InfoQ

InfoQ

Article

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

Book Review: Clean Code: A Handbook of Agile Software Craftsmanship

Posted by Ryan Cooper on Apr 08, 2009

Sections
Process & Practices,
Architecture & Design,
Development
Topics
Programming ,
Software Craftsmanship ,
Design ,
Agile

As programmers, our first priority is creating code that works. Unfortunately, code that just "works" just isn't good enough. To provide real, lasting value, code has to be clean. In "Clean Code: A Handbook of Agile Software Craftsmanship", Robert C. Martin makes use of extensive examples and case studies to hone our ability to identifying code that has room for improvement, and provides a multitude of techniques to clean up code, just a little, every time we touch it.

What is Clean Code?

In Chapter 1, Martin convincingly argues that clean code is not just desirable -- it is necessary. Without clean code, development slows over time. Eventually, it hits a point of such uncertainty, pain, and frustration that it seems easier to just start over and rewrite the whole thing from scratch. Of course, if the rewrite isn't done any more cleanly than the original, the problem persists, and in a few years the team ends up where it started!

Everyone defines clean code a little differently. Martin includes descriptions of clean code by such notable developers as Bjarne Stroustrup, Grady Booch, "Big" Dave Thomas, Michael Feathers, Ron Jeffries, and Ward Cunningham. Although they all emphasize different aspects of clean code, there are a few emerging themes: simplicity, lack of duplication, readability, elegance. Code that has these qualities is maintainable, breaking the slowdown/rewrite cycle, and providing true, lasting value.

The Devil's in the Details

Chapters 2 through 6 cover low-level coding decisions: picking meaningful names, defining readable and elegant functions, writing useful comments (and avoid bad ones), formatting your code to improve readability and clarity, and choosing when to use smart objects and when to use dumb data structures.

Martin effectively intermixes theory and explanation with concrete coding examples that illustrate his points. These back-and-forth sections convey a lot of wisdom, but are too lengthy to summarize or reproduce here.

Interspersed with these explanations are lots of concise, thought-provoking gems like these (taken from Chapter 2 through 4):

"The problem isn't the simplicity of the code but the implicity of the code: the degree to which the context is not explicit in the code itself."

"Our goal, as authors, is to make our code as easy as possible to understand. We want our code to be a quick skim, not an intense study. We want to use the popular paperback model whereby the author is responsible for making himself clear and not the academic model where it is the scholar's job to dig the meaning out of the paper."

"The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that."

"Don't be afraid to make a name long. A long descriptive name is better than a short enigmatic name. A long descriptive name is better than a long descriptive comment."

"It is hard to overestimate the value of good names. Remember Ward's principle: you know you are working on clean code when each routine turns out to be pretty much what you expected. Half the battle... is choosing good names for small functions that do one thing. The smaller and more focused a function is, the easier it is to choose a descriptive name."

"Side effects are lies. Your function promises to do one thing, but it also does other hidden things."

"The art of programming is, and has always been, the art of language design. Master programmers think of systems as stories to be told rather than programs to be written. They use the facilities of their chosen programming language to construct a much richer and more expressive language that can be used to tell that story."

These chapters stitch together a cohesive, consistent philosophy of clean code, and provide the pragmatic advice needed to follow that philosophy in practice.

Higher Level Concepts

Chapters 7 and 8 cover error handling and interfacing with third-party code and systems. I found Chapter 7 (written by Michael Feathers) particularly valuable. Error handling is one of those areas that is seldom done well, and is usually skirted around in literature about software design. Feathers delivers a practical approach to keeping error handling separate from the main flow, and keeping both clean and readable in the process.

Chapter 9 covers Unit Tests: why keeping them clean is as important as keeping your production code clean, and how to keep your tests clean. ("Three things. Readability, readability, readability.") The chapter is brief, but contains lots of examples of good and bad tests to illustrate Martin's points.

