Catch up on stories from the past week (and beyond) at the Slashdot story archive

 



Forgot your password?
typodupeerror
×
Programming

Clean Code 214

Cory Foy writes "As developers, system admins, and a variety of other roles in IT, we have to deal with code on a daily basis. Sometimes it's just one-off scripts we never have to see again. Sometimes we stare at something that, for the life of us, we can't understand how it came out of a human mind (or, as the book puts it, has a high WTF/minute count). But there is a time when you find code that is a joy to use, to read and to understand. Clean Code sets out to help developers write that third kind of code through a series of essay-type chapters on a variety of topics. But does it really help?" Read below to find out.
Clean Code - A Handbook of Agile Software Craftsmanship
author Robert C. Martin
pages 431
publisher Prentice Hall
rating 10
reviewer Cory Foy
ISBN 978-0-13-235088-4
summary A great book for anyone wanting to really improve how they write code
I had the pleasure of attending Bob Martin (Uncle Bob)'s sessions at several agile software conferences over the past several years. In them, Bob has a unique way of showing us the value of clean code. This book is no different. There is a warning in the introduction that this is going to be hard work — this isn't a "feel good" kind of book, but one where we slog through crappy code to understand how to make it better. The authors also point out that this is their view of what clean code is all about — and fully acknowledge that readers may "violently disagree" with some of the concepts.

The book wastes no time diving in covering "Meaningful Names", "Functions" and "Comments" right in the first several chapters. While I could sum up the chapters by saying, "Use them", "Keep them small" and "Comments don't make up for bad code" it wouldn't do the wisdom in the book justice. For example, in the meaningful names chapter, he talks about making pronounceable and searchable names — staying away from things like "genymdhms" (Generation date, year, month, day, hour, minute and second) and preferring things like MAX_STUDENTS_PER_CLASS.

After touching on formatting rules (including some very interesting graphs on the file and function length distributions in some common open source projects) he dives back into some more controversial topics — "Objects and Data Structures", and "Error Handling". The Objects chapter does a great job of drawing a line in the sand between Objects and Data Structures and why it really is both important, and clearer, to keep your privates in your private classes.

The Error Handling chapter is important because of the application of earlier chapters — the Do One Thing rule. Your functions should do one thing — either handle business logic, or exception handling, but not both. It's the difference between this:

