Archive for June, 2010

Book Review: Clean Code

Posted in Programming on June 15th, 2010 by Aviv Ben-Yosef – 6 Comments

This is another post in my book reviews series. I finished reading Clean Code a few days ago and loved it. It makes me feel good, seeing my decision to wear the Clean Code wristband a few months ago was a smart one.

After I finished it, I felt a bit weird writing a blog post about it, because, just like the previous books I’ve blogged about, I found this book simply awesome. Then I thought about the fact it’s simply because I’m reading those books that show up enough in other contexts that I upped them in my reading queue enough to get on top.

The book is about practical, low level details of writing good code. There are chapters about comments, naming, functions, you name it. In a way, it reminds me of Code Complete, other than the fact you can see it’s oriented for more practiced developers.

Like in his Agile Software Development book, Uncle Bob made sure to fill this one with code. Actually, this book has a lot more code. There are many examples of code still being worked on. It actually fills the gap I’ve felt in Agile Software Development of seeing the actual coding steps, test by test. The last chapter shows a really thorough (and actually quite mesmerizing) example of refactoring, with each change explained beforehand, including tests and alternatives considered.

In Agile Software Development, there were a few co-authored chapters. In Clean Code Uncle Bob took this a step further. Almost every chapter was written by a different author, each of very big caliber in the Agile and Software Craftsmanship world. This really resonated with me, because it’s kind of a “many in one” deal, and because I could actually hear a different tone in each chapter, and yet all were in harmony with the motive of clean code.

I think this is truly a masterpiece, and after reading, would recommend it to be read before Agile Software Development. Due to its greater technicality and the fact it’s quite new, it makes a really good read for developers, and it will have an effect on your coding a few pages in (pages! not even chapters).

The only thing that bothered me was that in the last chapter (which is also the best) I had to, as the introduction warned me, flip back and forth quite a bit, which was a bit hard at first since I’m not used to reading code on paper. I’d really love seeing some interactive version of this, but regardless of that, the book is really good.

I can’t recommend enough this concentrated piece of wisdom and experience.

Stay tuned, a review of Apprenticeship Patterns is nigh.

You should subscribe to my feed and follow me on twitter.

Case Study: Refactoring Interfaces with TDDed Tests

Posted in Programming, testing on June 2nd, 2010 by Aviv Ben-Yosef – 1 Comment

I’ve been practicing TDD for a couple of years now, and keep learning all the time.

In the past year I’ve been mainly working on a single project, the longest I’ve worked on a project with TDD. Putting aside how fun it is (TDD saved me quite a few times for me to be sure it’s worthwhile), working on a project for so long I finally got to see some of the main problems people have against TDD.

With the hundreds of test you have, refactoring on the class-interface level (that is, the interfaces of classes, and not inside classes) can be problematic, with you having to update all the tests.

I’m still learning how to handle this efficiently, and would like to share an experience I had today. This is an example of a problem regarding 2 collaborators and an interface change. Such refactorings in a TDD environment weren’t mentioned in the excellent “TDD by Example” book and similar works, so I’m pretty much guessing here.

The example:

The change we’re interested in is making “eject” simply open the lid, without rewinding, and making the rewind operation public. This is in order to allow LazyPerson to take the tape out, without having to wait. Gary Bernhardt wrote about this kind of changes a bit. I agree, the fact I need to make such a change is against the OCP. What can I say, I’m not perfect and made a design mistake. Saying “that’s not OCP” doesn’t help me – I’ve got this code and tests, and I need to change them.

I used to succumb to the temptation and make all the changes in one sweep. That means changing all the tests and the classes, then running the tests and hope they still pass. This, of course, is a crappy way of doing this. Had I been able to actually perform such tasks, I’d write less tests. The secret is baby steps. The pressure Kent Beck puts on baby steps and gradually working towards change made me consider this and force myself to find a safe way of doing this.

I decided to start with the VCR and its test (the AutomaticPresenter doesn’t use the VCR itself but an interface, and the tests use test doubles. This means changing one part won’t break the other’s unit tests). The path to enlightenment lies in finding the baby step that allows starting the refactoring without breaking the rest of the tests. I decided to add a test for the should-now-be-public “rewind” operation, while not breaking the existing tests.

The solution is adding a default value for telling the “eject” function whether it should rewind or not. This means existing users (be them tests or not) will still get the previous behavior, and new tests can start work with the new interface (in Java I’d probably do this with method overloading):

This got me to green pretty fast. Now I can slowly remove every rewind-related assertion from the old tests and also add the “should_rewind=False” flag to them, all with quick-green cycles. And we’re done with the first half.

The next move is to change the AutomaticPresenter to call “rewind” before “eject”, which is now really easy to do in the tests. Once we hit green, we remove the “should_rewind” flag and be done with the refactoring. Baby steps save the day:

Being able to get the refactoring working so easily makes me happy, but I’m still not sure this is the smartest way, and there are harder refactorings to master ahead. Yet, I hope this will help TDD adopters see that it’s possible to handle refactorings even with many tests, because once the right baby-step is found, each test can take practically seconds to convert.

I’d really love getting feedback on this cycle.

You should subscribe to my RSS feed or follow me on twitter!