Project: Quick & dirty

Dijkstra would not like it

Image for post
Image for post
“I mean, if 10 years from now, when you are doing something quick and dirty, you suddenly visualize that I am looking over your shoulders and say to yourself “Dijkstra would not have liked this”, well, that would be enough immortality for me.” — Edsger W. Dijkstra, both leader in the pursuit of simplicity and the abolition of the GOTO statement from programming.
cost (quick) < cost (clean)
  cost (quickAndDirty) 
= cost (quick)
+ cost (dirty)
  cost (quickAndDirty) 
= cost (quick)
+ cost (clean)
cost (quickAndDirty) > cost (clean)

Impact over time

Image for post
Image for post
Even when coded “cleanly” (debt is zero here), the complexity of the built software increases over time along with the code size (accumulation of new features delivered). Without regular refactoring, the maintainability decreases as the code gets more and more complex and the cost of adding new features in such a poor code increases. The curve of delivery flattens and in the end you cannot deliver anymore (logarithmic scales are used here to better show evolutions over time).
Image for post
Image for post
As the technical debt increases, maintainability decreases half earlier, down to a level where no delivery can be done anymore (flatline of shipping) as the code got too hard to maintain without breaking things. The cost of development curve steepens for the same reasons: because of the poor quality code, it takes longer and longer to produce new features without breaking existing ones.

When to handle technical debt?

  cost (quickNDirt1) 
= cost (quick1)
cost (cleanDev2)
= cost (dirty1)
+ cost (dev2)
Image for post
Image for post
With systematic cleanup the debt never increases more than one iteration. Maintainability gets jagged (because of each dirty-then-cleanup cycle) but keeps an acceptable level longer, allowing to deliver longer as well. Cost is sometimes higher tough, as cleaning is more costly (=2) than dirtying (=1).
  cost (quickNDirt1)
= cost (quick1)
cost (dev2)
= cost (dev2)
cost (cleanDev3)
= cost (dirty1)
+ cost (dev3)
  cost (quickNDirt1)
= cost (quick1)
cost (quickNDirt2)
= cost (quick2)
cost (cleanDev3)
= cost (dirty1)
+ cost (dirty2)
+ cost (dev3)
Image for post
Image for post
Not resolving all the debt makes it increase progressively. The cost saved by not cleaning up all the debt (quick dev) is actually increased by the bad consequences on maintainability, which falls earlier, thus impairing the delivery capability more quickly.

Even clean code requires refactoring

Image for post
Image for post
Avoiding quick & dirty to avoid debt is not enough: another kind of “implicit” debt with the increasing complexity of the product, and adding periodic refactorings allow to mitigate the loss of maintainability while keeping a good delivery pace, while not making costs worse.
Image for post
Image for post
Quick & dirty, if cleaned up, look similar to the clean code approach when including refactorings, but is a bit more costly and fails in maintainability earlier, because of the time lost in a subsequent cleaning up iteration (instead of writing clean version directly). As a result, delivery is less optimal.

Conclusion

— Why refactor it, since we’ll rewrite it from scratch in two years?

— To avoid rewriting it from scratch in two years.

Software engineer for three decades, I would like to share my memory.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store