What is the essence of clean code?
When we hear the term “Clean Code”, we usually think about the well-known book that was written by Robert C. Martin (also known as Uncle Bob):
“Clean Code: A Handbook of Agile Software Craftsmanship” (2009)
Ever since this book was published, the term “Clean Code” has become increasingly popular. Today, its meaning is strongly influenced by Uncle Bob's vision, but this does not mean that the term was never used before the book came out.
In my opinion, developers did use the term "Clean Code" before the book was published. And I also believe that developers naturally related the term to code that is easy to read and maintain.
Readability and maintainability are desirable properties of software; however, they do not give us a profound and unambiguous picture of what clean code really is. This is why I want to dig deeper. I want to discuss the essence of clean code beyond its basic properties of readability and maintainability.
If you look at a deeper level, you will see that clean code is subjective. For example, you can consider a fragment of C++ code as unreadable because you are not familiar with the syntax, but experienced C++ programmers may disagree.
Uncle Bob recognizes the subjectivity of clean code in his book:
“There are probably as many definitions as there are programmers“.
This statement sparked my interest in writing this blog post. I want to share what clean code means to me. I want to answer the question “What is the essence of clean code?” even if there are plenty of experts that have already answered the question much better than I will ever do.
1. Clean code reads like a good novel.
When code is clean, you should be able to sit in a comfortable couch, by the fire, with a good drink and dim lights to enjoy the code like you would enjoy your favorite novel.
You might think this is an exaggeration, and you would be right, but to a lesser extent than you may imagine. Reading clean code should definitely be enjoyable, because names are intent-revealing and tell you a story; because the flow is trivial; because statements are so straightforward that they glide through your eye; because the amount of gray cells that you have to engage is comfortably low.
Clean code tells you a story that is captivating and easy to follow.
2. Clean code is simple.
Clean code is so simple that it does not make the author look smart. And yet, it is obvious that the code was written by someone who put effort in it.
Because simple is not easy.
You don’t achieve simplicity on your first try. First, you make the code work, ignoring best practices if necessary. Then, you refactor so that the code is readable and maintainable.
First, you make it work. Then, you make it right ~ Kent Beck.
3. Clean code is tested.
A corollary of the previous section is that you can’t write clean code without refactoring. And, to refactor successfully, you need automated tests to guarantee that behavior does not change. Therefore, you need tests to write clean code.
Furthermore, automated tests are the way code remains clean.
It does not matter how clean the code is today. If it has no tests, you can't refactor confidently. Therefore, the code will become unclean because code tends to get more convoluted and coupled over time.
Refactoring and testing help you counteract this tendency.
The natural tendency of code is not towards cleanness. It is the opposite. Counteracting this tendency requires explicit action.
4. Clean code is focused.
Clean code does one thing and it does it well, in a few words.
The writer does not overload the reader with unnecessary details. The intent is clear. There are no ambiguities. It doesn't have surprises and unintended side effects.
If you call "isPrinterReady”, you know the function will only check if the printer is ready. It will not inadvertently remove a file.
Clean code does what it says, without unexpected twists.
5. Clean code does not repeat itself.
Clean code says everything once.
This does not mean that duplication is eliminated blindly. Clean code avoids premature abstractions and it knows that, if two identical pieces of code represent different knowledge, removing duplication introduces risk.
Clean code follows the DRY principle, but it acknowledges that DRY is about knowledge duplication, not code.
6. Clean code speaks about the problem, not the solution.
If a name in your code includes a “computerish” term (such as “DTO”), it is probably focusing on “how”.
Clean code focuses on “what”.
Clean code uses terms that focus on the problem domain, not on the specific solution on a computer.
And these terms are at the right level of abstraction. If a software module is in the domain layer, the code will use terms of the domain model. If a module is in the database layer, it will speak about databases.
Clean code uses the right level of abstraction to talk about the problem being solved.
7. Clean code pays close attention to details.
When you write clean code, you get details right and you do not make arbitrary decisions. If you declare a protected field, you know why you don't declare it private. If you declare a dynamic array, you know why a static array would not be better. Every detail counts.
In clean code, error codes and exceptions are meaningful; error handling is explicit; names are consistent; there are no memory leaks; etc.
In software development, details matter. Clean code recognizes this truth.
8. Clean code does not smell.
When you see code that smells bad, it is probably wise to refactor because design smells are often symptoms of deep quality problems.
Clean code does not smell, or, if it does, the odor is weak.
- Clean code is not rigid. It is easy to change.
- Clean code is not immobile. You can reuse it easily.
- Clean code is not opaque. The intent is easy to understand.
- Clean code is not fragile. You can change it without introducing errors.
If it stinks, change it ~ Kent Beck.
After (hopefully) getting a deeper understanding of what clean code is, you may be wondering: why would I want to write clean code?
The main reason for me is that code is read far more times than it is written. Therefore, it is inefficient to favor solutions that make writing fast at the expense of making reading slow.
For example, it may be tempting to add a method to an interface only because you need to call the method and you hold a reference to the interface, but this can make the interface less cohesive and harder to understand.
Always consider the consequences of your actions. Do not take steps back in your journey towards clean code.
The only way to go fast is to go well ~ Uncle Bob.
My humble advice for software companies:
Stop looking for experts in paint brushes and focus your efforts on finding good artists. Focus your efforts on finding software engineers that can write clean code. This is how you go fast and at a sustainable pace. You must pay attention to technical excellence if you want to be agile. You can't be agile if you write dirty code.
Excellent article. I was reading about clean code and this post is just perfect to understand the essence of clean code. Thanks for sharing.
These 8 tips will be my new checklist!
Hopefully companies will start looking for clean coders and not 'paint brushers'
Great post! Just wanted to share a couple of war stories from the field. I think it was Rich Hickey who said:
Clean code to whom?
I had the fortunate opportunity to work with a very, very accomplished functional programmer at my last company. He wrote extremely clean code following all the best practices and patterns from functional programming. Unfortunately, after he left my team, which was an FP team, he went to an OO team and continued writing FP. Needless to say, even though it was technically clean code, the rest of the team couldn't read it. He was let go because of the frustration he caused his team. A huge loss to the company - the irony is that company is now switching over to FP, but have no leadership to guide them.
Programming is a human endeavor, so I think we should strive to use the same communication tools as those around us. So if a team doesn't follow best practices, as long as the code is consistent, it's clean code for that team.
I met an architect that worked for a very, very large multinational software development shop. The software that they were working on raked in millions of dollars a month on licensing fees, but the entire code base was copy-n-pasted.
When he joined, he was shocked and promptly started getting a team together to refactor the code to keep it DRY. After a few months and several hundred thousand dollars later, he had only refactored a small piece. He realized that even though there were no clean code practices, the company could easily hire a junior or off-shore contractor to copy-n-paste code than spending money to refactor.
That was the moment he realized he need to quit. Clean code or not, if the business pays the bills, then you're at their mercy.
Thanks for your detailed comment!
You make a great point about the importance of the team. I think it aligns very well with my example about C++ syntax. Our background exerts a strong influence on whether a piece of code is readable for us or not. That's why, when we write, we should definitely take our audience into consideration.
Mario Cervera I always struggle with this. Especially in consulting where the client usually ends up giving the code base to juniors for maintenance. (Maybe this is a good blog post for the future? :D)
I find it really hard to decide when or when not to use a pattern as the patterns used by the team today might not be understood by the team tomorrow... but maybe this is just a reality of consulting vs product companies.