Wednesday, June 11, 2008

Resetting the 'Shitty' Counter

Again and again I hear the following phrase: 'This code is so bad that it has to be rewritten'. That statement is right in some cases. Even though I prefer to refactor, there are situations were it does not make sense any more. Most code bases can be salvaged with major and persistent refactoring efforts. Over time your refactoring skills get better and better and more systems are cureable but still, some cases are what they are: terminal.
What does it really mean to rewrite a system? It is the defeat of the software team. Often the existing team inherited the system, or worse they are the original authors. In either case, no team was able to make the code base more maintainable or at a minimum not to make it worse. The project lacked fundamental skills like team communication, best coding, configuration and testing practices. They failed -- the code rotted in their hands!
Next, this team decides to rewrite the system and promises to make everything better the next time. Sounds good? To me, it is more like a broken record. Why? They will repeat most of their mistakes and eventually call for another rewrite. Sure, the team learned from some of the old mistakes, but still this does not suffice to prevent another decaying code base. The rewrite means basically to 'Reset the Shitty Counter' [1].
Now your Counter is at zero, but unless you take matters in your own hands and actively manage the risks of your old mistakes your 'Shitty Counter' will slowly inch upwards. Well, ... you know the story!
How can this be achieved? There are many best practices from the agile world and even more books about those. It would be foolish for me to try to explain each of them and their dependencies and how they interact.

However, I will give you my elevator pitch:
  • Test Driven Development (TDD)
  • Pair Programming
  • Continuous Integration
  • Co-location of programmers, testers and domain experts
  • Scrum (do the Nokio Scrum Test to make sure you really do it [2])
  • Never ever change the length of your iteration
  • Determine you velocity
  • Retrospectives after every iteration [3]
From a code point of view, one should aim for:
  • Short methods (not more then 10 lines per method)
  • Single Responsibility Principle per Class
  • Low complexity (McCabe or CCN)
  • Loose Coupling and High Cohesion
  • Law of Demeter
  • Injectability (ie. Spring, Google Guice, PicoContainer)
Static Code Metrics
  • Test Coverage (use with caution unless you have many small tests)
  • Testability of Code (Testability Explorer) [4]
  • Percentage of duplicated code (CPD) [5]
These are the tools of the trade of an agile test infected code warrior. If you use those best practices on a daily basis and refactor your code mercilessly. Over time your code base will actually become better. It is not easy, it is a skill you learn by doing manually, day in day out.

[1] This term was coined by a colleague of mine
[3] Agile Retrospectives (Esther Derby & Johanna Rothman)