It is not everyday that a post offers some valuable insight into a subject and I have the feeling that it all fits together.
This weekend, after reading Steve Freeman’s “Bad code isn’t Technical Debt, it’s an unhedged Call Option” in which he advocates the theory that bad code compares to financial instruments that can bring massive losses when the market moves into an unanticipated direction and that refactorings are the premium we pay so that we can have more choices in the future, it all made sense to me.
How many times I saw tasks I estimated in hours taking days to be finished due to bad code that simply wasn’t adaptable enough? How many times I spent hours and hours due to hacks, lack of proper documentation, awful APIs and unreadable, non-intuitive code? I might be extending the concept of bad code, but I wonder how much of my estimation errors are due to bad code that simply cannot be used or adapted smoothly.
All this unpredictability now makes sense to me as the result of bad, non refactored code. And, as Steve points out, this is not a debt you choose when to pay. Actually, at a given time, you don’t even how much it is going to cost you. All it takes is the market going in an unanticipated direction – be it a new requirement, a new business rule – and the price, whatever it happens to be, has to be paid.
The post also reminded me of the TDD cycle proposed by Kent Beck and the method to compare technical solutions proposed by Jerry Weinberg in The Psychology of Computer Programming.
Kent Beck suggests the TDD cycle as the steps: write the specification (tests), write code that works (meet the specification), refactor. I can’t remember how may times I see the last step omitted – myself being guilty as well.
Jerry mentions that the most important questions to be asked of a technical solution are, in this order: Does it work? Can it be done on the time we have? Is it adaptable? How does it perform?
All these things now fit together for me and I would say the most important thing for a technical solution is its ability to address the present – it has to work and it has to be doable in the amount of time we have. The second most important attribute is its ability to address the future in a timely fashion, something we can only hope to guarantee by making our solutions adaptable enough through constant and diligent refactoring.