One of most frustrating things any software engineer deals with is unmaintainable code. Code that makes you study a class for hours before its intent comes to life. Code where variable names are meaningless. Code that doesn’t have any form of automated tests making it difficult and frightening to change it in any way.
Clean Code is fantastic book about how to practically fight against these problems. Author Robert Martin, one of the fore-fathers of the Agile manifesto, has a passion for software craftsmanship: the idea that software development is closer to medievil trades (such as blacksmithing or woodworking) that requires years for constant refinement and challenge to become a master practitioner. In this book, “Uncle Bob” helps to show how a software developer can write code that is maintainable, readable, and testable, etc. He wraps a lot of these qualities into a more abstract idea of “Clean Code”.
I’d like to give a brief overview of the book here, with a few of my personal take-aways.
Overview: Why We Need a Book About Clean Code
What is Clean Code?
The phrase “Clean Code” is a little abstract. I had heard the phrase used before I read the book, and my general thought was that Clean Code simply was, well, simple. In many ways this is still true, but the book helps to give better language to some of the ideas swirling in my head.
In this book, Uncle Bob first defines Clean Code by what it isn’t: Bad Code. Bad Code is hard to read and hard to change. It’s also usually very hard to test effectively. There are tons of specific examples to illustrate Bad Code, but I like the brief definition given in the book.
By contrast, Clean Code should be easy to read, easy to write, and easy to test. Some quotes and examples describing it include:
Hard for bugs to hide
Looks like it was written by someone who cares
Turns out to be pretty much what you expected
My favorite is the last one: turns out to be pretty much what you expected. In reality, its harder for that to happen in code than you would think. Any engineer working on legacy systems will agree with me.
Why is Clean Code Important?
Clean Code isn’t just a lofty goal in the sky for no reason. Clean Code has real value.
First, Clean Code is a important because the opposite, Bad Code, has financial cost. Hard to write and maintains systems cost companies money. There are developers who take longer to write features or fix bugs than they should, thus waisting developer time. Systems full of Bad Code have a higher chance of creating outages or performing erroneous operations, both which affect the bottom line.
Secondly, Clean Code is thinking about your fellow developer. Don’t you remember the first time you started work on a really old and crufty software solution? Wasn’t it terrible? Writing clean code is paving the way for new developers to join your team and contribute faster. And those new team members won’t hate you for your code when its clean 🙂
Third, the simple fact that you will spend the majority of your time coding reading cold you previously wrote is worth it. Its that typical 80/20 split: we spend 80% of our time reading code – so we should make it very easy to read. This isn’t just about the business and your fellow man now, this is about your own time and sanity. Even on side-projects, write code that you are proud of and it will help motivate you to keep working!
How Does One Write Clean Code?
Ok ok. You get what Clean Code is. You understand it’s important to write it. But how do you actually start?
The nuts and bolts of Clean Code is all about providing heuristics and examples of how to write Clean Code. From names, to function parameters, he dives into the weeds. The first part of the book can generally be thought of as “standards” to try and hold yourself too, while the second is examples of refactoring code bit-by-bit to get it where you want it.
There are many important things to take away from the how section of this book, and if you apply them your code will get better. I promise.
Instead of going through each one (that would be laborious), I decided to share some of the specific rules or standards I have tried to really focus on over the past several months since reading that have made me a better developer.
My Top Take-Aways
Functions Should Do ONE Thing
I know this seems trivial, but I promise that pushing myself to keep this as true as possible has lead to some of my best code. If a function checks something, then manipulates something else, and then returns an object unrelated to what I checked or manipulated, something went wrong.
Keeping this rule is harder than it sounds. It is soo easy to check for the existence of a value, then manipulate a
List or something, then return some filtered version of that
List all in the same function. It would be better off to do each of these in different, discrete functions.
If you ask why it matters so much, the core reason in my experience is you gain two big things.
- Flexibility in composing your functions together as needed
- Easier to test in the long run
Naming Is Crucial
As developers, we have a unique ability to create and manipulate the “vocabulary” so to speak of the systems we create. Class names; variable names; packages names; function names; They all work together to help us tell a story within our code. We have the ability to name things whatever we want (well, within the language rules of course) and with great power comes great responsibility.
Therefore, we should be thoughtful about what names we give to things. In my experience, the two that matter the most in telling the story of what a software solution does are the class names and the method names. When those names aren’t good, it becomes difficult to compose functionality and limits understanding.
An example of a naming paradigm that I think has started to create havoc is the
Service naming convention used in typical web-applications these days. You create a
ReportService, then you create a
CustomerService, etc. The problem is that before too long, your simple web-application needs to call other web-applications. A name of
ExternalServiceService pops up faster than you would have thought.
In these scenarios, I have found it helpful to look at package names and understand how classes are related and do some renaming until it feels right. A simple way that I have found is not using vague phrases like
ApiService. Instead, be specific and granular.
When it comes to function names, it becomes even more important. Make sure that something with a name
get actually returns something. If a function returns a
boolean, it should likely start with something like
should etc. When you couple really good function naming to functions that do one thing, it changes how you code.
Understanding the Difference Between Models and Things That Operate On Them
Uncle Rob calls these Data Structures and Objects. In my head, that is a little confusing, so I like to stick to POJO (or Plain Old Java Object) or Model and then things that operate on those Models.
Essentially, Models are simple data-containers that allow you to pass related data easily. All of your other classes should generally be operators or performers that do something with those models. Similar to an API, you POST, GET, PUT, etc. (ie perform an action) one some resource (ie Model).
You probably do this already right? So why is this a take-away for me?
It’s a take-away for me because of how often I try to mix them together. I’ve written Models that try to understand too much about themselves (like say, trying to sort its internal elements). I’ve also done the opposite where I try to keep too much state with an operator class that makes it hard for me to keep my head straight. By keeping the two distinct, you get cleaner lines of separation, more flexibility, and the ability to abstract sooner. All of which leads to more maintainable code over time.
Keeping Code Clean is a Battle
Writing Clean Code doesn’t stop when you finish a class for a particular feature. You may need to refactor that class later. You might find a better name. You might need to isolate your functions even more than you did initially.
All Bad Code was at one point in time, probably Clean (or at least very close to Clean). Very few developers want to write hard to read code (at least the developers that I know). All software systems, including the system you are working on, suffer from unreadable and unmaintainable code. The law of entropy is working against you. You have to fight to keep you code maintainable.
All in all, I highly recommend this book to any developer who wants to grow in their coding abilities. It will give you the specific language and tools that you have likely been trying to formulate as you’ve tried to write better code.
Till next time!