Original cover photo by Janko Ferlič on Unsplash.
Purpose of documentation
Documentation of projects is a task that is overlooked by software developers quite often. While most popular open source
libraries have profound documentation websites with examples and even sandboxes, lots of other projects, especially enterprise
applications often go without a shred of documentation effort. Let's look at what problems this can cause։
- Difficulties onboarding: when new team members join your organization, existing documentation can save lots of time explaining which is what and how everything works.
- Confusion for existing developers: Often developers have to work on code which was written by others. A well documented piece with examples and instructions can also help save time, while missing docs can result in slow development and even bugs because of a misunderstanding
- Difficulties with managers and stakeholders: Lot's of times when managers want improvements, they may ask questions about how existing features work, or specifics about nuances (for example permissions or edge cases). A look into existing documentation can, again, save time and trouble
With this in mind, let's now first explore what is important in documentation for any project (not necessarily Angular), and then dive into specific tools and practices that can help document Angular projects in particular
Some rules for documentation
In my experience, documentation is a dedicated process that needs to be specific and adhere to certain rules. Here are some important considerations:
- Always document edge cases and weird nuances: if a part of your app behaves in a somewhat unexpected way, or maybe a piece of code is structured in an unexpected way because of a specific business requirement, make sure to mention it in your documentation
- Keep documentation close to what is being documented: in Angular projects, JSDoc comments can be used to document components, pages and so on write on top of the source code, which is very useful and saves time
-
Do not overdocument: there is no necessity to describe every single property of the class, especially if its name is self-evident.
isDialogVisible: boolean
is fairly understandable; focus on parts that can be mistaken - Use tools to generate documentation websites: for large projects having a separate place where everything is documented is a best practice, and can help with onboarding new members
- Use precise and accurate language: don't be too artistic, try to convey a meaning of some piece of code in a short, but understandable manner
- If you have a pull request review/peer-review process, definitely include reviewing docs as a part of code review; make sure people who have not worked on writing that doc have a fairly good understanding of what has been documented
- Provide examples! Examples are super useful for reusable functions and/or components and provide a fast way for other developers to get started
Now, with this in mind, let's examine documenting Angular projects.
Documentation for Angular applications
What to document?
First and foremost, let's understand what really needs to be included in the documentation. Before going to specifics, let's brush away things that do not need to be documented:
- Modules in general, especially feature modules. Names like
UsersModule
orDocumentsModule
are usually self-describing, no need to spend time explaining those in detail. - API calls in service methods. Usually those parts of code is very descriptive, take a look at the following example, it is completely evident what these methods do, you will have probably hundreds of those in your project:
@Injectable()
export class UsersService {
constructor(private readonly http: HttpClient) {}
getUserById(id: number) {
return this.http.get<User>(`api.ourprojectapi.com/users/${id}`);
}
}
- Business logic related models/classes: again, fairly self-describing, no need to explain what a
UserModel
is unless some particular nuance is present. - Enums, unless they have ambiguous names (in which case first explore whether the naming can be improved).
- If you use third party state management system (like NgRx or NgXs) documenting basic boilerplate things like reducers or actions is unnecessary, but some things like Effects in NgRx may warrant some explanations in certain cases
Now let's address stuff that definitely needs to be documented:
- Business logic (also known as container) components, which get data, create forms, update the DOM and so on. Describe what those components do, where they are used. In the case with page components (where you have a route pointing to it), it can be useful to describe what route exactly points to it, what parameters it gets, what (if any) resolved data is used and so on
- Reusable components: heavily document those types of components, as they are going to be used by lots of other developers for whom their intention might not be readily understandable. Document emitted events, and provide examples. Take a look at this case, it should be readily understandable what the component does:
/**
* This component displays a loading spinner over a block of content,
* in a dimmed overlay. Content inside the component is projected,
* and a boolean Input `loading` displays the spinner at will.
* Projected content is blocked from interaction when `loading`
* is set to `true`
*
* Usage example:
* @example
* <app-loader [loading]="loading">
* <div>
* Content goes here
* </div>
* <button (click)="loading = true; getContent()">
* Get new content
* </button>
* </app-loader>
*/
@Component({
selector: 'app-loader',
template: `
<div #wrapper [class.loading]="loading">
<ng-content></ng-content>
<div class="blocker" *ngIf="loading">
<loader-icon></loader-icon>
</div>
</div>
`
})
export class Loader {
@Input() loading = false;
}
- Usage of business logic related pipes. Take this example, here the pipe finds whether a particular item is pinned to the top of the screen when matching with another specific item:
/**
* This pipe takes a look at a list of items
* (Orders, Shipments or Products)
* and determines if it contains items that match with
* those in an AssignmentList,
* so that it can be displayed
* as pinned at the top of the page
*
* @example
* <!-- in Order List page, for example -->
* <div>{{ products | isPinned : currentAssignment }}</div>
*/
@Pipe({
name: 'isPinned',
})
export class IsPinnedPipe implements PipeTransform {
transform<T>(
items: { propertyName: T; id: number }[],
item: T,
): boolean {
return items.some(i => i.propertyName === item);
}
}
- Custom services with their methods, for example, a utility service with generic methods, or wrappers around native functionality, for example, if you have a
LocalStorageService
, make sure to document it extensively. - Document error cases whenever it is necessary, for example, if a method with an API call can result in an error if different ways, mention it in the method description
Of course, this list is in no way exhaustive, but doing at least these things can save you time and trouble.
Now let's understand how documentation needs to be written
How to document
Writing a document is fairly similar to writing an essay or an article, but here we need to try to be even more precise and short. Here are some rules that help:
- Keep it short: too much text and developers will start skipping over potentially important information
- Use simple language: don't try to show off, documentation is meant to be a pragmatic instruction, not poetry
- Use JSDoc annotations like
@description
,@example
and so on - Use links where appropriate: for example, when using a third party component, a link to its documentation page can be very useful.
- Yet again, provide examples where applicable, show instead of telling, how something should be done in practice
An important first step is to write the README
page. This page serves as a starting point for new developers and as an onboarding document. Describe what the project is about, what tools are used, how to install and run the project, what are the main components of the app and other important things developers should know from the get-go when dealing with your project.
If you are starting documenting a project for the first time, it is a good idea to go over popular framework/library docs and see how people usually document things. For example, documentation sites for RxJS, NgRx, and Angular itself can be super useful to up your skills at documenting software.
For example, take a look at the structure and language in the documentation page for the map
operator in RxJS. It has a short description, parameter types and return types described (those can be automated - more on that later), a detailed description with an illustration, and an example with references to related things. Usually you don't need as much sophistication, especially when working with enterprise products, but this is a good structure to follow overall.
What tools to use
Finally, we have come to a point where we want our JSDoc comment documentations to turn into a full scale documentation website, which we can share with new developers instead of providing lengthy Word documents, or which can be used by the team to search for explanations and direction during development. Thankfully, there are amazing tools that help us build such sites easily, with just a console command. Today we will be exploring one such tool called Compodoc, which is a documentation website generator specifically designed for Angular projects (it also supports Nest and Stencil, but we will focus on Angular).
Let's explore a bit and try to create a documentation site from an Angular project. If you have a handy Angular app on your computer (maybe a pet project), just follow this instructions:
Notice: even if there is zero documentation in your app, Compodoc will generate a website that describes all components, directives, services, pipes and so on with their inputs, outputs, method parameter names and types, just without detailed descriptions, which, of course, we would have to provide with JSDoc annotations
- Install Compodoc globally with
npm install -g @compodoc/compodoc
- Create a file named
tsconfig.doc.json
, containing a key include pointing tosrc
folder - You can optionally add a script to your
package.json
file that runs the documentation website:
"scripts": {
"compodoc": "npx compodoc -p tsconfig.doc.json"
}
- Now run it with
npm run compodoc
This command will generate a documentation
folder in your app root. This is the documentation website. It will also open in your browser automatically, so you can ee what has been generated.
There are several Demo documentation examples generated with Compodoc that you can see, here is the Angular app Documentation Demo.
You can further customize your documentation experience with the following steps:
- Exclude some files or types of files from being documented if you do not need them
- Add examples and descriptions with JSDoc annotations
- View the documentation coverage page to see how much you have documented so far
- Maybe choose a theme and style for your doc site
- Add additional external documentation files
- Add syntax highlighting for coding examples
- And so much more
In Conclusion
Documenting software is a practice as old as writing software itself. Some teams skip these projects, but more often than not, this comes back to cause problems later, especially with growing teams. Hopefully this article provides tips and tools for starting documenting your projects, and improving your development experience.
Top comments (1)
This is incredible.
I discovered this in 2024 and it still works like a wonder charm.
Great post and thanks for sharing 👏🏽👏🏽👏🏽