Thoughts on Code Documentation
Over the past few months, I’ve worked on a rather big project: the Ozon.ru, one of Russia’s leading online stores, iOS app. What’s even more important than its size is the fact that the app is constantly evolving—both on the inside and the outside. With hundreds of commits added to the trunk branch weekly, one has to read and understand a lot of others’ code to stay current on the latest changes.
One of my key takeouts from working on the project is the notion of code documentation’s importance in the process of software development.
First of all, it’s worth outlining what code documentation is and what it’s not. By code documentation I don’t mean a couple of comments sparsely added to the most difficult-to-comprehend expressions. I prefer to see documentation as a routine thing that supplements every piece of code, especially those exposed to an outside scope (i.e. used beyond the current class). It’s something like what you can find in Apple’s own frameworks.
For the purposes of this post, I define three degrees of documentation quality and completeness: okay, good, and great.
A code comment is okay when it tells what something is. Such a comment may often seem silly and redundant, but once in a while it becomes a lifesaver. Developers are people, too, and every human being sees the world in a somewhat different way (duh). That being so, even the plainest and most straightforward names imaginable can be confusing or misleading to some.
Let’s say you see the class
Human which has a property named
numberOfFingers. How are you supposed to know whether thumbs count? Is this about only one hand or both? No doubt you could look for a separate property for thumbs, or ask whoever wrote the code what they meant (if they’re still around and available). But you’d waste a great amount of time when all you needed was a concise comment: something like
The total number of fingers (including thumbs) a human has. Easy, right?
Naming policies and guidelines help prevent some of such situations, but they’re not fail-proof, so by adding a short comment you hardly lose anything.
A good comment explains what the code does. It’s what you want the function or the service to do when you write it. A good idea is to mention certain characteristics which are not obvious, especially if they can backfire: the fact that the method requires internet connection, or that it may return on a background thread. That way, people who rely on the code you wrote won’t be wondering why it functions not the way they expected, and won’t have to spend time on debugging and troubleshooting.
Finally, great code documentation makes clear why the code functions the way it does and why it’s even needed, in the first place. It describes the rationale behind the class, method, or property itself, as well as the way the code is organized: why the author has decided to decouple a piece of functionality into a separate method, for example, or why it seemed best to use the delegate pattern instead of closures. Doing so will ensure others understand the principles behind the design, which will help align future developments of the code with the existing code base.
As you can see, even the plainest documentation which simply describes what the piece of code is saves time, in contrast with the (likely) #1 reason against writing code documentation you might hear (the one that states writing documentation is a waste of time and not useful enough).
Now, what about that “self-documenting code” concept you might’ve read about? Personally, I just don’t buy it. I’m not denying the hypothetical existence of such thing, but unfortunately, it’s too impractical in most cases.
The problem is, self-documenting code depends on the big picture: once you’ve grasped the whole, its individual parts make sense to you, and property and method names alone would be enough to understand what they do and why they’re there (in other words, they would self-document). But way too often, all you have are individual pieces which you must recreate the whole thing with in your mind. Without some kind of entry point—in the form of either a detailed description of the big thing, with all its core ideas, design principles, etc., or documentation of its separate parts—it’s a classic chicken-or-egg problem.
In my work, I try to document as much as possible, without getting too explicit. Instances of the core design structure that’s reused across the app (components of a single module, for example) probably don’t need the same comments boilerplated over and over again. However, every one-of-a-kind thing (e.g. an internal service, a networking client, etc.) requires a detailed documentation, in my opinion.
As a bonus, many IDEs make working with documentation embedded in code really neat. Xcode, for example, can show notes for types, properties, and methods when you option-click them. This feature, in most cases, eliminates the need to jump back and forth between calls and definitions.
Xcode also makes it really easy to add new comments: pressing option + command + / will add a stub which you can extend as needed. What’s more is Xcode supports a set of keywords that provide rich markup capabilities for structuring the comment into sections, such as Returns or Important.
One of last year’s WWDC sessions, namely 239 Great Developer Habits, was all about the culture of software development, and among its key points was the importance of comprehensive code documentation. This session resonated with me greatly, and I encourage you to watch the video. The speaker gives a few advice which, once implemented in the daily routine, flatten the learning curve for new team members, and save a lot of time and effort for everyone.