Application-Level Documentation Beats Code-Level Documentation

Or how to dramatically reduce training time, speed up recovery during disasters, and make future programmers love you

This article is part of my Confessions of an Unintentional CTO book, which is currently available to read for free online.

First off, what is application-level documentation? It’s documentation that addresses the big picture, such as what the software does, how it’s built, how it’s deployed, and so on. This type of documentation stands in contrast to API- or code-level documentation, which, by contrast, zooms in to describe functions, classes, and algorithms.

My ideal application-level documentation would do the following:

  • Explain how the business works. The reasoning here is that a programmer who understands your business goals is empowered to intelligently prioritise competing claims on their time. At Oxbridge Notes, the first page of my application-level documentation links to a three pager called "How We Make Money". This document describes our business model and includes information about the relative sizes of our various revenue streams.

  • Describe the major flows through the web application (e.g. buy something, apply to become a content provider, etc.). In sufficiently large codebases it’s absurd to maintain (as many grisly programmers do) that "the code documents itself". I believe that a one-minute video which runs through the major features—while flipping back and forth between the user interface and the code editor—will save programmers hours of head-scratching. Not only that, but such a video would provide the new contributor with an easy-to-remember holistic orientation. Of course, if you don’t want to record videos, you could instead direct the reader to visit the website and run through major flows X and Y manually, thereby enabling these new contributors to see these flows for themselves.

  • Elucidate the overall architecture insofar as it differs from the standard practices in your chosen community (e.g. Rails, Django). Here I’d expect details about how you divide your functionality into various servers and how you organise your major sub-systems/namespaces/modules (e.g. at Oxbridge Notes I organise the code into systems like Accounting, UserManagement, Shop, AuthorManagement, Discounting, Downloaders, and Converters).

  • Detail how cross-module functionality works, i.e. features that span more than one model or namespace. This includes the philosophy behind your caching system, the strategy you use for internationalisation, the way you handle time zones and money, and your rules for SEO (e.g. rules for canonical URLs, SEO meta-text, RSS feeds, sitemaps, etc.)

  • List any coding style guidelines that you want collaborators to follow. Needless to say, you need only include guidelines that are not already generally accepted standards within your community. Be aware that this decision needs to be made on a language-by-language basis. For example, I follow the consensus practices in the Ruby world, so my documentation includes no explicit guidelines for Ruby code. But I do include guidelines for CSS, since I find many of the existing recommendations to be ill-advised. (If you’re curious about my CSS guidelines specifically, I’ve published them in my guide to refactoring CSS that I co-wrote with Adam Niedzielski.)

  • Explain your backup system—how does it work, how can you save a backup, how do you restore one, and how do you set the whole backup system up again should it break down for some reason?

  • Provide every detail about setting up a production server. I really mean it. I’d expect to see every expected environmental variable, the full NGINX configuration(s), a detailed list of other dependencies expected to be on the server, etc. Deployment setups are frustratingly fragile, and when they fail, they fail disastrously. Thus it pays to keep their documentation up to date. (Of course, it’s even better for this documentation to be stored in the form of provisioning/deployment scripts.)

  • Describe how to set up a development machine so that someone can begin writing code quickly and painlessly. How is the local database installed? Are any startup scripts required at the OS level? What versions of programming languages and other dependencies are needed?

  • Similarly, describe how to outfit your testing environment for the first time and then how to run your tests.

  • Explain the reasons why you chose a particular third-party library over another (or a particular branch of one library instead of the standard version). Without this information, a future maintainer might replace an incumbent library with another, more popular one that performs that same function. This maintainer will be unaware that you chose the existing library owing to its inclusion of a rare “must-have” feature or simply because it was the only library that didn’t namespace clash with other parts of the code.

  • Detail your source-control workflow. What is the purpose of each long-term branch like master and development? How should they be employed? What are the company policies for merging and pushing code? How can new programmers avoid making a mess in the commit logs? Are there commit hooks that programmers are expected to run?

  • Explain the folder structure of your application insofar as it differs from your community’s conventions. A new programmer unaware of your project’s organisational idiosyncrasies cannot be expected to adhere to them. As such, your documentation should describe the purposes of non-standard folders and the purposes of each of the various files lurking in your project’s root directory. Here I’m talking about the “.env”, “.ackrc”, “tags”, and “.slugignore” files. Yes, it is obvious to you why these files are present, but the point of documentation is to think past your own needs and toward those of other people without your experience.

  • Furnish any IP addresses/URLs where collaborating programmers can view the software running—e.g. in production or staging. Don’t forget to include these details for every server—it’s not enough to only include addresses for your primary user-facing web app. At some point or other, your programmers will need to deal with your behind-the-scenes services.

  • Give links and login details for appropriate administrator or other accounts on your software. Include credentials for the various third-party software solutions you rely upon (for example test accounts for sandboxed Facebook or PayPal services). Finally, list any email addresses associated with the software.


More Articles: Click here for full archive

log_tokens

A simple technique to make your logs more useful when debugging


Debugging Rails With Built-in Tools

Lesser known tools built in to the standard stack - such as the middleware lister, Gemfile.lock, Ruby compiler checks, rails dbconsole


Replayability

Why your code should be capable of remembering and replaying inputs in the event that something goes wrong