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.