try { s = new Socket(4000); s.OpenSocket(); string data = s.ReadFromSocket(); if(data == "32") data = "42"; printer.print(data); } catch(Exception ex) { if(ex == NetworkInterruptException) { //do something } if(ex == PrinterOnFireException) { //do something } logException(ex); }

And this

try { tryToPrintDataFromSocket(); } catch(Exception ex) { logException(ex); }

We then move on to "Boundaries" and "Unit Tests" — the critical points where we tend to really let code go. If we work hard, usually we can keep our own code clean. It's when we have to begin interacting with other systems that things start to go astray. In these chapters, Bob and James Grenning show us how to keep our code at the boundaries clean — and how to keep our code working, period. The authors are proponents of Test-Driven Development, and the chapter on unit tests is a fresh reminder that those tests are just as much code, and need to be kept just as clean as any other code we write.

We then begin to move at a higher level, starting with "Classes" and "Systems". The classes section should be familiar to most any OO programmer — keep the classes small, with a single responsibility, and low coupling. He also talks about Organizing for Change which is a great section on how to structure classes in a way that keeps them open to change. The Systems section continues along the path with the great reminder to "Separate Constructing a System from Using It". Here they go into Dependency Injection and Aspect-Oriented Programming, which I'll address in a bit.

Moving even higher up the chain, the book then tackles "Emergent Design". The key is to keep the design simple, which according to Kent Beck, means:
  • Runs all the tests
  • Contains no duplication
  • Expresses the intent of the programmer
  • Minimizes the number of classes and methods

With the above list given in order of importance. Really this breaks out to "Runs all the Tests" and "Refactoring" or making the code better. Simple design is perhaps one of the harder things out there, and yet the most important. When you look at systems that highly scale, it's because they are made up of simply designed components which work very well together.

After the Emergent Design chapter there is suddenly a chapter on Concurrency. This was not something I expected to see, but was very glad to. Too many times books about patterns and design don't address problems like scaling and concurrency. But this chapter does a great job of introducing the necessary steps that need to be taken to deal with concurrency — while still keeping your code clean. The book also provides an appendix which goes even deeper into the concurrency topic which I found to be quite good. Both this chapter and the appendix provide some very valuable rules that I personally have used when writing concurrent systems — like "Get your nonthreaded code working first" and "Run with more threads than processors" to flush out problems.

Chapters 14-16 cover the cleaning up of three different sections of code — an argument processor, JUnit and SerialDate, which is part of the org.jfree package. These chapters really hold true to the warning in the introduction that we'd be going through some code. However, the refinements work very well, and I think that each of them show the value of how much cleaning up the code can improve the readability of even code that works well and seems clean.

The last chapter is a "Smells and Heuristics" chapter which I'm finding to be a handy reference guide for code smells I see. When something is bothering me with code I'm reading, I flip to this section first to see if they have it listed. And with things like "Replace Magic Numbers with Named Constants" you can be sure that all of the advice that should have been beaten into your head long ago is still there, and relevant.

All in all I think this is a very valuable book for any developer wanting to improve how they write code. For senior level people, some things may seem trivial, but if you really take the time to look at the structural changes being made and apply them, you will write better code. For functional developers — the authors believe in OO, but there are still valuable nuggets that are applicable outside of that (like "Use Copies of Data" in the concurrency section). And for any developer, the insights are really good, and you'll find yourself writing down little snippets to hang on the wall.

The challenges with the book are first that it is just as they said — hard work. This is not a flip-through-with-your-mind-shut-off type book. If you want the most out of it, you have to be willing to really work at it. The other challenges are that at times it gets way too Java-centric. All of the code examples being in Java is fine, but some of the chapters (most notably the Systems chapter) really go heavy into Java tools and the Java way which, to me, weren't always applicable across languages.

All in all, I'd highly recommend this book to anyone wanting to improve how they write code. You likely will find yourself violently disagreeing with parts, but the total sum more than makes up for it.

You can purchase Clean Code - A Handbook of Agile Software Craftsmanship from amazon.com. Slashdot welcomes readers' book reviews — to see your own review here, read the book review guidelines, then visit the submission page.

This discussion has been archived. No new comments can be posted.

Clean Code

Comments Filter:
  • by nwf ( 25607 ) on Wednesday September 24, 2008 @01:26PM (#25138849)

    Run with more threads than processors

    Funny, I've found more problems by running with fewer threads than processors. Otherwise, you aren't necessarily getting true concurrency. Running ten threads on a single processor isn't going to help you find some of the pesky concurrency issues that arise from true parallel execution. Of course, one should run with more threads than processors to test that as well.

    Either way, writing non-trivial parallel code isn't easy.

  • by Anonymous Coward on Wednesday September 24, 2008 @01:39PM (#25139085)

    So you're saying that you generally find more concurrency issues by running less than one thread on a single processor?

  • Clean code? (Score:4, Insightful)

    by Mycroft_514 ( 701676 ) on Wednesday September 24, 2008 @01:42PM (#25139113) Journal

    Just write the code like it is YOU that has to debug it at 4am. Nothing to see here, move along, move along.

  • Clean Code (Score:5, Insightful)

    by codepunk ( 167897 ) on Wednesday September 24, 2008 @01:49PM (#25139243)

    I recently ran across a situation where I looked a piece of code someone else wrote and thought to myself that
    is really ugly. I set out to write a clean version but gave up when I figured out that no matter what I did
    this was still going to be ugly. Not so much because of a poor job coding it but because of what the code had
    to actually perform.....I guess it is just not possible to always put lipstick on the pig.

  • by mellon ( 7048 ) on Wednesday September 24, 2008 @01:54PM (#25139325) Homepage

    For some reason, whenever I see that word in reference to programming, I want to run screaming in the opposite direction. Does that make me a bad person?

  • by Louis Kleiman ( 1371245 ) on Wednesday September 24, 2008 @01:54PM (#25139347)
    So, you can't write code that is both pretty and efficient? Don't saddle the rest of us with your problems. "Clean code" and "Preformance related code" [sic] are NOT opposites. In fact, I have seen a huge number of situations where I sped something up by cleaning out the code.
  • by leenks ( 906881 ) on Wednesday September 24, 2008 @01:57PM (#25139415)

    It depends on the situation.

    Efficiency isn't always the desirable outcome as most code doesn't need to be exceptionally efficient - a good developer's time is expensive, and often anything that makes it easier to maintain is a good thing.

    It also means developers can spend more time developing extra functionality rather than coding uber efficient code that usually isn't needed - and then rewrite poorly performing code.

    That said, sometimes you really do want to go for the efficiency - a good developer will know when to do that and document appropriately (both inside the code and out - the last thing you want when planning a large change is to not know what is involved until you get neck deep in code).

  • by dubl-u ( 51156 ) * <2523987012@pota . t o> on Wednesday September 24, 2008 @01:58PM (#25139421)

    Put another way, the kind of engineer that would actually benefit from a book like this, has probably already read a book like this.

    I think you've created a false dichotomy.

    I haven't read this book yet (although Bob Martin's other stuff is great), but back at the dawn of time, I was working with a team that was all relatively young. When McConnell's "Code Complete" came out, we all went through it pretty excitedly.

    Although we had the right spirit, and we each could have named some of the things in the book, none of us could have articulated all of them. And there were a lot of subtleties that we had never thought of.

    So I'd agree that jerks won't read this and nice graybeards don't need to, there are plenty of people who are perfectly nice that haven't perfected their craft yet. They can use this book.

  • by Anonymous Coward on Wednesday September 24, 2008 @02:02PM (#25139495)

    Um, he used proper grammar. He is putting this book beside the other, therefore he is setting it next the other. Both books would be sitting on something.

  • by Nerdfest ( 867930 ) on Wednesday September 24, 2008 @02:04PM (#25139539)
    It's taken me a long time to get myself out of this mindset. I used to always go for the absolute fastest implementation I could come up with. I now generally go with 'fast enough' rather than 'as fast as possible' if the latter is more maintainable. Sometimes the bar for 'fast enough' lowers, but not often.
  • by dubl-u ( 51156 ) * <2523987012@pota . t o> on Wednesday September 24, 2008 @02:12PM (#25139681)

    related code" [sic] are NOT opposites. In fact, I have seen a huge number of situations where I sped something up by cleaning out the code.

    I know what you mean, but the guy has a point. I have also often sped things up by removing "performance improvements" that some dolt had added because he thought he was being clever.

    My view, which I guess you'd agree with, is that it's best to start with clean, simple code. Usually, that's plenty fast. If performance tests prove that you have a problem, and a profiler shows you the source of the problem, only then should you sacrifice clarity for speed. And you should only do just enough to meet your performance goals.

  • by Frequency Domain ( 601421 ) on Wednesday September 24, 2008 @02:22PM (#25139857)

    Comments are for readabilty, not the code. Always go for efficiency.

    I endorse the saying "when debugging, ignore the comments - they can be very misleading." Hence I want the code itself to be readable more than I want it to be maximally efficient.

  • Re:yay! (Score:5, Insightful)

    by Surt ( 22457 ) on Wednesday September 24, 2008 @02:23PM (#25139867) Homepage Journal

    And if he had documented his code, explaining the performance advantages, you'd have read it in an hour and reached the same goal, and he wouldn't have dozens of WTFs to his credit.

  • by Anonymous Coward on Wednesday September 24, 2008 @02:33PM (#25140049)

    Bzzt, fail, please go buy the book.

    http://en.wikipedia.org/wiki/Optimization_(computer_science)#Quotes

    Clean code is efficient and performs well because you can easily see where the issues are and optimise there appropriately.

  • by Tassach ( 137772 ) on Wednesday September 24, 2008 @02:36PM (#25140111)
    No, it's natural to fear the (mis)application of the buzzword du jure. Agile has some good ideas, but like any other development methodology, too many people just blindly follow the formula without really understanding WHY it works or realizing that software development isn't a cookie-cutter process. Any methodology like Agile, or CMM, or whatever, is just a way of keeping the code monkeys in their cages grinding out code. There's only one way to write great code: hire great programmers. Management types love to believe that a swarm of code monkeys can produce on the same level as a brilliant top-tier programmer. They can't.
  • by Anonymous Coward on Wednesday September 24, 2008 @02:36PM (#25140119)

    You're joking I hope.

    Clean is NOT the opposite of efficient.

    >Comments are for readabilty, not the code

    No. NO. NO!

    There is no excuse for writing unreadable code. The code itself must be readable. Then comments are necessary to supplement the code, to help understanding the tricky parts, explain the reasons that lead to choose this or that method to solve a problem or -the most important- explain the INTENT of the code. How many projects (FLOSS and closed source) have I seen that were a mess because they don't bother with those simple and basic principles... Sad.

  • by Enter the Shoggoth ( 1362079 ) on Wednesday September 24, 2008 @02:50PM (#25140387)
    Abso-freakin-lutely! Agile isn't such a bad idea in principle but you tend to find that people who rave-on about it seem to think it somehow relieves you of the burden of creating project plans, software specifications and the like.

    For some reason, whenever I see that word in reference to programming, I want to run screaming in the opposite direction. Does that make me a bad person?

  • by jgrahn ( 181062 ) on Wednesday September 24, 2008 @03:06PM (#25140623)

    Preformance related code and highly efficent code is the opposite of clean code. Clean code is often high level in nature, while efficient and robust code is low level and not pretty.

    Clean code is the enemy of robust code? I've never heard anyone state that before.

    Comments are for readabilty, not the code. Always go for efficiency.

    Even when I don't need it? You don't make sense.

  • Re:Clean code? (Score:4, Insightful)

    by Mycroft_514 ( 701676 ) on Wednesday September 24, 2008 @03:46PM (#25141313) Journal

    LIKE it has to be you - not that it will. If I write code like that, then my buddy can debug it at 4am and not have to call me to fix it. And if his code is like that, I can figure out what is wrong easily and not have to spend hours fixing it.

  • by Eudial ( 590661 ) on Wednesday September 24, 2008 @04:52PM (#25142513)

    There are naturally various considerations: Value caching as you mention, whether the programming language optimizes tail recursion, and so forth.

    But the real shenanigans in the function is that you can use mathematics and find that the sum of the series 1...n is n*(n+1)/2 straight away, so making such a function is a moot exercise altogether.

    On the other hand, keeping that sort of mathematics arcane and shrouded in mystery creates thousands of extra programming jobs all across the world.

  • Re:Clean code? (Score:3, Insightful)

    by fyoder ( 857358 ) * on Wednesday September 24, 2008 @04:56PM (#25142619) Homepage Journal

    Just write the code like it is YOU that has to debug it at 4am.

    It's likely it will be me who has to debug it at 4 am. Writing clear code with helpful comments where necessary makes me appreciate my past self, since if the code is more than a few weeks old, I've already forgotten a whole lot. If it's more than a year old, it might as well have been written by someone else. This is, in fact, how I learned the value of clear coding. It wasn't for others, but for myself. The early shit I wrote in perl looks like something that might originally have been scrawled in feces on the padded cell of someone totally deranged.

  • Re:Good review (Score:3, Insightful)

    by Bill, Shooter of Bul ( 629286 ) on Wednesday September 24, 2008 @04:59PM (#25142653) Journal
    No, it was a good review rather than a slashvertisement. I'm not buying it because you described it well enough for me to tell that it was not the book for me. Although that is the default state, It also means that I won't have to open the book myself, if I see it in a book store.

    Not ragging on you in particular, but I've never bought a book reviewed on slashdot. They all seem to be geared towards the novice. Where is the book review for "advanced systems programing in Haskell"? Or "Algorithms for taking over Delaware" You know, books for nerds.
  • by I cant believe its n ( 1103137 ) on Wednesday September 24, 2008 @05:16PM (#25143011) Journal
    "I confess my doubts. Thanks to the criticism of the comrades, I have been able to purify my language. I bow in humility to the opinion of my comrades and the Party and am thankful for the opportunity to correct my spelling. You enabled me to repudiate my deviational language. I acknowledge my debt to the selfless leader and the government of the people."
  • Re:yay! (Score:4, Insightful)

    by Spy der Mann ( 805235 ) <`moc.liamg' `ta' `todhsals.nnamredyps'> on Wednesday September 24, 2008 @05:18PM (#25143051) Homepage Journal

    Over two days of following the nested ifs, the gotos (no STL, no exception handling, the gotos made perfect sense), the logic, then BAM!

    "Wow, that's fast!"

    And your understanding could've been faster if the author had bothered to include a comment block before the series of ifs/gotos.

    Example:
    /** The following series of if's/gotos are a hardwired implementation of
      * a finite state machine, as documented in the book "Efficient State Machine
      * examples for data processing (ISBN blablablabla, p.15).
      * The machine is as follows:
      *
      * A -> (condition 1) -> B
      * A -> (condition 2) -> C
      * ...
      *
      * The if at point 1 is node A
      * The if at point 2 is node B... etc
      */

    // Point A of the FSM
        if(...) {
            goto B;
        }

    True, comments aren't an excuse for bad code, and WTF/min aren't necessarily accurate. But difficult to understand code without proper in-code documentation is a potential disaster. In fact, I'd call your example a mega-WTF for its lack of comments.

  • by ChatHuant ( 801522 ) on Wednesday September 24, 2008 @05:24PM (#25143149)

    int sum(int n) {
    if(!n) return 0;
    return sum(n-1) + n;
    }

    Ouch... Your function fails miserably if n is negative. Check if n greater than 0, not !0

  • by sfjoe ( 470510 ) on Wednesday September 24, 2008 @06:00PM (#25143715)

    Sounds to me like the problem was with the idiot who signed a SLA allowing for that much downtime and to the owners of pagers for turning them off without investigating. IT worked as it should have.

  • by greg1104 ( 461138 ) <gsmith@gregsmith.com> on Wednesday September 24, 2008 @09:59PM (#25146185) Homepage

    If you're operating in integers with a fixed range, computing n*(n+1)/2 might overflow in situations where computing the sum via a series of additions will not. You need to consider which of (n,n+1) is even, divide only that one by two, then multiply by the other odd term to get something that is both a fast computation and utilizes the full range of the integer size you're working with.

    While the above might seem simply pedantic, consider the case where a program built using a naive sum approach that needed the full range was broken by replacing it with the multiplication-based approach. That sort of issue, where clever code is more fragile than the simple implementation, is one reason some programmers shy away from being too clever.

  • by Raenex ( 947668 ) on Wednesday September 24, 2008 @10:59PM (#25146697)

    Ken Iverson was a Real Man of Genius.

He has not acquired a fortune; the fortune has acquired him. -- Bion

Working...