Book Review: Clean Code
I finally got around to reading Clean Code by Robert C. Martin (Uncle Bob). It is often high on lists of the best books for software development, and for good reason. Clean Code is an excellent book that all programmers should read. Here is what I liked and didn’t like about it.
Organization
The books is divided into four parts. Chapters 1 to 14 go through the basics, including naming, functions, formatting, comments and error handling. Then there are three example programs that are refactored to follow the recommendations given in the first part.
The three example programs are a command-line argument parser, a part of JUnit, and SerialDate, a class for date handling. The examples are quite extensive (together almost a hundred pages), with a lot of source code. All these (and all examples throughout the book) are written in Java.
Next is a chapter called “Smells and Heuristics”, which lists problems in code (and the solutions) in the form of 66 rules.
Finally there is appendix A, with more on concurrency, and appendix B, which has the complete source code for the third example program (SerialDate, almost 60 pages of program listing).
What I Liked the Most
Small. This is the one-word summary of the whole book. Functions and classes should be small (no, even smaller than that). It is much easier to make sure a function does only one thing
Niladic and monadic functions. The fewer arguments a function takes, the better (a niladic function takes zero arguments, a monadic one, and a dyadic two). I hadn’t thought much about the number of arguments before, but Uncle Bob makes a convincing case for using very few.
Flag arguments. A flag argument to a function is a boolean argument that controls what should be done. This is really an indication that the function should be split up in smaller parts.
Error handling. The argument for using exceptions for error handling instead of returning error codes is that it is much easier to separate the error handling from the regular logic. Also, using unchecked exceptions (instead of checked) avoids cascading changes when a new exception is added deep down in a hierarchy.
Newspaper Metaphor. The source file should be organized like a newspaper article, with the highest level summary at the top, and more and more details further down. Functions called from the top function come directly below it, and so on down to the lowest level and most detailed functions at the bottom. This is a good way to organize the source code, even though IDE:s make the location of functions less important, since it is so easy to navigate in and out of them.
Javadoc only for API:s. The recommendation is to only use Javadoc for documenting API:s that are exposed externally. Internally in a system, Javadoc documentation usually only results in unnecessary noise. I have seen this problem a lot, and I completely agree with this advice.
Long refactoring examples. The refactoring of the three example programs was quite valuable because it showed how to apply the recommendations in practice, and how the refactorings interact. This is often missing from other books. The disadvantage is that it can be pretty hard to follow when you don’t have an IDE to help you navigate and search.
What I Didn’t Like
Concurrency chapter and appendix. This chapter and appendix felt a bit out of place in the book. I also didn’t like the advice on instrumenting the code to try to find threading issues. In my experience, you don’t find multi-threading bugs that way. Instead, the best way is proper load testing, where the software is in heavy use in realistic scenarios.
Chapters 11 (Systems) and 12 (Emergence). These two chapters, despite promising titles, didn’t contain much of interest. They can easily be skipped without missing out on much.
State to reduce the number of arguments. In order to reduce the number of arguments a method needs, member variables are sometimes introduced instead. While this reduces the number of arguments, it also forces you to examine how the member variable is used in the rest of the class before you have a complete understanding of what the method does. This in my mind is worse, even if the class is small. I prefer the functional style, where it is enough to know the input arguments to have a complete understanding of what will happen.
No emphasis on dynamic error information. When an exception is thrown, it should always contain as much dynamic information as possible, to help in debugging. For example, if a network connection fails, include the port number and IP address the connection was intended for. Without this information, trouble shooting is a lot harder. Unfortunately, this is not mentioned at all in the book.
Wildcard imports. Rule J1 advocates importing a whole package rather than individual classes if two or more classes are needed from the package. However, then your program can break when a class is added to a package you import (more in e.g. this StackOverflow question). A long list of explicit imports at the beginning is not a problem in my view, it is easy to skip over.
Conclusion
There is a lot more good information in this book than I have been able to cover here. You can also tell that the advice is based on decades of experience developing real life software systems. I rate this book as one of the top three books on software development (the other two are Code Complete and The Pragmatic Programmer), and I think all programmers should read it.
Have you read Clean Code? What did you think? How does it compare to other books on programming? Let me know in the comments.