
“Clean code” isn't actually clean - _ncxu
https://sdegutis.com/blog/2017-08-28-clean-code-isnt-actually-clean/
======
FrankyHollywood
Most guru's take an 'all or nothing' approach, this goes beyond programming,
look at food-guru's "eat only carbs, never eat refined sugar" etc. This is for
me the same as "always do TDD, never use static methods".

People without experience often look at guru's because they can not yet think
for themselves.

I'm a developer in my 40s, have done a lot of projects in a lot of different
companies. Having this experience gives me intuition about what to do in what
situation. I just (think I) know when I should write a unit test and when not.

The 'all or nothing' attitude is created by people who want to be guru's and
is followed by people who want to have some guidance.

This is not a bad thing, it takes time to shape yourself as a programmer. This
takes years:
[http://www.norvig.com/21-days.html](http://www.norvig.com/21-days.html)

Learn from the guru's, and be consious, people preaching an 'all or nothing'
view of the world are NEVER right :)

~~~
kristianp
Please, it's just "gurus", no apostrophe needed.

~~~
asp_hornet
its not plural, its possessive so apostrophe needed.

------
flohofwoe
IME the 'best' code solves an existing problem with the least amount of code,
is human-readable, and easy to throw away (instead of being 'future proof').

Of course this 'easy to throw away' will also lead to a slow replacement
process of 'good code' (that's easy to replace) with new 'bad code' (that's
incrementally harder to replace) and eventually each software project will end
up in the same broken mess, no matter how well it started ;)

~~~
pul
Replace `least amount of code` with `least amount of complexity` and I
completely agree!

~~~
danielbarla
This has been my "go-to" definition for a while, though I'd add a caveat:
complexity can be subjective, based on the reader's particular experience or
background.

~~~
manmal
Whenever I use FRP, I'm worried that the code is super maintainable and
readable for me, but a hell for a less experienced coder.

------
gfiorav
This just seems like poor justification for laziness.

You need to keep a project clean. This means profound refactors when concepts
for the product change. Some rules are:

\- Keep it readable

\- Don't over engineering

\- Easy to remove

\- Good tests (complete, min stubbing, interface oriented. Never refactor and
change tests at the same time.

A lot of "veterans" are just resented with new paradigms and too egotistical
to stay relevant. It takes effort to maintain a clean project, many will try
to say "it's not worth it". That's just out of the question, it's your job, it
doesn't have to be always pleasant or easy. If you don't suffer for it a bit
now, someone else will in the future (maybe clients or users).

This is what I like about open source projects, it teaches maintaince
discipline. In the end, you can sum up all rules into one:

\- Make it easy to maintain

~~~
koonsolo
> A lot of "veterans" are just resented with new paradigms and too egotistical
> to stay relevant.

Sometimes, your new paradigm is actually something that they tried 10 years
ago.

> In the end, you can sum up all rules into one: Make it easy to maintain

That is only one of the many facets of programming that you have to balance:
performance, memory consumption, ... .

If you want to push your system performance to the extreme, believe me, "easy
to maintain" is not going to happen. But that is the trade-off that you will
have to make at that point.

Veterans know that everything is a trade-off.

Let me give you one extreme: you are writing a throw away prototype. How much
time and effort are you going to spend (=waste) on making your code easy to
maintain?

I'll give you my veteran answer:

\- If you are in 100% control of the project, you know you will throw away the
prototype, and you can throw things quickly together.

\- If you have a manager, he will take 1 look at the prototype and say "Wow,
it's almost complete! Don't start a new project, just add these features to
your prototype and it's done.". So in that case, make the "throw away
prototype" easy to maintain.

That is what veterans bring to the table: making trade-offs in specific
situations. And they've been through a lot of situations.

~~~
gfiorav
Good points. For the record: I'm not saying all veterans are egotistical.

I think code based performance is something that is just not as big as an
issue as before. In web world it's common to solve extreme performance via
cache, replication, etc.

In any case, I think that in very few cases you get to a performance
requirement so intense that you can't write maintainable code. We can't argue
on extremes :)

