Whenever we find a severe bug that is caused by an error in a complicated piece of code, in my experience, the first instinct is that better documentation is needed. So that the next time we need to debug the code, at least we know what it is supposed to do. I argue that this is a waste of time.
The 5 Pillars of a Self-documented Codebase
- Write detailed tickets and user stories.
- Document decisions (in decision logs or your tickets).
- Practice BDD style TDD and write high-quality tests.
- Keep your code simple (constant refactoring!).
- Write meaningful commit messages and keep a clean history.
If you feel the need for extra documentation, you probably screwed up somewhere above. When facing a situation where adding more documentation feels necessary, more often than not, what you should do instead is to work on your code and make it simpler.
When practicing TDD, you should feel comfortable doing that because your tests guarantee that you don’t accidentally break anything during refactoring. Your test scenarios (and the tickets that you’ve linked to the code via the commit messages) tell you exactly how the code should behave. Furthermore, great commit messages will inform you that you introduced this obscure piece of code because of that weird edge case you have to watch out for. Of course, an accompanying test will make sure you don’t forget to deal with the edge case anyway.
Now, if you think: yes, in this hypothetical perfect world where I have those 5 pillars in place, I probably don’t need documentation. But, of course, the projects we work on don’t check all of the 5 boxes perfectly all the time. But if they don’t, the first thing we do shouldn’t be to introduce an additional box we need to check: documentation. If you fail at doing 1-5, why do you think you’ll be more successful at doing yet another thing?
Code Is Documentation
Programming languages are designed to help express complex relationships and conditions so we humans can understand them easily. If our code fails to do that, we failed.
Of course, there are exceptions to that. For example, sometimes, we have to solve very complex problems which demand complex solutions. But most of the time, what we’re building is yet another CRUD app. So if our code is complex, it is because we made it so and didn’t understand the problem domain well enough before starting coding.
When we design our workflow to follow the rules of the 5 pillars, we don’t need to write extra documentation because the documentation will be a natural artifact of our daily work.
Write (Extra) Documentation!
I exaggerated a bit to get my point across. I hope you forgive me. There certainly are situations where it makes sense to write documentation.
Suppose a problem is inherently complex and, as a result of it, requires a complex solution. Or if you failed at erecting the pillars 1-5 and you have to begin somewhere, then documenting the mess probably seems like the most sensible way to move forward in the short term.
Also, if you’re good at writing excellent documentation and have processes in place to keep it up to date: that’s awesome! You absolutely should continue doing that.
Last but not least, if you mastered 1-5 and want to do an even better job, you’re in a good spot to introduce a 6th pillar and start documenting your code in a wiki, for example.
And those are just a few instances. There are certainly a lot of other good reasons for writing documentation.
Wrapping It Up
The point of this article and its sensational title is that time is finite, and you should invest it where you expect the best ROI. We should spend most of our time nailing 1-5 before we load up on additional work. Writing good documentation is a very time-consuming process. I don’t think we can afford it as long as we have severe deficits in other areas of our process.