Clean Code
A Handbook of Agile Software Craftsmanship
1 Listen to Clean Code Summary
2 Book Summary: Clean Code by Robert C. Martin
“Clean Code” by Robert C. Martin, affectionately known as “Uncle Bob,” argues that writing clean code is a professional discipline and a crucial survival skill. Bad code, or a “mess”, actively hinders development, decreases productivity, and can ultimately lead to project failure. The book is divided into principles of clean code, case studies of refactoring, and a list of “smells” or heuristics to identify code that needs cleaning.
“Truth can only be found in one place: the code. Only the code can truly tell you what it does”
2.1 Core Principles for Writing Clean Code
The foundation of clean code is a set of principles that guide a developer’s choices at every level, from naming a variable to structuring a system.
Meaningful Names: Names in code should be intention-revealing. They should answer why it exists, what it does, and how it is used.
- Use names you can pronounce.
- Use searchable names.
- Avoid encodings (like Hungarian Notation or member prefixes like
m_
). - Class names should be nouns; method names should be verbs.
Functions: Functions are the first line of organisation in code. They should be small and do one thing.
- Small!: The first rule is that they should be small. The second is that they should be smaller than that. Ideally, a function should be easily visible on one screen without scrolling.
- Do One Thing: A function should have a single, well-defined responsibility and should not be divisible into sections.
- One Level of Abstraction: The statements within a function should all be at the same level of abstraction, following the “Stepdown Rule” where code reads like a top-down narrative.
- Few Arguments: The ideal number of arguments is zero, followed by one, then two. More than three arguments should be avoided. Flag arguments are a sign that a function does more than one thing.
Comments: Comments are not “pure good”; they are, at best, a necessary evil. The best comment is the one you found a way not to write by making your code more expressive.
- Comments do not make up for bad code. Rewrite the code.
- Avoid redundant comments, journal comments, and commented-out code.
- Good comments include legal notices, warnings of consequences, and TODO notes.
Formatting: Code formatting is about communication. A consistent style makes code easier to read and understand.
- The Newspaper Metaphor: A source file should read like a newspaper article, with high-level concepts at the top and details increasing as you scroll down.
- Vertical Formatting: Use blank lines to separate concepts. Keep related code vertically dense.
- Horizontal Formatting: Keep lines short. Use horizontal whitespace to associate related items and disassociate weakly related ones.
Bad code can bring a company to its knees. As the mess grows, productivity approaches zero. Adding new developers to a messy project only makes it worse, as they don’t understand the original design intent and are pressured to add more mess. This often leads to a “Grand Redesign in the Sky” which frequently fails, creating a vicious cycle. The only way to go fast is to stay clean.
“Leave the campground cleaner than you found it.”
If every developer checks in their code a little cleaner than when they checked it out - by improving a variable name, splitting a function, or removing a small bit of duplication - the system’s quality will steadily improve over time. This continuous improvement is a core part of professionalism.
2.2 Handling Structure and Errors
Beyond the basics, clean code involves robustly designed structures and error handling mechanisms that don’t obscure the primary logic.
Objects vs. Data Structures:
- Objects hide their data behind abstractions and expose functions that operate on that data.
- Data Structures expose their data and have no meaningful functions.
- This creates an anti-symmetry: it’s easy to add new functions in procedural code (data structures), but hard to add new data structures. In OO code, it’s easy to add new classes (types) but hard to add new functions. Choose the right tool for the job.
Error Handling: Error handling is important, but if it obscures the program’s logic, it’s wrong.
- Use Exceptions Instead of Return Codes: Returning error codes clutters the caller and leads to nested
if
statements. Throwing an exception separates the error-handling logic from the main program flow. - Write
Try-Catch-Finally
First: This defines a scope and forces you to consider what happens when an operation aborts, ensuring your program remains in a consistent state. - Don’t Return Null: Returning
null
creates extra work for the caller, who must check for it. A missing null check can cause the application to fail. - Don’t Pass Null: Passing
null
into methods is even worse. It creates a burden on the method to handle it, often leading to moreNullPointerExceptions
. Forbid passingnull
by convention.
- Use Exceptions Instead of Return Codes: Returning error codes clutters the caller and leads to nested
A method should only call methods on:
- Itself
- Objects passed as parameters
- Objects it creates
- Objects held in its instance variables
This avoids “train wrecks” like ctxt.getOptions().getScratchDir().getAbsolutePath()
. Instead of asking an object for its internals, you should tell the object what to do (e.g., ctxt.createScratchFileStream(classFileName)
). This principle helps to reduce coupling between modules.
2.3 Other key ideas
2.4 Key Heuristics Checklist
- [Names] Does the name reveal intent? Is it pronounceable and searchable?
- [Functions] Is this function small? Does it do only one thing? Does it have three or fewer arguments?
- [Comments] Does this comment add value, or could the code be made more expressive to eliminate it? Is the comment accurate?
- [Formatting] Is the code formatted consistently according to team rules? Does it read like a well-written article?
- [Structure] Does this class have a single responsibility? Is it highly cohesive?
- [Error Handling] Are you using exceptions? Are you avoiding returning or passing
null
? - [Duplication] Have you eliminated all duplication? (The DRY Principle: Don’t Repeat Yourself).
- [Tests] Are the tests clean, fast, and independent? Is there a test for every piece of production code?
3 Summary Video
4 Practise
A great way to practise the principles from “Clean Code” is to perform a refactoring exercise.
Find a function or class in one of your current projects that you know is messy, long, or difficult to understand.
Before changing anything, ensure you have a suite of tests that cover its current behaviour. If not, write them first.
Go through the Key Heuristics Checklist above. Apply one principle at a time.
- Rename one variable to be more descriptive. Run the tests.
- Extract one small part of a long function into a new, well-named function. Run the tests.
- Remove one redundant comment. Run the tests.
Continue this process of making small, incremental changes, running the tests after each one, until the code is noticeably cleaner.