------
jack9
So no data, no examples, no anything. Full of such wisdom as "Testing isn't as
important as it might seem but it's still important"

The only thing actually articulated was "you don't need 100% test coverage",
which is not contrary to existing practice (afaik). I'm not sure the singular
point nested in platitudes can be useful to me.

~~~
blub
A lot of software engineering practices lean towards tribal wisdom instead of
being evidence-based.

The only resource I know of that provides citations to studies is Code
Complete by McConnell. But having data is no guarantee of correctness.
Bossavit debunks some SWE common sense in "The leprechauns of software
engineering", including the cone of uncertainty which is referenced by
McConnell.

I'm also planning on reading SW engineering best practices by Capers Jones,
which is likewise based on data, not anecdotes.

~~~
jack9
Shouldn't everyone demand more before promoting ideas without any basis?
([https://vimeo.com/9270320](https://vimeo.com/9270320))

Even if it is just "tribal wisdom", is HN where you recruit a tribe from a
vapor posting? I would hope you at least have a tribe before upvoting it up
the pile. It feels like it's being promoted for no reason or through a
backchannel.

It didn't even give a wiki link to the Chesterton's fence analogy. Sigh.

------
BigJono
On my side projects at home, I can't even remember the last time I had to slow
down or got stuck on maintenance/integration type stuff (as opposed to new
functionality or algorithms, which don't rely on existing code). And I have a
couple of fairly big ones, it's not all "Todo list" stuff.

It's happened constantly at work though, throughout multiple jobs. Sometimes
I've been so stuck I've got basically nothing done for days or weeks at a
time. Sometimes that happens a few times in a row and I feel like I'm an inch
away from being fired for incompetence. This even happens on relatively small
projects. It's not confined to big 10 year old monstrosities.

The sad thing is, I work for startups, which should be all about lean, clean
code and making big changes rapidly to respond to business needs.

I think a lot of it comes down to how hard it is to work on other's code. I
don't think any of the conventional wisdom is a solution to this problem
either. I haven't noticed any discernable difference between projects with big
fuck off linters, or 50 page style guides. It's not a mish mash of semi-colons
that's causing trouble (although consistency is nice).

"Dirty code" is really the crux of the problem. But like the author of this
article, I don't always agree with what the conventional wisdom says about
writing clean code.

To me, the most important part of keeping your code clean is always having the
minimal solution to the problem. Your code shouldn't do one thing extra it
doesn't need to. Half of this is YAGNI, half of it is being a good enough
developer to come up with simple solutions that aren't too fancy.

On that note, don't get too fancy, and don't take DRY too seriously. Whatever
complicated mess of higher order functions you're writing probably isn't going
to phase other experienced devs in a vacuum, but combined with all the other
icky parts of the code base and it might just be the straw that breaks the
camel's back. If you need to write twice as many lines to make it more
grokable, that's fine.

Speaking of YAGNI, people should be applying it somewhat to dependencies as
well as functionality. It's just far too easy for a simple React project to
blow out in complexity because of an over-reliance on other's code. Sometimes
it's easier to build something out of code than NPM Lego.

~~~
bfred_it
I like NPM Lego a lot, especially if the legos are tiny and (battle-)tested.

At the same time if I can replicate the gist of lodash.omit in 5 lines I will.

------
raverbashing
Criticizing code for not being "clean code" is 70% of the time "I don't like
this code for various reasons"

Not to mention of the pedantism of one of the biggest proponents of clean
code.

So, in essence, worry that your code has a certain quality but in the end all
projects will end up in the trash can. It's software, not the Mona Lisa.

------
darawk
I think the problem here is that 'clean' is an umbrella term for a bunch of
different things. To sum them it is: 'how does this code make me feel inside'.
But what goes into that are: readability, extensibility, maintainability,
testability, clarity, correctness, simplicity, and yes, aesthetics. Some of
these are _objectively_ always good, and some of them are contingently good.

For instance, a simple algorithm for distributed consensus is probably not
correct, and you should rightly not view it as 'clean'. Some things simply
aren't simple. The goodness of simplicity is contingent on the complexity of
the problem.

But aesthetics is at the final end of the spectrum: it's purely subjective.
And yet we wrap all these things up under the term 'clean', and so it is
confusing. People will defend their notion of cleanliness using the objective
standards, and then apply it to the subjective cases.

------
panic
Given how young the practice of programming is, I doubt anyone alive today
knows how to write truly good code. Just look at the kind of code people used
to write 30 or so years ago. It's interesting to think about: what will "clean
code" look like in 2047?

~~~
taeric
This seems to couch the idea that older professions finally "understand it."
Look at the houses people made 40 or so years ago. We now have to have
disclaimers indicating that the materials they used were... not so wise to be
used.

Go back further, suddenly you will be left with basically nothing but survivor
bias. It will seem like they had it together, but it is just as likely they
did not. Pull it in some and you get the hastily built houses that seemed to
fall apart way too easily.

I feel like this can go with software. It is actually trivial to find software
that is still is use from the 80s. Older fortran code still exists. It is far
harder to find any lessons in those software packages. Even when I desperately
want to.

~~~
panic
Sure, but we've been building houses for a long time. We know a lot more about
building houses today (or even 40 years ago) than they did when the practice
of house-building was still relatively new. And most of this knowledge didn't
come from building houses over and over, but from developing better theories
of how buildings stay up, using better materials, etc....

~~~
taeric
I think we'd both be surprised on how much actually does come from "building
houses over and over." My assertion being that much of material science
advancement came from required advancements from previous failed houses.

~~~
penpapersw
That's my same experience with programming. That's kind of what I was getting
at in this article actually: that you get better by doing your best and making
mistakes. Nothing beats hard-earned experience.

~~~
taeric
Completely agreed. It is good to learn from the mistakes of others, though.

To that end, it is good to have exposure to a lot of things that have failed.
Seeing how they succeeded isn't as instructive, interestingly.

------
aidenn0
RE: Automated testing.

Modulo certain forms of static analysis, your code is ultimately only as good
as it is well tested[1]. Non-automated tests do count here, but for long-
maintained codebases the cost of automating pays for itself very quickly.

1: Note that pretty much all code has been informally integration tested (A
"can I run it" type of smoke-test is a very simple integration test).
Similarly all compiled languages (and any interpreted languages that parse an
entire file before running code) has _some_ static analysis, as syntax errors
will be caught. Unless you check in code without compiling or running it, you
are already doing some testing.

------
devnonymous
I don't understand the negativity in the top voted comments here! It's almost
as though I read a completely different article than the one being commented
on.

The comments here are being dismissive and then reiterating what the post
said! Here's the summary from the post :

> So I stopped worrying about whether my code is perfect. And I just accepted
> that if I can't see any immediate flaws with the code, and if all the tests
> pass (whether automated or manual), then it's fine. And I trusted that if I
> ever come across a bug, I can fix it.

Why, specifically, is that a bad thing?

------
flor1s
I love the story about a group of American car manufacturer executives
visiting factories of Japanese car manufacturers in the 80's. After returning
to the US they were asked about their visit and they remarked that the
Japanese did not show them their real factories, as the Japanese factories
were too clean according to the American executives. As it turns out, a clean
work environment (and that includes source code) has benefits if you are doing
logical work.

------
AstralStorm
Sometimes the warts are just warts and mistakes, sometimes there is a deep
undocumented reason for it. Which indicates a problem as reasons like that
should be explicitly documented.

And yes, often clean code actually is finished. Mess is often produced by
wrong architecture or rushed development which means not finished if
maintainability is in your definition of code being done. What the author
probably meant is concise code instead.

------
chris_wot
There is something really cool about looking at a large enough codebase, and
just _reading_ it. Then when you absorb it, then you might see a way to
refactor it. I did this with the error handling code in the VCL module of
LibreOffice. Frankly, I just did some renaming and a small bit of logic
changes, but it just made the code far easier to understand and work with.

------
hasenj
Promising title, but not enough content.

------
arkh
Shitty documented code beats clean undocumented code for maintenance. Maybe we
need more "how to document my codebase" tutorials than "how to reinvent the
wheel in this shinny new language" ones.

------
dovdovdov
Attended a couple of clean code trainings, always wrote the shittiest code for
a week or two afterwards. ¯\\_(ツ)_/¯

~~~
davnicwil
Do you have examples of things you learned on the courses that you thought
made your code more difficult to understand and modify?

After that, did you completely switch back to the code style you were using
before the courses? Did you cherry pick some things and not others?

Just to make my view plain, for me 'clean code' was the most important book
I've read in my career, and what I learned from it has (in my view) massively
positively influenced the quality of my code over the years. I'm really
interested in getting an opposing viewpoint. At the end of the day I'm aiming
for my code to be understandable and maintainable by other people as much as
myself.

~~~
Ao7bei3s
I agree, Clean Code was the most important book for me too. But I wouldn't
follow it blindly. Also, it's less useful for non-Java and much less useful
for non-OOP languages (it's ok to have a focus, but one has to keep in mind
that sometimes, certain idioms, best practices or design patterns are actually
workarounds around the limitations of Java).

My favorite example: Overdoing the short functions thing. I've seen this a
lot. Unsurprisingly, considering that for most devs, when you ask them what
makes good code, "short functions" seems to be the first thing that comes to
mind.

Splitting code into extremely short functions has a few disadvantages too: a)
in what order they're called is not immediately clear, b) where they can be
called from is not immediately clear, c) going up/down the stack can make it
harder to follow when debugging interactively. d) It increases the LOC and
noise. And e) especially in OOP languages, short methods make it more tempting
to turn variables into attributes to avoid passing them around explicitly (bad
due to longer lifetime).

