How to write better Documentation
Whether you’re developing software or designing a distributed system, writing quality documentation is essential for long-term development and maintenance. This blog will introduce you to various tools and practices to enhance your documentation.
Why write documentation?
Documentation helps users understand how to use and develop software effectively. It accelerates the onboarding process by providing structured information about the product, system architecture, methodologies, and work practices. It also serves as the source of truth in analysis, planning, and future updates.
You’ve made a decision.
You have something in your mind you need to share. Crack the knuckles and start typing…, but how, where? Using which tool?
I always picture the reader as someone who has little to no understanding of the subject. I try to use the terminology closest to them, draw examples in the real world that make sense, share as much useful information, and occasionally repeat myself.
When it comes to software work, choose an editor that makes work easy to write and for users to consume. Use different fonts, colors, headings, bullet points, and blank spaces. Highlight important details, make comparisons, and occasionally display tables or images, e.g:
Common text editing software:
- WYSIWYG Editors
- Markdown Editors
- Template Apps
WYSIWYG
What You See Is What You Get (or simply WYSIWYG) is a type of editing software that allows users to see and edit content in a form that appears as it would when displayed on an interface, website, slide presentation, or printed document.
Writing is smooth and straightforward. Every text modification you need is set in the toolbar.
These tools include:
- Microsoft Word
- Apple Pages
- Google Docs
- Zoho Writer
- Notion, etc
Markdown
Markdown editors are a popular choice for writing technical documentation. Learn once, write anywhere as the syntax is the same no matter if you’re writing a readme file on Github, blog on The Practical Dev, or any other markdown template.
This base syntax works like this:
# Heading1
## Heading2
### Heading3
#### Heading4
##### Heading5
###### Heading6
Regular Text
# Line Break
[Link](URL)
![image](URL)
* Bullet points
* Bullet points
*italic text*
**bold text**
```js
console.log('Code block');
```
Which translates into:
The writing is usually done inside IDE, like Visual Studio Code, Notepad++, Vim, etc, or online in any markdown editor.
Markdown generator
If writing code is an overhead for you, you’re in for a treat.
Using the app Readme.so, you can generate a markdown for your content just by clicking elements on the screen.
The output is a raw markdown that you can download and use in your docs.
Template App
There are templates online built using popular web frameworks that you can acquire that are specifically designed around docs.
These include:
- Vanilla HTML & CSS
- Gatsby
- Next.js
- WordPress and similar.
You can always build the docs site yourself.
Writing quality documentation is more than just mashing the keyboard. Sometimes it’s better to draw a picture.
Diagrams and docs are a perfect fit as they’re used to showcase where a certain feature exists in the architecture, and how it works, transforms, and is consumed by other entities.
Diagrams follow UML standards that are understood by developers, business analysts, and architects.
Standard categories:
- Structural diagrams
- Behavior diagrams
Commonly used diagrams:
- Data-Flow diagram
- Entity-Relational diagram
- UML class diagram
- Sequence diagram, etc.
Commonly used tools for drawing diagrams or hand-drawing:
It’s a common practice to design an app using three-level diagrams:
- Level 0 — General project overview for stakeholders
- Level 1 — Low-level diagrams that are more technical
- Level 2 —Lower-level diagram describes the behavior of individual components and features
Level 0 (Data Flow Diagram)
Level 1 (Data Flow using AWS Services)
Level 2 (Sequence Diagram)
Besides drawing diagrams manually, you can use Diagrams as Code tools to generate architecture based on your code:
Code Summary
It’s a common practice to write comments in the code, to explain what a certain feature does or clarify why such implementation was needed.
Using proper syntax, you can turn your comments into summaries.
In JavaScript, you can generate docs by simply typing /**
and hitting enter. The Visual Studio Code then sets up a wrapper:
/**
*
*/
Inside you can describe your classes, interfaces, functions, their properties, and return types however you like.
Let’s say you created a function:
export const exceptionHandler = (
error: IHTTPError,
req: Request,
res: Response,
_next: NextFunction
) => { }
If you hover over its name, you’re going to get very brief information about what it does.
Now add comments using JSDoc syntax and once again hover over,
/**
* Global Exception Handler
* @param {IHTTPError} error - Custom Error interface containing error name, status code, message and stack trace
* @param {Request} req - Express request object
* @param {Response} res - Express response object
* @param {NextFunction} _next - Express next function
* @returns HTTP error status code and appropriate message
*/
export const exceptionHandler = (
error: IHTTPError,
req: Request,
res: Response,
_next: NextFunction
) => { }
This time around there are a lot more details. A similar feature can be found in other programming languages, like C#:
[HttpGet("GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get(int ID) { }
If you write three slashes (///
) on top of the method, Visual Studio / VSCode will automatically generate an XML comment summary for you to fill.
/// <summary>
/// Retrieves current weather
/// </summary>
/// <param name="ID">Item ID</param>
/// <returns>List WeatherForecast</returns>
/// <exception cref="System.Web.Http.HttpResponseException"></exception>
[HttpGet("GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get(int ID) { }
Typedoc
The Typedoc package can generate markup documentation pages based on the JSDoc comments you type in your editor. To get started, install Typedoc in your TypeScript project:
> npm i typedoc
Open up a package.json
file and add a script that will run Typedoc:
"scripts": {
"build": "tsc",
"start": "...",
"type-docs": "typedoc", // <-- Add this line
},
Then create a tsconfig.json
file and set the entry point array containing paths for the files you want to display in the generated docs and an output directory:
{
"compilerOptions": {...},
"typedocOptions": {
"entryPoints": [
"src/shared/models/*.ts",
"src/services/*.ts",
...
],
"out": "docs/typedoc", // <-- set up output directory
}
}
Run the script:
> npm run type-docs
The output is an HTML file that you can open up in the browser and browse through your functions, classes, and their properties.
Swagger
Swagger allows you to describe the structure of your APIs based on the Open API specification. Once again, you’re using code comments to generate documentation pages.
Using the Swashbuckle package for .NET Core (or Swagger-UI Express for Node.js), you can extend your APIs by generating Swagger docs based on your comments.
Swagger UI Config (.NET Core)
// Program.cs
var builder = WebApplication.CreateBuilder(args);
//...
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo {
Title = "Your Weather API",
Description = "Weather API description",
Version = "v1"
});
// Check "Documentation File" checkbox in project properties/build
// and build the project.
// This will generate <Your-Project>.xml inside Bin/Debug directory
var fileName = Assembly.GetEntryAssembly().GetName().Name + ".xml";
var filePath = Path.Combine(AppContext.BaseDirectory, fileName);
options.IncludeXmlComments(filePath);
});
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
Code comments
// comments on controller action
/// <summary>
/// Retrieves weather forecast by ID.
/// </summary>
/// <remarks>
/// Sample request:
/// GET /WeatherForecast/GetWeatherForecast?ID=5
/// </remarks>
/// <param name="ID">The ID of the weather forecast to retrieve</param>
/// <returns>The requested weather forecast</returns>
/// <response code="200">Returns the requested weather forecast</response>
/// <response code="404">If the weather forecast with the given ID is not found</response>
/// <exception cref="System.Web.Http.HttpResponseException"></exception>
[ProducesResponseType(typeof(WeatherForecast), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(WeatherForecastError), StatusCodes.Status404NotFound)]
[HttpGet("GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get(int ID) { }
// comments on classes
/// <summary>
/// Weather Forecast Exception Class
/// </summary>
class WeatherForecastError
{
/// <summary>
/// HTTP Status Code
/// </summary>
public int StatusCode { get; set; }
/// <summary>
/// Error Message
/// </summary>
public string Message { get; set; }
}
Swagger UI Preview
Detailed overview of the API actions.
Overview of models.
Postman Documentation
If you’re using Postman to test APIs, you may not be aware that Postman comes with built-in API documentation.
To get started, in your workspace, click on View more actions (three dots) and choose View documentation from the dropdown.
This opens a new window with an overview of each endpoint from the collection.
You can add more context to APIs by writing the description for a collection or each endpoint.
Add Example Response
Choose an endpoint from your collection and send a request. Once you receive the response, click the Save Response button on the right.
This saves an example to your collection that you can further edit.
You can add more examples by clicking on the ellipsis menu (three dots) for the endpoint (by clicking on Add example).
Make an example request and hit the Try button on the right and save the response.
You can also publish your documentation online by clicking the Publish button in the top-right corner.
Create docs that users can interact with. Provide an engaging, user-friendly, and informative experience.
Interactive content
Increase the content interactivity. Add slides, tabs, pop-ups, expansion panels, buttons, inputs, etc.
Search & Filter functionality
Browsing through long docs can be tedious. Improve the user experience by implementing a search bar that enables users to quickly find relevant information by typing in keywords or phrases.
Collaborative Editing
Collaborative editing features allow multiple users to use and edit the docs in real-time.
Version History
Documentation changes through the lifecycle of the project. Therefore, it’s a good idea to keep track of changes, knowing what was the original idea, what was changed, and when, etc.
Embedded Videos
Make instructional videos outlining and showcasing specific features or business policies.
Interactive Code snippets
Provide interactive code snippets or automation tests that users can run directly within the documentation to see the results and understand how certain features or functions work.
Storybook is a great example of this. You can showcase your reusable web components outside the app and test them in isolation.
Know your audience
It’s important to connect with the end user of your documentation. As mentioned before, there is a difference between drawing a picture for a product manager versus the developer.
With this in mind, write docs that target groups with a specific level of business or technical understanding.
Related Work Items
Refer your docs page to an existing Epic, User Story, or Bug as those give more context about why the change was needed.
Link Docs or Tutorials
If you’re implementing a feature and you’re worried that people on your team may not be familiar with the syntax, paste a link to the docs in the comment.
Ask for feedback
Have other team members review your work. Ask them if they can get around it, and what they’d change or improve.
Code Highlight
As developers like to put technical details in the documentation, feel free to use markdown or libraries (e.g. highlight.js) to highlight code snippets and make them more readable.
Keep Docs up to Date
The documentation should be frequently reviewed and revised.
Wrapping up
Sometimes you forget how a certain feature works and you need a reminder. That’s what the documentation is for. So if you’re not writing docs, start now and if you are, take your time to get the quality right.
Good documentation is a lifesaver, especially on big projects.
If you want to dive deeper, I recommend checking out the Learn More section below. And if you found this article useful give it a clap.
Also, follow me on Medium, Twitter, and The Practical Dev to stay up to date with my content 👋