One of the many catchphrases I use with my team is Fix it twice. This refers more to the Red – Green – Refactor cycle. For clarity, that’s usually used during TDD where you go Red – a failing test. Then you do whatever it takes to make the test pass – Green. Finally, you review the code you’re left with and, with the security of the unit test around you, you refactor it to the simplest possible design/structure for its current feature set.
Where I say Fix it twice, I’m usually referring to the rare case of a bug-fix or similar. With TDD you don’t get bugs so much, because your tests kind of prevent them. You do, however, get some surprises at later points. Tests are never perfect, and some issues only rear their heads when you add more features. So at some point, you need to apply a fix to existing code to make it do what it ought to have done all along.
We still use TDD for bug fixes, you can’t be sure you’ve fixed it until you’ve found a test that needs it to be fixed in order to pass. The problem can sometimes be that you don’t know the scope severity of the fix until you’ve had a crack at solving the problem, after which you can be left with code that’s not at your usual standard.
Refactoring alone may not make the root cause of your problem better. But, once you’ve fixed the code once, to get something that now works again, you’re usually in a better position to judge what you should have done all along. This is the Fix it twice of which me and the team speak.
Maybe you revisit a root cause of the bug. Maybe you generalise the code to avoid edge cases that need resolving individually. Maybe you add more tests to prevent a naive change causing a surprising regression. The philosophy of Fix it twice is the solution to the classic case of L’espirit de l’escalier that we encounter in life sometimes, where you wish you’d said something different in a conversation that’s now over. In software you’ve always got the chance for a better do over.