Documentation is very common in software companies. It helps to keep the knowledge within a company while people come and go. It also helps new joiners to get up to speed. The general idea is to share the knowledge, which is needed to increase the bus factor of the team. 

But maintaining good documentation is definitely not an easy task. People just don’t like to write it and it quickly gets outdated. One thing we can notice about the documentation is that different documents can change for different reasons and at different pace. We can leverage that and not mix up documentation types in order to separate stable and more dynamic documents (Software Engineering at Google, 2020). 

In this article I’m going to show multiple documentation types. Picking the right document type is crucial for writing documentation that will be easy to read and will stay up to date for a longer time. 

Types of documentation

At the top level I would suggest separating documentation types based on the expected audience. In the companies that write software the documentation can be written for either end users of the software or other people working on creating that software.

Documentation for end users

Tutorials

Tutorials are learning-oriented. They assume the user doesn’t know the system and by following the steps they will achieve some tangible goal. This also means that the tutorials have to be kept working and reliable. They shouldn’t explain high-level ideas, as well as all the edge cases. The author decides what the reader has to know from the tutorial. They don’t have to focus on real-world problems.

Taking the cooking analogy it could be more like a cooking lesson rather than a recipe, the end result is not important. 

Examples:

How-to guides

How-to guides show the users how to achieve the real-world goal. They may assume the users already know something about the system and already have specific problems to solve. They are problem-oriented and usually encompass multiple concepts.

Taking the cooking analogy – it doesn’t have to explain the basics of cooking or discuss different properties of the ingredients. 

Examples:

Reference docs

Reference documentation describes a single element. It is information-oriented. It doesn’t explain the general concept, it doesn’t have an end result. Otherwise it would be distracting and prone to becoming outdated.

In cooking analogy it would be like trying to find all information about a single ingredient. You look up the ingredient by its name and you expect to find all the relevant information, how to prepare it properly, and if it has any special side effects. 

Examples:

Concepts

It helps to understand the general concept, and clarify a specific building block of the system. It is understanding-oriented, and it doesn’t have to explain all tiny details or edge cases. It should rather focus on a general idea how these elements work together. It may provide context, or historical background as to why some decisions have been made. It can have a more relaxed form, but it doesn’t mean it is easier to write, because it can have more arbitrary structure and it can be more difficult to find topics to describe. 

Taking the cooking analogy it could be a culinary TV show or a book that includes discussion about different aspects of the activities in the kitchen like cooking, frying, boling or describe different kitchen utensils.

Examples:

Release notes

Release notes have very specific goals. They answer the question “what is included in a specific version of the software?” or “what has changed since the last release of the software?”. They don’t include anything else besides that. No concepts explained, not code examples, just raw information with a timestamp. 

It’s difficult to find a cooking analogy for that, but let’s say it could be something like a history of updates to a cooking book. 

Example:


Documentation for engineers

On the other side of things there are engineers or more generally people who create the products the end users use. When new people join these teams they also need to learn how to use and contribute to the product. This means the organization can also benefit from documentation that targets their own employees. 

Design document

One of such documents could be design documents. They are usually created before some bigger part of the system is built. They may contain a list of different options to consider, their pros and cons, and the final outcome. It may serve as a point of reference when building the feature, but it can also serve as a historical context to explain why some decisions have been made and what was the thought process.It can have a fixed structure which can help future readers to navigate through multiple documents more efficiently. One such example is ADR (Architecture decision record) which describes important architectural decisions with their decisions and consequences. There are multiple templates already to use: https://github.com/joelparkerhenderson/architecture-decision-record

Once written they’re usually not updated. They cannot become outdated because they capture the state of the system in a very specific moment in time

Test scripts

Test scripts can help when doing regression testing to ensure the existing functionality of the software hasn’t been broken by releasing a new version. New people in the team can also benefit from them because they can better understand how the system is supposed to behave. It should describe an initial state of the system, steps to take to change the state, and the final outcome to verify. It could be in a form of a video, so more context is given without mentioning it explicitly in a video. 

One thing to keep in mind is that it tends to quickly become outdated because the user interface and user journey in the app is prone to changes, so any screenshot may quickly require replacement.

API documentation

Similarly to the reference documentation it is information-oriented. Its purpose is not to explain different concepts and high level ideas. It answers the questions of what endpoints are available, how can I call them, what parameters are required and what can I expect in return

APIs are usually consumed by the client developers of the system, but if the API is the company’s product it could this kind of document could also be treated as the end user documentation. 

Example: Stripe API https://stripe.com/docs/api 

Developer guidelines

Each new person in the team introduces a new perspective. And as useful and creative it can be, it also leads to inconsistencies because each one of them may present different and contradicting preferences. Therefore teams may want to introduce guidelines to have a consistent codebase and easier-to-reason-about APIs. Such documents can describe different aspects of the developers’ workflow and what’s inside depends on the needs of the team. It could for example be whether the team uses snake_case or kebab-case URLs in the API or if there’s any specific approach towards naming new repositories in GitHub. 

