Do the simplest thing.
I’ve also heard: Do the simplest thing that you can refactor later.
In TDD, you attempt to do the simplest thing to allow the real design emerge and to not add unnecessary code that is not needed. This tends to reduce the complexity of the code. There is plenty of writing about this – such as http://www.extremeprogramming.org/rules/simple.html and http://martinfowler.com/articles/designDead.html#TheValueOfSimplicity.
More than a year ago I did a new piece of work. The team completed it and I went back to look at the code and saw that I could simplify it in several ways. One of those ways was to remove an unused parameter as it was always the same id for all the objects in the list returned. We did the work and life was good. I felt that we were achieving simple and changeable code. I felt good.
A month or so later we needed to change the way we fetched these objects to now be fetched so that the single id was now actually varying. A developer attempted this task for two days and we gave up doing the work as we had a simpler solution that the client was happy enough with.
I felt like the whole point of developing with tests and being safe was to make the code easier to change and here I failed. Miserably.
So I retrospected…
Perhaps the removed complexity was important all along – as very rapidly it was needed.
Perhaps the code base isn’t as intuitive as it could be.
Perhaps the dev wasn’t good enough to see how to change the code easily.
All of these may be true. In particular I observed two things:
- Misinterpreting the need: The usage that we had from the UI that we could see was simple – needing only the objects for 1 id at a time. The common usage of related lists was often with varying ids. I had assumed that was a complexity added unnecessarily, but in retrospect it actually was the needed requirement when analysing what the callers were really doing at a higher level. The problem being that the callers aren’t doing that and the code is highly convoluted and hides that – but they should be. Since then I have also change the way I look at building up things like this – in order to make things simple – and this would also have led me to the correct need of loading with varying ids initially.
- Expectation to change: I knew that the code was likely to change in this direction and I actively removed it in a pursuit of simpler code. Perhaps looking ahead a miniscule bit is valuable to support the open/close principle in the short term. If I had left the complexity it would already have been able to deal with this change. I’m not 100% comfortable with this thinking. In Agile Principles, Patterns and Practices in C#, Uncle Bob suggests only making such a change when the code changes in that way. Guided by that principle, it shouldn’t have been there. But in this case it was there already (it wasn’t test driven initially… this part was inherited.) I do suspect misinterpreting the need is more the root cause, though this is worth pondering and entertaining and experimenting with the tension that gets introduced.
So maybe it is useful to think of: Do the simplest thing that you can refactor later while keeping in mind how the current design is already telling you it needs to be open for extension?
But more likely, simple is hard, and you need to dig deeper to ensure you have the depth of the real need the code is fulfilling.