I was thrown in a project, that was a big mess. They told me the guy who built it was a pro, but it was created under extreme time pressure that's why it's just a bit messy.
I didn't believe that.
I thought: "the guy who build it was an idiot". Functions were all over the place, there was no logical grouping of code and naming was terrible. Yes, naming is hard, but these function names not even came close to what the code was doing...
I thought - clean code is important. I liked the way clean code looked. Small and concise functions. Short names. Comments above functions that had a box of dashes around them to make them more visible. Beautiful.
Different story:
A while ago I have been working with a clean coder on a different project.
He kept pushing back the releases. "I need to refactor that first", "Before the next ticket I need to do 1 week of cleanup", "man, I just spend the full day splitting a 5000 lines file"...
He was very serious about this. And he was doing decent work, but as humans do, he also made mistakes, and his 5000 line refactorings lead to new bugs that needed to be fixed and required another refactoring.
Every time I mention clean code in a blog post i get a few comments why it's so important and how everyone should adhere to the holy bible of coding guidelines.
"Take your time to clean up.", "Leave the code in better shape than you found it.", they said.
It reminds me of the whole inbox zero debate. Imagine a mailbox, that is empty. Beautiful. It takes some housekeeping effort, but man look at this beautiful emptiness.
After all, isn’t this the same as keeping your house clean? No one wants trash to pile up in the house. Keep the house clean - keep the desk clean - keep the inbox clean - write clean code?
After taking a vacation my inbox was flooded again. You have to have a close eye on your inbox every day and you better react quickly if you don’t want that mf to fill up again. It’s a little bit of housekeeping, but doing that shit everyday piles up and then it becomes a lot of housekeeping. And it’s annoying, and it stressed me out having to keep the inbox clean.
Tim Ferris' 4 hour work week got me back on my feet. One core idea from the book: We are wasting 80% of our time with nonsense (Paretos law). Emptying your inbox is procrastination. Writing dashes around code comments is procrastination. Every second you deal with a spam email is a waste. It is easy and everyone can do it. There is this quote from the book which is something like: "Am I inventing things to do in order to avoid what's important?".
At some point I just had too much on my plate to deal with all that crap. And I gave up and let my inbox fill. It itches, but I felt relieved at the same time. I let go. I just let go. Mails kept coming in and I did not care anymore.
And guess what - you get used to it.
And you get good at search.
And filtering.
And skimming headlines fast.
And reading ugly code.
And navigating messy codebases.
And every now and then you miss something.
And you need to accept that.
And then a reminder comes in and then you deal with it.
The first version of your code needs to be messy. Then, after using it for a few weeks or months, you realize the flaws. And when you need to extend functionality, you fix it. You fix what’s important. If you never touch it again, you leave it messy.
I’m not saying: „be an idiot to your coworkers“. Don’t produce something messy for the sake of being messy. Just stop painting and focus on what’s important.
The difference between a messy house and a messy codebase is, that in coding we have the tools to navigating it.
Don’t try to refactor a 5000 line file in one go. It takes forever and you will make mistakes. It’s a form of procrastination.
Fix naming that’s off when you work with the function. Rewrite a function if you fix a bug with it.
Fix what causes headaches.
Tiny improvements - smaller commits.
Leave the code better than you found it.
Top comments (32)
Interesting thoughts, and I agree on some level, but it's a balance.
I try to write clean code from the start, but I don't force it, because sometimes you just need to write something down in order to really understand the solution needed. Local messiness is ok in that case, and as soon as I know it works I clean it up: refactor parts to other functions, move functions together that belong together, refactor functions to a class so that I don't have to pass the main object that is "now" clearly being passed around all over the place, use AI to add type annotations and tell me if there are obvious bugs.
What I mean by local messiness is that on new code, I don't let the whole code get messy, as soon as a function is "figured out", I clean it up. As soon as I see that several functions make sense to move into a class, i do it.
I don't obsess, but as a tech lead I lead by example and I can't ask others to produce decently clean code if I don't.
I write code assuming that in 6 months it'll either have to be understood by my colleagues or re-understood by me. And since at that point I will likely need just a fix, I really don't want to be thinking, "oh gosh this is so messy I really need to refactor as part of this fix", I want to minimize how much of that I need to do so I don't introduce new bug.
I have to say, here is a very good filter to ask at your next interview: do you have refactoring tickets, how often? If the answer is that they don't, they only refactor as part of fixes or "when they have time" (read never because when is there nothing to deliver), then they are not a team I'm interested in. Unless of course they say "we really need someone to help us get better at that".
Anyways thanks for a nice article.
Yeah, it's always a balance. And as soon as you can tell something is completely "figured out" you can do your best to keep it somewhat clean to a degree that makes sense. In my experience it often takes a field test first in order to know when new code is "figured out", especially on more complicated problems. And having that expectation in mind, I lean more towards: get the first draft to field test as fast as possible, then work with what's coming back and fix or refactor if necessary.
What I learned working at a company where we maintain about 200 repos, some are decades old and some were created literally last week:
Too many people passed through this codebase. Each coded in their own way in the past. There were no guidelines. Even the language chosen for the code sometimes is different as we are in Brazil, but some people insist coding in English (even though some don't understand English very well and make mistakes)
Since the pandemic, when we had a sudden boom in repo creation for obvious reasons, we defined internal guidelines and put some order in the chaos. One of them is regarding clean code.
But when you have tens of devs it's still quite difficult to keep it tidy. We then introduced code review to try help with it. The code review regarding clean code was more of a means to educate the dev on how they could have done something better than asking them to change their structure, but they are free to refactor it if they have the time. Over time it made the overall code much better.
Some devs love refactoring like you said. There will always be this one guy who will refactor 5k lines of other people's code before he can start his own task, which can lead to bugs in portions of the code that aren't going to be tested. We don't encourage this sort of thing.
What we tell them is if they are not familiar with one specific repo, they take a look into its structure. If it's the familiar structure we defined, do it according the guidelines. If it's not, try to infer the overall structure it was written on, taking examples on similar functionality that's already there if possible. If it's in English, keep writing in English. If it's in Portuguese, write it in Portuguese.
We don't always have time for refactorings. But when we do, it's usually targeted at those older legacy projects that are on a different stack we currently work on. Many of the new "last week" creations are there to substitute the decades old code that became really difficult to upgrade for security reasons and are still open to be used outside the intranet. These are treated as fully new code and have specialised teams working on them.
The idea is that if the code you were told to work on is an old mess, you shouldn't stress out about refactoring the chaos.
Seems reasonable!
If some legacy project don't try at least using clean code then it is a good indicator of death trap job. I am wrorking one of that. ... at least this job cannot steal any AI.
Yeah, even AI refuses to do that - it's too dangerous! 😃
Totally agree, follow the flow however have your body/heart/mind align and focus on what's important, that's the key.
Finding your inner balance will make your code more balanced and you will find true long lasting happiness 🧘♂️
Yeah, I really feel this - sometimes you just gotta push forward and not let all the code-polishing slow you down.
It sounds like you haven't read Clean Code. In the book it says that code should as far as is practicable be self-commenting and hence comments should not be needed in the majority of cases.
Also nowhere does it mention such fripperies as dashes around comments.
I get the email thing (who would not want an empty inbox?) but it's a poor analogy as your inbox tidiness largely affects only you.
@j_j_b77c6f60020810c325308 I do agree on some level. But I think you might be missing a bit the point here. What the author is emphesising here is, your job is to fix a business problem and you should do that first.
To put things in perspective, I will share an experience I had while interviewing with Sonar Source, this is the company that ships SonarQube. They are like disuples of the clean code bible. When I was interviewing with them i was tasked with a live coding challange and the interviewer strictly suggested, that I get it working first then clean it up.
In short it is better to have an ugly solution in the end than a clean unsolved problem.
100% agree!
I don't believe in 100% self commenting code, some things just need explanation - especially to give background on workarounds.
And yes, dashes around comments are not mentioned anywhere, but I still see people do it from time to time and I think it's a form of avoiding more important problems - and so is fanatical cleaning your inbox everyday.
The only place I usually add comments is documentation of public methods. These are frequently more complex than just a "title" can be. I can't know just from the name what's the difference between
StringUtils.isEmpty()
andStringUtils.isBlank()
from Apache commons. I need some documentation. But a private method doing a very limited set of actions can much more easily be readable just from the name given it's only being used in that limited context.I often leave comments to explain why I chose a certain implementation that is not obvious - something like: „ I already tried x y and z but because x I had to do z.“ Stuff like this should be inline in my opinion, I’m a big believer of adding documentation where it is used.
Agree. Code explains 'what' but not 'why'. That can only be done with comments.
Great article and I can totally relate. There's no doubt that "Clean Code" is more often overused than underused. I've see projects with a few simple CRUD operations done with "Clean Code" standards without any reason whatsoever. Ironically, you can make your code messier with "Clean Code" standards when used inappropriately.
Many developers are obsessed with abstracting things by default, creating more problems than they solve.
YES, I agree. I have never understood how someone can refactor a codebase into 3x the code and just think it is easier to manage. It is as if the refactoring itself guarantees that next time, a small addition is needed, it will also be a small amount of work. Many times, you end up editing way more code than if you had not refactored. It is more complicated than it looks to identify the parts that will change and thus be refactored so that additions will be easy.
I have often seen a refactor that just refactors into a domain model without regard for what will come. One domain model might fit the original problem, but not the purpose of the code. A domain model has to be part of the purpose, not the goal itself. Just because you derive a domain model from the data structures moving around the code, does not mean that enforcing a domain model will make the code more maintainable. You might get a better narrative around the code when you talk about business logic, but maintainability is not guaranteed.
Totally true. I’ve worked on a “clean” codebase written by “super developers” that was so unnecessarily complex that even addition of a one tiny CRUD operation would take me almost an hour. It could’ve been a 15 minute job at most if written in a simpler way.
Did the author really “let go” of Clean Code?
The title at least claims so. Somewhere at the first paragraphs we read
And the piece ends with:
I'm left with the impression that the only things the author really have 'let go' of are Inbox Zero and maybe the word 'shape': which is totally fine, but not exactly the revelation I expected.
Respectfully, the author doesn’t appear to have rejected Clean Code at all. What they’ve realized is that it shouldn't be followed above all else. And that’s fair. Context matters. Tradeoffs exist.
And rules sometimes need to be bent, broken, or reimagined, in order for us, engineers, makers, to really come up with something new.
There shouldn't be any 'absolutes'; not, at least, in creative work, like ours should be...
But the subtle glorification of “productivity at all costs” goes again into that somewhat misguided direction... As if procrastination is inherently bad - and not, also, something that can give us the break we sometimes need to proceed.
It’s a balance - don’t produce garbage, but don’t starting painting either...
Regarding the whole productivity thing, I think I could come up with more effective strategies for recovery than refactoring - this is of course subjective😃
That's a very clever approach (not because I also do the same), because it shows the evolution of the project, the HOW it flaws. If you feel you can't find something important, refactor this exact part. Clean code is not just a set of rules, this is a philosophy of code which is easy to refactor and extend
I think it is essential for us as developers to practice clean coding for future readability and better maintenance. However, as time-consuming as it can be, we must embrace the utilisation of AI tools to help us maintain the code structure more efficiently. I still advocate to write code manually in our first try, but we can utilise prompt coding to ask for a better way how to optimise the earlier version of our code. For example, asking CoPilot "how would you suggest this part of code to be more efficient" can give us an insight the overlooked mistake we did during our first writing to avoid the similar mistake in the future.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.