Clean Code: 5 Essential Takeaways
Key points from a must-read book for programmers
I recently wrote about “5 Books That Changed the Way I Code.” In the comments, several readers recommended “Clean Code” by Robert C. Martin. As a result, I’ve now read the book and found it worthy of an in-depth review.
About the Book
“Clean Code” was published in 2008, and over recent years, it has consistently ranked as one of the top five highest-selling books on Amazon. The author, affectionately known as “Uncle Bob,” was one of the original authors of the Agile Manifesto and has some serious credentials. The book has achieved an average rating of 4.4 on Goodreads from over 13,000 ratings. Suffice to say, it’s one of those books every programmer should read.
In this review, I’m going to condense the book into five essential takeaways.
1. Programming Is a Craft
I’ve often thought architecture and construction are poor metaphors for programming. We don’t create a full design, then build the foundations from the ground up, steadily progressing to the finished building.
Rather, we start with a sketch, iteratively adding details. We revise, refine, and extend — working at various levels of abstraction until the software does what we need. Software is never truly finished.
This very much the essence of “Clean Code.” Throughout the book, the author conveys the idea that software is an art and “a lot like painting a picture.” In essence, he believes programming is a craft.
But how do we go from simply writing code to crafting code?
According to Martin, the main tools we have at our disposal are continuous refactoring and test-driven development (TDD). These work together like two sides of a coin. Here are some definitions:
Refactoring is the process of restructuring existing computer code without changing its external behavior.
Test-driven development is a process where requirements are turned into specific test cases, then the code is added so the tests pass.
So, the process of crafting software might look something like this:
- Write failing tests that verify the required but unimplemented behaviour.
- Write some (potentially bad) code that works and makes those tests pass.
- Incrementally refactor the code, with the tests continuing to pass, making it more clean with each development iteration.
“It’s a myth that we can get systems ‘right the first time.’ Instead, we should implement only today’s stories, then refactor and expand the system to implement new stories tomorrow. This is the essence of iterative and incremental agility.”
— Robert C. Martin
Thus, a central idea presented by Martin is clean code is something that emerges through the process and practice of development, rather than being simply created in one pass.
2. Keep It Short!
“The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.” — Robert C. Martin
According to Martin this means two things:
- Function bodies should be short — hardly ever longer than 20 lines and mostly less than 10 lines
- Functions should take as few arguments as possible, preferably none
Function brevity makes code easier to read. It also steers us towards a situation where functions do one thing — and do it well.
He makes a similar point about classes. With classes, he suggests using responsibilities as the measure of size rather than lines of code. The idea is a class should only be responsible for one thing. This is known as the single responsibility principle (SRP).
Keeping entities short is a divide-and-conquer strategy for making code cleaner. If we have a big file with lots of lengthy, complicated code, we can divide that file into modules, divide the modules into functions, and divide functions into subfunctions until the logic and intent are clear.
3. Make Code Self-Documenting
“Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments.” — Robert C. Martin
In the sections on comments, meaningful names, and formatting, Martin makes a strong case for code being self-documenting. An example of this is given as follows:
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
This gets refactored to:
- The comment is removed
- The conditional logic is encapsulated into a method
- Because a method is used and not a free-standing function, instance variables can be used, creating a zero-argument method call
- The method is given a descriptive name, making its responsibility super clear
“Clean Code” includes a full chapter on naming, which is essentially an elaboration on Tim Ottinger’s rules. These include:
- Use intention-revealing names — e.g,
int elapsedTimeInDays, not
- Use pronounceable names — e.g.,
- Avoid encodings — don’t use an
m_prefix for members and don’t use Hungarian notation
- Pick one word per concept — don’t
getfor the same concept
4. Respect Abstraction
According to “Clean Code,” if we want to make sure our functions are only doing one thing, we need to make sure the statements within each function are all at the same level of abstraction.
Martin illustrates this with the following example from FitNesse:
This mixes at least two levels of abstraction. The first is the high-level concept of rendering an
hr tag with a given size, the second is dealing with the low-level syntax details of actually constructing the tag. To illustrate this, the code is refactored more cleanly, as follows:
render()function is now only responsible for constructing an
- The low-level details of constructing the tag are now delegated to the
- Size formatting is abstracted into a separate function
According to Martin:
“Separating levels of abstraction is one of the most important functions of refactoring, and one of the hardest to do well.”
This is certainly something I’ll be thinking about a lot more in my own code going forward.
5. Clean Code Is About Principles and Hard Work
I didn’t want this review to simply be a list of bullet points and aphorisms that forms rules we can just apply to get clean code. To do this would be a disservice to the book — since it’s a long way from having such a dogmatic approach itself.
Rather, I get the impression Martin is coaxing us into developing a strong sense of personal principles and continuously illustrating the effort and conscientiousness required to take code from being dirty to clean. The book refers to this as code-sense, something that requires the “disciplined use of a myriad little techniques applied through a painstakingly acquired sense of cleanliness.”
“Clean code is not written by following a set of rules. You don’t become a software craftsman by learning a list of heuristics. Professionalism and craftsmanship come from values that drive disciplines.” — Robert C. Martin
Personally, as someone who suffers from a lack of confidence, I very much welcomed this emphasis. It’s nice to know even Uncle Bob firmly believes coding is hard and requires serious work and discipline. To truly become good at writing clean code, we need to iterate on our personal development as programmers, as well as the development of our code.
Not every idea in “Clean Code” was originated by Uncle Bob, and he openly acknowledges this at various points in the book. If anything, this is one of the things that makes the book so successful — it’s a distillation of wisdom from various parts of the programming community, fleshed out with practical examples.
If I have one minor criticism, it’s that the balance between chapters about details is slightly off compared to chapters about higher-level concepts. The systems chapter gets only 13 pages, nearly half the space dedicated to comments. However, I suspect the reasoning for placing less emphasis on systems was to save this discussion for his later book “Clean Architecture,” which will be on my reading list for 2021. Aside from that, this is one of the best programming books out there.