Cleanish Code - A feasibility review of Uncle Bob's Clean Code

9/23/2015

Clean Code by Robert C. Martin (Uncle Bob) is one of those books on most lists of "books every developer should read". It offers guidance on how to write good code. Good (or clean) code is defined as code that:

  • does one thing well
  • is simple and direct
  • has meaningful names
  • has straightforward logic, which makes it hard for bugs to hide
  • is full of crisp abstractions and straight forward lines of control
  • contains no duplication
  • has unit and acceptance tests
  • is maintainable
  • reads like what you would expect
  • looks like its written by someone who cares
The book lays out several principles for writing clean code according to the Uncle Bob school of thought; which he readily admits is not the only right school of thought, but many, myself included, consider it to be an excellent one.

It stands to reason that if all of the Clean Code principles were followed in a green-field application it would leave you with a system that has no technical debt (by Uncle Bob's standards). The following question could then be asked; is it possible to build and maintain a large system that has no debt? My answer to that would be: yes, but at a very high cost. Such a system would probably need to have a heavy dose of both upfront design and agile/successive refinement. In addition, every change would require careful thought and a certain amount of refactoring of the application. In a brown-field application (which is what 90+% of developers work on 90+% of the time), the cost is even higher.

Quick Sidebar: According to a quick Google search there are only 5 countries in the world with no debt; Brunei, Liechtenstein, Palau, Nieu, And Macau Of China. Most other countries have to carry some debt to achieve their goals.

The thought behind this review is to perform a cost benefit analysis of some of the clean code principles: What are the costs of implementing a principle and is the benefit worth the cost to the developer making the decision? This process of cost benefit analysis is done (either consciously or subconsciously) by every developer who is sitting at a keyboard and making a design decision. This post is my version of that thought process, done from my perspective. I've done some grouping of the Clean Code principles based on my perceived cost of implementing a principle and the benefits gained from that implementation.

Low Cost, Low/Medium Benefit

These principles are so low cost in my opinion that even if they provided just a little benefit, everyone should almost always adhere to them. Following them would make your code easier to read and be understood which has its own set of benefits.
  • Use meaningful names - Meaningful names should reveal intent, be human pronounceable, be searchable, use one word per concept consistently throughout the code base, and should draw from the solution and problem domain. Classes should have noun or noun phrase names and methods should have verb or verb phrase names. Meaningful names improve the readability of the code for cheap.
  • Formatting and spacing - The top parts of a source file should provide the high-level concepts and algorithms. Detail should increase as we move downward, until at the end we find the lowest level functions and details in the source file. In a block of code, blank lines should separate concepts. 

Low Cost, High Benefit

Not only are these principles low cost but they also provide great benefit in terms of the maintainability and robustness of your code. Unsurprisingly, these principles are very familiar to modern developers.
  • Don't Repeat Yourself - As Uncle Bob says "duplication may be the root of all evil in software". The good news is that duplication is often easy to identify and refactor out into its own method.
  • Have no side effects - Side effects break the promise made by the function definition; the function promises to do one thing but it also does other hidden things. In this sense, side effects break the Single Responsibility Principle. Avoiding side effects affects not only improves the maintainability of your functions but also makes them easy to parallelize.

Medium Cost, High Benefits

These are the hallmarks of a clean coder. They illustrate how much love and thought you put into your code, and pay off in readable, extensible, maintainable code with clear lines of control. These principles may take some time to implement but produce big time savings when maintaining and troubleshooting the code in the future.
  • Keep functions small, very small. Functions should be transparently obvious and tell a story. They should do only one thing and contain only one level of abstraction. They should be meaningfully named and should have as few arguments as possible. Large numbers of arguments take up conceptual power and make testing more difficult.
  • Use meaningful exceptions with context - Error handling should be separated from the business logic so as not to obscure the business logic. In addition, exceptions thrown should provide enough context to determine the source, location and type of failure. Nulls should never be passed into a function or returned from a function.

High Cost, High Benefit

These are principles that significantly alter the way you do development. When done right these principles can be highly beneficial to the reliability and maintainability of a code base. However, implementing these in a greenfield application can be tasking, and is even more difficult in a brownfield application. Developers that aren't convinced of the benefits may sometimes choose to carry some technical debt in this area. Although I'd advise that in projects that value the benefits these principles bring, you should try to have as little debt in this area as possible.

  • Test Driven Development - The 3 laws of TDD are: 1. You may not write production code until you have written a failing unit test. 2. You may not write more of a unit test than is sufficient to fail, and not compiling is failing. 3. You may not write more production code than is sufficient to pass the currently failing test. Tests should be fast, independent, and repeatable in any environment.

Medium/High Cost, Low/Medium Benefit

In my experience I'd classify these as nice to have. They provide a slight to moderate benefit but require good amounts of refactoring to achieve so technical debt in these areas isn't highly detrimental.
  • Clean Tests - In my experience, unit tests for internal projects rarely gets read, they just get run, so readability isn't a big factor. However, if you are writing clean tests the same rules that make all code readable apply; clarity, simplicity, and density of expression. There should be no duplication and only one concept per test.
  • Small Classes - In some respects, small classes are another manifestation of the single responsibility principle. The idea is that a class should have only one reason to change and should be highly cohesive. In other respects, small classes are about the organization of code to make things neater and easier to find. In practice however, it may be challenging to consistently have small classes throughout a code base because it requires a lot of refactoring to achieve.

Conclusion

I concur with probably every other person who has read Clean Code; its one of the best books ever written on the craft of software development. All that's left now is finding ways to incorporate these principles into your daily development life cycle, and get to writing clean code. Or at least cleanish code.




You Might Also Like

0 comments