Archive for August 8th, 2005

TDD and Intentionally Violating the DRY Principle

Monday, August 8th, 2005

Anyone that knows me knows that I’m a huge fan of TDD. Not just TDD for testing - but TDD for architecture (and many other things too).

I’m currently working on a project where I generate a lot of pdf documents. I had a couple of big-picture ideas for how to write the code, but there were a few things that I knew would emerge and become clearer as I starting writing the code. When we finally picked a pdf-library for the document generation I quickly found out that the API was horrendous. There were areas that this significantly complicated the “ideal” architecture for the application (at least the way I had originally envisioned it).

I didn’t try to do much BDUF (intentionally), so I figured I would just let the code and the circumstances tell me what to do and this pretty much how it went…

  1. I wrote the implementation for the drawing (the api I’m using is based on a nasty coordinate system used for generating pdf files) of the first document.
  2. I wrote the implementation for the drawing of the second document, and the third document, and the fourth document.
  3. I noticed that I was duplicating a *lot* of code (it was nasty code too).
  4. Since I had tests around everything, I figured I could easily refactor and remove the duplication. Unfortunately, I couldn’t figure out how to refactor the duplication out to something clean. At this point, I got a little worried. I typically like to remove duplication as soon as I notice it. I had a lot of duplicated code in three different places and to say the least — I hated knowing that it was duplicated. I wasn’t sure of what to do so I kept duplicating code. The code that was being duplicated wasn’t one-for-one, but it was close enough that it was obvious that at some point it should by consolidated and reused.
  5. I wrote the implementation for the fourth document.
  6. I started to see some common patterns where I could start to pull out the duplication.
  7. I wrote the fifth implementation.
  8. I had a good weekend.
  9. I started refactoring and was finally happy (thank god for tests).

I usually follow the red-green-refactor cycle but in this case I just wasn’t sure how to refactor. After lots of duplication and more experience I learned more about the API that I was using and this allowed me to refactor back into code that *felt* right. I still have some duplication, but I’m sure as I write a few more implementations that the duplicated portions will work themselves out like the other duplications did.It’s interesting, because I would usually have recommended to remove the duplication at the first (or second) sight of the repetition.