Skip to content

Documentation

As we're joining a new team, our manager points us at a Confluence page so we may read up on the team's practices. While Confluence has yet to generate any tingle of excitement across our entire career, we're thrilled at the potential of our new tasks and eager to get started. Dutifully, we read through the onboarding pages and start following the instructions.

Alas, only three steps into the process, a link to a sign-up page returns a 404 error. We consult a team member, who explains that the company migrated their SSO solution and sends us an updated URL. We continue our onboarding journey. A couple of minutes later, a setup script fails. Checking the source, we realize that the script's command flags differ from those in the documentation. Together with our helpful teammate, we unravel the required command structure and complete our onboarding…

Since we followed an internal guide, we were able to reach out for immediate and actionable help when the documentation misled us. Moreover, because we are at work, we had no alternative but to remediate our blocking issue. Were a potential customer to encounter a similar issue during their self-service onboarding, they would take their business to a competitor rather than reach out for help.

Missing documentation can be frustrating, but misleading documentation actively harms our organization. If we offer no guidance, our users may roll their eyes and start looking for help elsewhere. Yet, if they follow the officially supported guide and discover it conflicts with their actual experience, we erode trust in our brand. Therefore we treat documentation as part of the software development lifecycle rather than as an activity we consider after the fact. We do not document everything, but we ensure the documentation we provide remains trustworthy, discoverable, and useful.

In this chapter, we look at the different kinds of documentation we create, how they differ in purpose and maintenance, and how we manage them as an integral part of developing and delivering software.

Documentation as Code

Organically, source code changes faster than its accompanying documentation, a fact we've termed documentation drift. In fact, throughout this book we discuss a range of processes, tools, and automation to speed up software changes. Engineers intuitively agree that this approach is worthwhile for code, but we sometimes fail to apply the same procedures for work other than our source. Documentation is part of our product and we need to treat it as such.

Useful documentation evolves at the same pace as the source code it references. To ensure complementary development, we manage our documentation within the same version control system as our code. The alternative - storing ephemeral words on a separate platform - leads to unseen drift and an uncertainty as to when the docs were actually up to date. Documentation stored within a VCS correlates to the state of our code at any point in time.

We work on documentation using the same strategies and tools we use for working on product features. We create feature branches and integrate changes via a merge request. We define a documentation style guide and run automated tools to verify the documentation's compliance with our ruleset. Our peers review the documentation and potentially request changes before accepting the contribution. Periodically on main, we crawl the hyperlinks in our documentation and confirm a successful response.

Unlike other dependencies, incorrect documentation does not break our build. Thus, errors and oversights in our documentation surface once a user relies on it, not before. Actively shifting left on documentation mandates that we build automation tooling for its continuous integration and delivery. We continuously consider our readers' needs and extend, adapt, move, or delete our writings accordingly.

The previous chapter mentioned how we extract changelogs from merge requests and closed tickets. We can extend the practice by generating reference documentation directly from our source code. Using the actual implementation as the source of truth reduces the possibility of human error in our documentation artifacts.

Just as we write source code and deliver a built, packaged binary, we define an authoring format for our documentation. Popular choices - such as Markdown, LaTeX, and AsciiDoc - come with broad support and community tooling. Using these tools, we build the needed presentation formats. We generate and upload HTML pages to our documentation webpage, we bundle raw text files with our product, and share PDF documents with our sales team.

With the mechanics of maintaining documentation in place, we turn our attention to its content. What should documentation contain, and how should we structure it for our readers?

Diátaxis Framework

During his time at Canonical, Daniele Procida polished his work on a technical documentation framework, Diátaxis. Daniele's work builds on the philosophy that technical documentation has competing goals depending on the reader's context. Depending on their goals and state of mind, our readers require specific support.

For example, our live production database fails and requires a reboot. During this stressful task, we do not benefit from documentation highlighting why we switched from a relational database to a document store; instead, we need strict and isolated instructions on what scripts to run and resolve any errors we encounter.

Daniele considered the needs of his readers and built a systematic approach to software documentation. Diátaxis separates documentation into four styles: tutorials, how-to guides, explanations, and technical references.

Diagram of the Diátaxis framework

Tutorials

When we find ourselves interested in a new subject, we get started by entering the topic plus the word "tutorial" into our favorite search engine. The result of our query introduces us to guided sessions and workshops. As we have no subject expertise yet, we gain contact, comfort, and confidence in the new practice by mimicking the presented material.

Our lesson plan consists of a clear starting point and a practical goal our student can run when completed. We introduce them to the nomenclature of our documentation's subject. When progressing through the lesson, we provide frequent results to mark the journey. A well-structured tutorial delivers transparent progress and reliable results.

Although a teacher presents them didactically, tutorials are not lectures. We stay away from explanations that are not directly applicable to the task at hand. An overload of information obscures our students' path to an actionable result. As teachers, we are not able to determine what our students are going to learn, only to facilitate an environment of learning. Our student may pursue further knowledge later, at their discretion and as their cognitive load allows.

Our users explore our product with the help of tutorials and example procedures. Internally, we create tutorials for demo projects to evangelize new technology or tools we created.


  • Enjoying the chapter? Unlock the rest.

    Behind the paywall: We continue going over the Diátaxis framework, analyze different documentation media, and look into a documentation-driven development strategy.

    Engineering Collaboration is currently available as an Advanced Reading Copy for select readers.

    Get in touch with the author