Some bigger companies expose their internal guidelines so other people can get inspiration:

Developer tutorials

Considering the system is built with certain architecture in mind, or it uses a specific tooling system, it could be useful to have a set of tutorials to show new engineers during onboarding. It could be for example a tutorial, how to add a new use case to the system – where to add a repository, where to add a controller. It can give a feeling of how to navigate through the codebase.

High level documentation

Documents describing high level concepts don’t change that often. Therefore it makes sense to clearly separate them from more detailed pieces of documentation. 

We could separate the high level documents into two categories: system architecture and business use cases.

System architecture

We can describe different blocks of our system, and how they interact with each other. We can for example show where are the contact points between our system and the user (e.g. API, mobile app, CLI), or show how services communicate with each other (e.g. recommendation service needs to fetch user metadata from user service). Essentially there could be multiple levels on which we can describe the architecture. C4 model could be a useful guideline to correctly scope a level of detail when describing the system. 

In this case, it’s a very good idea to back up the documentation text with images and diagrams.

Using the C4 model, one useful tool could be Structurizr that allows us to define the diagrams as code. 

Other useful tools to write the code that generates the diagrams are

Business use cases

On the less technical side, but still related to the product itself, we could describe high level business use cases. It helps engineers to get some more context as to why the feature was implemented, how it’s used, and who uses it. Similarly to the system architecture, it’s also useful to provide diagrams here to visualize the data flow or the user journey. 

One thing to keep in mind is that the features themselves don’t change that often, but the details of them do. E.g. if we describe a referral system in our app, we can describe how the referral system works in general, but we may have a different place to describe the details e.g. how many users per month you can refer to get a reward, or how what is the reward. 

Sometimes the features are sunsetted. We may preserve the documentation about them which can help with code archeology. But let’s make sure we clearly indicate that the feature is no longer active.

Code comments

Code comments are the closest to the actual code they describe, so there’s a bigger chance they will stay up to date (however, it’s always possible to overlook them getting outdated during code review). They can help to understand implementation details of the code, especially in case of more complex modules. 

In some languages you can use a certain type of code comments to make the IDE present this documentation.

e.g.

having a JavaScript function like this

/** this function formats the date to a stardard ISO format */
function formatDate(date) {
  // ....
}

It’s going to be shown in VSCode (IDE) like this:

Another benefit of code comments is that they are stored in a version control system which means it’s easy to see a history of changes (if the code uses VCS obviously).

README

README it’s a markdown file that can usually be found at a root level of the code repository. It’s probably the first piece of technical documentation that the engineers are going to come across when joining the company. The document usually contains information about the project itself e.g. to install dependencies, how to start it, what is the convention when creating new modules and it can also link to other guidelines that could be stored somewhere else. 

An example of README can be found in almost every open source project e.g. https://github.com/expressjs/express/blob/master/Readme.md, however internal company projects may contain slightly different information. 

Team landing page

Team landing page it’s a living document that tries to catch the current state of the team. It may contain a list of people in the team and their roles, but ideally it should not contain any content by itself. It should rather focus on linking to the resources that may be useful for the people in the team.

Infrastructure as code

Maybe it’s not entirely the documentation by itself, as it’s a production code, but it serves as a good source of truth when it comes to the current state of the infrastructure within a company. It’s more like a reference documentation rather than the high level one, because it describes every detail. The example could be Terraform.


Conclusion

There are multiple documentation types. Choosing the right type can be very helpful to have relevant, readable and up-to-date documentation within an organization.

We could split the documentation into two groups:

The one read by end users, and the one read by people who create the product. 

The end users’ documentation may contain:

  • tutorials – which help new users to make their first steps in the system
  • how-to guides – which help to solve real life problems the customers have
  • reference docs – which provides details about a single topic
  • concepts – which gives a full picture of different topics of the system
  • release notes – which answers a question what has changed since the last version

And the engineers’ documentation may contain:

  • design documents – which gives context of what options have been considered and why the team chose the ultimate one
  • test scripts – which helps new people understand how the app works, and also helps detecting regression
  • API documentation – which is full of details of how to work with the API
  • developer guidelines – which provides best practices the team has agreed to follow
  • developer tutorials – which teaches new developers how to contribute to the system
  • high level documentation 
    • system architecture – which gives an overview of the components of the system
    • business use cases – which gives an overview of the capabilities of the system and what they are used for
  • code comments – which helps to better understand the code
  • README files – which is probably the first document the engineers will see, and which describes how to run the project
  • team landing page – which navigates to other resources the team may find useful
  • infrastructure as code – which serves as a source of truth of the current infrastructure.

References

Author

I'm a software engineer with 9 years of experience. I highly value team work and focus a lot on knowledge sharing aspects within teams. I also support companies with technical interview process. On top of that I read psychological books in my spare time and find other people fascinating.