Splitting functions should only be done if it makes sense semantically. Each
function should make sense on its own. If some logic is highly cohesive (e.g.
because it implements a specific algorithm), not independently reusable, and
it's subblocks only make sense in one order, and it all fits on a few
screenfuls, it might make sense to keep it in one longer function instead of
dividing it into fairly arbitrary chunks.

~~~
davnicwil
I think the short functions thing is a funny one. The benefits of short
functions are definitely praised in the book, but they are really more of a
side effect of the real goal: to have pieces of logic that do one single thing
that can be summed up in a function name and understood as a clear input ->
output 'step' at the level of abstraction above, without having to dig in to
find out 'how it works' or understand any weird quirks / unexpected side
effects etc.

Usually, by their nature, such functions don't end up being very long. This is
great, but it remains just a nice side effect of the real goal, and one that
is not more important than the real goal. To artificially break up a slightly
longer function which is very focused in its behaviour, just for the sake of
line count, is probably a mistake.

To be honest, I can't remember how clearly the book makes this distinction, or
if it does at all, but I feel like it probably could be made clearer given how
common this misinterpretation is.

------
Izmaki
Essentially you are recommending that people slack off as soon as they face
trouble instead of spending time making sure they don't break stuff. Had you
mentioned Continuous Integration and many commits per hour I would agree that
tests and nurture is less important but you seem to base your thoughts on the
laziness of old people.

------
atdt
What's the fence story?

~~~
habitue
Chesterton's Fence:
[https://en.wikipedia.org/wiki/Wikipedia%3AChesterton%27s_fen...](https://en.wikipedia.org/wiki/Wikipedia%3AChesterton%27s_fence)

~~~
arkh
That's why you document why you do things some way and not how. So when the
why changes or disappear you can change things.

Same problem with rules. Document why they exist.

Simple coding example: the one exit rule. It exists to make easier the
resource management in a function. So it is useful in languages for which the
coder has to manage resources. For a scripting language or one where resources
are managed by the language? No. So there you can enjoy early returns.

------
nicky0
YAGNI?

~~~
relate
You Ain't Gonna Need It. (I think)

------
Walkman
This guy mix and match totally unrelated things.

\- clean != finished

\- clean != perfect

\- ugly is not clean

\- you can understand a code and find it still ugly

What is he actually talking about?

> Automated tests are not that important

I agree with the content of this section, but the title is bad.

