This article was originally published on Books on Code.
Not many books can be considered classics in the programming community. Programmings books too easily become out of date. In order for a programming book to be a classic, it must share all-around good wisdom rooted in good principles.
Clean Code is certainly one of these rare classics. When I asked my readers what programming book they can't live without, this book topped the list along with The Pragmatic Programmer.
For being published over a decade ago, which is a lifetime in the tech world, the book has Java examples that are beginning to date. Long-time fans are now likely hoping for a fresh coat of paint soon.
But even with this small fallback, Clean Code is the current Amazon #1 bestseller for the "software testing" category.
Why does Clean Code continue to have such an impact on readers a decade after its publication?
Programmers self-report having a coding awakening after reading the book. They are profoundly changed. Their entire philosophy about code, and therefore about their careers, gets a radical shift.
Programmers who have coded for decades discover this book and deeply regret all the years they went without this book's teachings. That's how powerful this book is.
Those who have had their code philosophy transformed wear this book like a badge of honor, reading it every year to stay fresh and to spread the word of Clean Code.
So if, like me, you are wondering what all of this is about, I have a fresh copy of Clean Code in front of me and we're about to walk through it together, key point by key point.
Let's get ready to embark on the clean-code mindset shift and share the greatest takeaways together.
The following sections are key takeaways I had reading Clean Code for the first time.
Clean your code with soap and water every day. It's your responsibility.
You are reading this book for two reasons. First, you are a programmers. Second, you want to be a better programmer. Good. We need better programmers.
This is a book about good programming. It is filled with code. We are going to look at code from every different direction. We'll look down at it from the top, up at it from the bottom, and through it from the inside out. By the time we are done, we're going to know a lot about code. What's more, we'll be able to tell the difference between good code and bad code.
--- Clean Code
Code represents the "details of the requirement." Code itself is a small, essential piece that makes up the whole. We cannot abstract away code, just like I can't abstract away the individual words and sentences in this article. Code itself is essential to programming.
By talking about abstraction in the opening pages of Clean Code, we immediately launch into the philosophy of code that we adopt for the whole book.
The book gives its first warning: we should not worship abstractions and respect foundations.
The book goes on to say that bad code has been the culprit in dismantling whole companies. Debt builds and builds. Features pile and pile. Sooner or later, the whole foundation crumbles and the company folds.
Bad code is behind major slow down after a big spike in productivity with a fresh codebase. The build slows and slows so that changes that should take hours instead take weeks.
But for many codebases, the mess prevails!
Clean Code then shares something that is the beginning of the code indoctrination: it's your fault. Programmers must take responsibility for the code. Why? Well, who else actually knows the code and can speak on behalf of it?
And while managers can seem scary, they honestly want the truth. But just as a part of being human, it's too easy to be agreeable, to divert blame, and to let bad situations happen.
As an employee at a software company myself, I know how it feels to divert blame because I have done it and have seen others do the same without realizing it. It takes courage to take responsibility and to do the right thing and to not naturally spot scapegoats.
Taking responsibility is a powerful skill and it can turn a fine programming into a truly good programmer. That is, if they have the ability to turn mess into clean code. The book calls this ability "code-sense."
Clean Code likens "code-sense" to any art in the sense that it can't be taught but guided and nurtured. The book itself claims to give rules that are not an absolute principle, but absolute in the sense that we create rules around sports. The 'rules' are law within the discipline, although they may not speak an absolute, universal truth.
On a name tag, I write just "Miranda." My intention is for people to call me by name. What if I were to write something funny there instead?
The hardest thing about choosing good names is that it requires good descriptive skills and a shared cultural background. this is a teaching issue rather than a technical, business, or management issue. As a result many people in this field don't learn to do it very well.
--- Clean Code
Alright. So we're in the meat of the book now (and also in the meat of code). We're talking about names now: variable names, function names, argument names, class names, file names, package names, and all of the names.
So what's in a name? You know, to make it "smell as sweet"?
Here's a quick summary of the basic tips:
Use intention-revealing names: The name should answer big questions like why it exists, what it does, and how it is used.
Avoid disinformation: The name should not leave false clues. For example, an object with
Listin the name, when it is not itself a list, is disinformation. Even if "list" has some semblance of truth, our technical understanding of "list" makes anything other than a "list" data structure disinformation.
Make meaningful distinctions: An example of poor naming is
a2for argument names instead of simply distinguishing them with meaningful names.
Use pronounceable names: Clean Code argues that as humans, our brains have evolved to deal with the spoken language and therefore pronounceable names are just aesthetically nice and easier to talk about with colleagues.
Use searchable names: This is a dis on single-letter names like
e. When we're searching through a codebase, having some intuition about where to find code would be nice.
Avoid encodings: Encodings in names create the problem of requiring anyone reading the code to have additional context.
Avoid mental mapping: No mentally translating names into other names. In other words, no being smart about names. Just say it straight.
Class names: Class names should have a noun phrase. No verbs. Save those for methods.
Method names: Methods should have a verb phrase. No nouns. Save those for classes.
Don't be cute: And don't be funny. Don't name a function
HolyHandGrenade(which breaks the rule directly above anyway) but instead say
Pick one word per concept: In other word, be consistent. Don't use
retrieveinterchangeably. Choose one and stick with it.
Don't pun: Same as being cute. Also don't be funny!
Use solution domain names: We can assume that programmers have computer science knowledge, so we can use computer science terms, algorithm names, pattern names, math terms, and more.
Use problem domain names: Code that has more to do with problem domain concepts should have names drawn from the problem domain. Worse case, the programmer will just have to ask an expert or use Google.
Add meaningful context: Imagine a variable out of context. If you see
zipcode, you have a different idea than if you see
Don't add gratuitous context: Adding prefixes or using redundant naming conventions are both ugly and unnecessary. Shorter names are normally better as long as they are clear.
In the list, I find funny the number of "don't"s and "avoid"s. Multiple points drove the same point: don't be funny, cute, or smart. Just say what the thing is or what the thing does.
The most valuable and prescriptive naming conventions for me are consistency ("pick one word per concept"), use solution domain names, and use verbs for methods and nouns for classes. Also, the more we know about algorithms and design patterns, the more aptly we can name our objects.
Each domino does only one thing: once it receives force, it falls over.
The first rule of functions is that they should be small.
The second rule of functions is that they should be smaller than that.
--- Clean Code
Here's the problem with the "do one thing" advice that is common for chunking functions: what is one thing, exactly?
Depending on how much we abstract, one thing can be quite big or quite small. A whole piece of software is "one thing." Can you imagine what that function would look like?!
So Clean Code came up with a more specific rule about this: the statements in our function must be within one level of abstraction.
Clean Code says, "Master programmers think of systems as stories to be told rather than programs to be written." Reading code is reading a story: it introduces elements, puts them through a journey, and ties up loose ends.
Mixing levels of abstraction is always confusing and we can sense when they have been mixed. We expect to see pieces of consistent size within our functions even if we don't consciously know it. Writing code in this way can be challenging to grasp, but ultimately rewarding for the readability and maintainability of the code.
The goal of any function doing "one thing" is to have no consequences. It doesn't mutate anything unexpectedly. There are no tricks.
Comments exist when things are out of place or not working as they should.
It is possible to make the point that programmers should be disciplined enough to keep the comments in a high state of repair, relevance, and accuracy. I agree, they should. But I would rather that energy go toward making the code so clear and expressive that it does not need the comments in the first place.
--- Clean Code
The ideal state is for code to be self evident. Whenever there is a need for a comment, it indicates how the code is failing.
This philosophy about commenting was the opposite taught to me in the classroom. I would have a failing grade on a C++ assignment if I didn't extensively document the purpose of every method and every argument and every variable of a class. Because of this traditional education I had, I got a rude awakening in the workplace. How embarrassing.
The problem with comments, as I have discovered myself, is they do become wrong over time and don't follow the original source of code. "This list is in alphabetical order." Is it really now?
Error handling within the code acts like a thick fog on the code itself.
Many code bases are completely dominated by error handling. When I say dominated, I don't mean that error handling is all that they do. I mean that it is nearly impossible to see what the code does because of all of the scattered handling. Error handling is important, but if it obscures logic, it's wrong.
--- Clean Code
When it comes to error handling, Clean Code encourages using exceptions rather than return codes. For code to truly be clean, the error handling must not obscure the logic.
So how is this done? The book describes several rules:
**try-catch-finally**statement first: Doing this helps you define what the user of that could should expect no matter what goes wrong in the code.
Provide context with exceptions: Thrown exceptions allows you to be able to determine the source and location of an error so that you can determine the intent of the failed operation.
Define exception classes in terms of a caller's needs: While we can classify exceptions by any number of things, like source or type, but Clean Code argues the most important distinction is in how the error is caught.
Don't return null: If you don't ever return null, you don't have to check for null. Simple.
Messy tests can ruin your production code.
[In TDD, we]write dozens of tests every day, hundreds of tests every month, and thousands of tests every year. If we work this way, those tests will cover virtually all of our production code. The sheer bulk of those tests, which can rival the size of the production code itself, can present a daunting management problem.
--- Clean Code
You probably knew this was coming. Clean Code wouldn't be deemed clean without Test-Driven Development (TDD). But Clean Code talks about more than TDD: it talks about also keeping your tests clean.
If you practice TDD, you will grow a huge number of tests. And like everything else, you need to organize and manage it. The book says that "having dirty tests is equivalent to, if not worse than, having no tests." Like code itself, it can get so messy that it adds hours of bloat to maintenance and creates an unhealthy relationship between the tests and the production code. Changing something in the production code might set off dozens of unnecessary bombs in the test suit. For programmers changing production code with messy tests, they brace for impact each time they edit a line.
But there's a solution!
Clean Code says that "readability" is everything when it comes to tests. Readability trumps all with test suites --- potentially more than production code.
But 'readability' is actually a fairly loaded term, defined in the book as "clarity, simplicity, and density of expression." Quite a lot to unpack there. Perhaps an entire other book's worth.
The book does include a cute, little acronym on writing good tests, though. The acronym is FIRST and it goes like this:
Fast: Tests should run quickly, otherwise people are less likely to run them and the code will begin to rot.
Independent: Tests do not depend on each other.
Repeatable: They can run in any environment.
Self-Validating: They either pass or fail. You do not need to have to interpret the results.
How does your codebase smell? Can you make it smell like flowers?
This list of heuristics and smells could hardly be said to be complete. Indeed, I'm not sure that such a list can ever be complete. [...] 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.
--- Clean Code
The final chapter of the book includes a catch-all section for 'smells'. These are general rules for when something probably isn't right. But with the same philosophy The Pragmatic Programmer, programmers should not follow rules blindly, but have their own understanding.
In my time working in the software industry, I have heard of a number of these 'smells', but it's nice to see a collection of these all in one place.
Here is a sample of the 'smells' a codebase might have:
Obsolete comment: Old comments. Ew.
Redundant comment: Comments that describe something self-evident. Also ew, but honestly not so bad. A simple delete takes care of that.
Poorly-written comment: In my experience, the worst writing over-explains details that nobody cares about.
Commented-out code: This just rots over time. We have version control. Just remove it.
Test require more than one step: All unit tests should run with one command.
Functions have too many arguments: Keep it down to zero, one, or two. More than three is questionable.
Dead functions: Functions should be removed if they are never called.
Duplication: Duplication in code is a missing opportunity for abstraction.
Inconsistency: Do the same things the same way every time.
Understand the algorithm: Make sure you understand exactly how your function works. It's understandable that the process to get there came from little tweaks here and there, but truly get the full picture before you're done.
Replace magic numbers with named constants: Magic numbers are those strange numbers that are not self-evident in purpose, but we need them to make specific calculations. Leaving the numbers as they are, without a label, can confuse future readers and obscure what the operation is doing.
Wow. After reading Clean Code, I am surprised to have discovered a well-written and inspiring programming book.. I enjoy that the book addresses programmers as craftsmen. It makes me feel respected as owning a trade that takes skill and creativity.
Clean Code echoes a similar reverence and charm as The Pragmatic Programmer, and I can see why these two texts are toted side-by-side. As programmers, we have a duty to uphold the integrity of the code, and I feel inspired by the nobility of the task.
Overall, I feel this book is worth owning and refreshing with from time to time. The book is large enough to grow with you as you focus on different pain points of coding throughout your career.
If you liked this article and if you are inspired to better yourself by reading more books on programming this year, I have a free email course that you are sure to enjoy called Getting the Most From Technical Books.
As always, let's keep bettering ourselves as programmers and perfect our crafts.
Until next time. 👋😁