Over many years I have seen people claim that good code is “self-documenting”. I’m pretty sick of this argument and I wish that as a profession we could put it behind us. This is nothing but an argument used by lazy programmers who don’t want to put the work into documenting their code.
Just try understanding 100K liners of code without any documentation what-so-ever. It doesn’t matter how clear the code is. It will take you weeks or months to understand (if you ever do). This pain can be at least partially short circuited with extensive documentation.
The problem that any experienced programmer has reading an unfamiliar software base is not what the code does (they can see that by reading the code), but why it does what it does. Working with a new software base requires an understanding of the software architecture and how the pieces fit together.
So, here for your enjoyment is some simple code. Anyone who can program should be able to understand what it does (“there’s this array and it’s calculating an average…”) There’s even some documentation. So please tell me, what does this code do?

As it turns out, this code is a fragment of a code that implements a signal processing technique called the “wavelet lifting scheme”. I wrote many pages of documentation describing what this simple code does. The material I wrote was taken from a much longer paper by Wim Sweldens.
Perhaps you might respond “that signal processing stuff is very specialized, so of course it has to be documented” What about a database that consists of tens or hundreds of thousands of lines of code? Self-documenting? What about a compiler? Self-documenting too? What about a bank market order processing system? Self-documenting?
Here’s another thing to think about. You write documentation not only for others but for yourself.
nderground consists of over 15K lines of Groovy and Java, built with the Grails framework. I’ve had to write relatively little code because I can leverage Spring, Hibernate and the vast Java ecosystem (e.g., Apache and many open source packages).
I will often spend a few weeks working on one part of nderground. When I return to another area of the code, I may have forgotten how I did something or why I wrote the code in a particular way. Often there are are complex issues that were addressed in the code that I later forget. So I read the my own comments to remind myself about what the code is doing.
Sometimes, I find that the comments are not as complete as they should be, so I am forced to work through the logic again. If this is the case, I improve the comments. I also maintain the comments along with the code. The comments are as much a part of the application as the executable statements.

When you build a complex system like nderground, there are hundreds of decisions, large and small that go into the design and implementation. I have extensive notes that I wrote as I developed the software. These notes describe the choices I made (e.g., why I used DynamoDB and not MongoDB or Riak). Without these notes, months or years later, I will have forgotten why I decided on a particular design. There are also notes on systems issues, like forwarding HTTP to HTTPS. I really hate having to figure out something twice.
Here’s the bottom line: the difference between an engineer and a coder is whether they write documentation. Documentation is also one of the things that sets successful software development groups apart from groups with failing software projects.
Be a professional. Document your code and use something like a wiki (e.g., Atlassian’s Confluence) to document all of the issues that surround the code.