Chapters 10, 11, and 12 cover higher-level design concepts: classes, systems, and emergent design. Chapter 10 focuses heavily on The Single Responsibility Principle (SRP), a concept from Martin's previous work, Agile Software Development: Principles, Patterns, and Practices. The treatment here is less in-depth, but a good starting point. Chapter 11 talks about clean code in the context of system-level techniques such as Dependency Injection and Aspect-Oriented Programming. Chapter 12 reminds us to rely on tests and refactoring to drive our high-level design as well as our low-level decisions.

Chapter 13 covers Concurrency. It doesn't go into great depth, and feels a little bolted-on, but does contain a good deal of solid advice.

The Case Studies

In chapters 14, 15, and 16, Martin ties the ideas from the previous chapters together. In each chapter, Martin starts with a real example of not-great, not-terrible code, and guides us through the process of refactoring it into something much cleaner.

The code examples are not trivial, but not unnecessarily complicated either. They are complex enough to not feel like "toy" examples, but straightforward enough to understand after some careful code reading. They provide the necessary environment in which to develop a more in-depth understanding of how to apply the concepts presented earlier in the book.

It's one thing to read that refactoring should be done in "baby steps". It's entirely another thing to see a concrete example of how an experienced agile developer picks which baby steps to take. These chapters add a lot of value to this book. This is where everything you've read so far will really begin to sink in and acquire practical relevance. Reading the case studies reminded me of pairing with a really smart, experienced developer -- a testament to the clarity of Martin's writing.

Smells and Heuristics

Chapter 17 wraps up the book with a list of "code smells" and heuristics. It condenses the ideas of the book into a very direct, problem-centric format, ideal for review. And at 29 pages, it makes a nice, concise reference.

Conclusion

This book belongs on the bookshelf of every developer who cares passionately about quality and craftsmanship. Less experienced developers will find it more valuable, and more of a slow read – this book is packed with good advice, without much "filler". Martin uses plenty of examples, and uses clear, concise language, so although inexperienced developers will find it slow going, they are unlikely to feel lost.

Experienced developers would do well to give it a read as well. It will reinforce those things that you already know you should be doing (but which you don't always do), remind you of a few things you've forgotten, and teach you a few new things as well. Most of all, it will give you a fresh perspective on all those seemingly mundane decisions you make hundreds of times a day.

  • This article is part of a featured topic series on Agile
Excellent book by Juan Gil Posted
Anything different from "Code Complete" by Aayush Puri Posted
Re: Anything different from by Denis Miller Posted
  1. Back to top

    Excellent book

    by Juan Gil

    This book its a *MUST READ* the author and his collaborators are very clear about the problems they found working all day long, behind the trenchs...

    once they stated why "x" is a bad practice, they allways explain how avoid it, in many ways... its a pleasure to read :)

    this book, not only describe really commons bad practices, it also shows them on real proyects and describe ways to correct them.

  2. Back to top

    Anything different from "Code Complete"

    by Aayush Puri

    Looks quite a useful book as per the excerpt but I was wondering if this book offers anything different/extra that what is covered in "Code Complete". Even though there aren't a lot of book of coding practices as such, but I felt like "Code Complete" pretty much fills that void. So is there anything more that this book adds?

  3. Back to top

    Re: Anything different from

    by Denis Miller

    Yes, there is. It is another level of understanding. 'Code complete' tells us how to implement some things. But this book tells about how to think. Nothing to compare. Two different books.

    If we want to compare, I think, we should compare "Implementation Patterns" by Kent Beck and "Clean Code". I think, IP will win ;)

    I can arrange 4 books from particular implementations to values/way of thinking:
    Implementation<------------------------------------------------------> Values
    Code Complete ---> Refactoring M.Fowler ---> Clean Code ---> Implementation Patterns.

Educational Content

New-age Transactional Systems - Not Your Grandpa's OLTP

John Hugg discusses high volume transaction processing applications with high and low frequency profiles, and how VoltDB can be used for that purpose.

Cool Code

Kevlin Henney examines code samples to see what can be learned from them starting from the premise that one won’t write great code unless he knows how to read it.

Collaboration: At the Extremities of Extreme

Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.

Yesod Web Framework

Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).

Transactions without Transactions

Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.