DOCS
Readme Documentation
The README is a crucial part of any project. It should be succinct yet loaded with all the frequently needed information, acting as the gateway to understanding our projects.
Each README within our ecosystem should consistently feature these important sections:
Setup and Installation
In this section, provide comprehensive instructions on how to install and run the project locally. It should cover the process of cloning the repository, installing the necessary dependencies, and any command line instructions for executing the project.
Configuration
Elaborate on how to configure the project. Include any information necessary for:
If there's an .env file or a config directory, make sure to mention it here and include instructions on how to get it.
Resources
Highlight useful links that directly pertain to the project, such as:
Troubleshooting & Known Issues
Git Convention
Detail the Git conventions followed in the project. This could include information on whether conventional commits are being used, the tense to be used in commit messages, and the rationale behind the chosen approach (if necessary).
Testing
Outline the testing methodologies adopted in the project. Information about the types of tests, expected coverage, and methodologies such as GWT (Given When Then) or AAA (Arrange Act Assert) should be covered. In cases where tests are not applicable to the project (like purely visual projects), explicitly state this.
File Structure and Infrastructure Overview
Give a basic description of the file structure, focusing on what a new developer needs to know to start working. If the project uses cloud or third-party services and the infrastructure is different than a usual standard project, provide a simple graph showing how components connect to each other.
Tools like the ones listed below can be used to create these graphs:
External Documentation
There are aspects of the project that require a more detailed form of documentation. These include elements that discuss in-depth architectural choices, extensive coding style guides, or major project decisions. For these, an external documentation platform such as Confluence is more suitable. This platform allows for better organization of complex information, collaborative editing, and structured layout, which are essential for navigating larger projects
ADRs
ADRs, or Architecture Decision Records, serve as documentation of important architectural choices made during a project. They provide an understanding of the context, decision, and consequences of choosing one solution over another. While not frequently referenced in day-to-day development, they become crucial when troubleshooting issues or making further architectural decisions. Given the fact that they are not referenced often, it's practical to host ADRs on an external platform like Confluence.
Architecture Specs
When a project is large, the basic information in the README might not be enough. You may need to create more detailed architectural diagrams and specs. These documents could provide a deeper look into the system, show how different parts interact, and give complete technical details. These documents are often too detailed for a README. It's better to put them on a platform like Confluence. This way, the README stays easy to understand, while more detailed information is available for those who need it
In-Code Documentation
Backend API Docs
When it comes to documenting backend APIs, OpenAPI is a reliable tool. We typically utilize an implementation like Swagger (+ UI) for REST and GraphQL APIs. It provides a UI to interact with the API and understand its functionalities. This form of in-code documentation is essential when we have a dedicated backend team and the APIs are complex enough to warrant such documentation.
However, if we are creating a simple pseudo-backend with Next.js API routes, such detailed documentation may not be required. The focus should be on making the code as readable and easy to understand as possible.
When working with other types of APIs like gRPC or tRPC, other forms of documentation may be necessary. Since OpenAPI is limited to REST and GraphQL, additional tools or methodologies may be required to adequately document these systems.
Utility and Type Docs
To maintain clarity and readability in our codebase, we employ JSDoc format to document utility/helper functions and global TypeScript types. This form of documentation is key to understanding how these utilities work and how to use them.
You may wonder why we need JSDocs when we already have TypeScript. The answer lies in the self-documenting nature of code.
Global functions or types often have short names, which is expected and good practice. However, these concise names can sometimes affect the self-documenting aspect of the code. By using JSDoc format, we can provide detailed descriptions, parameter explanations, and return value information that TypeScript alone may not convey.
Additionally, JSDoc comments can serve as the foundation for generating web-based documentation. Tools like TypeDoc can extract JSDoc annotations from our code and generate interactive documentation that helps developers understand the utilities and types we've defined.
Code
1declare global { /** * Defines the Optional type which allows properties of T to be optional. * * @template T - The type for which properties are made optional. * @template K - The set of keys within T that should be optional. * * @typedef {Object} Optional * @property {Partial<T
2 >} Pick<Partial<T
3 >, K> - A new object with all properties of T being partially optional. * @property {Omit<T, K
4 >} Omit<T, K>
5 - A new object with all properties of T except those in K. */ type Optional<T, K extends keyof T>
6 = Pick<Partial<T>, K> & Omit<T, K> }</T,></Partial<T></T,
7 ></T,
8 ></T,
9 ></Partial<T
10 ></T
11>
12
And a utility function:TypeScriptCopy
Code
1/**
2 * Approximates the integral of a function using Simpson's rule.
3 * Simpson's rule is a numerical integration technique that approximates the integral of a function by
4 * dividing the area under the curve into a series of trapezoids and using a quadratic polynomial to
5 * approximate the shape of each segment. It provides a more accurate approximation compared to simpler
6 * integration techniques like the trapezoidal rule.
7 *
8 * @param {Function} f - The function to integrate.
9 * @param {number} a - The lower limit of integration.
10 * @param {number} b - The upper limit of integration.
11 * @param {number} n - The number of intervals for integration.
12 * @returns {number} The approximate value of the integral.
13 */
14function approximateIntegral(f, a, b, n) {
15 const h = (b - a) / n;
16 let sum = f(a) + f(b);
17
18 for (let i = 1; i < n; i += 2) {
19 const x = a + i * h;
20 sum += 4 * f(x);
21 }
22
23 for (let i = 2; i < n - 1; i += 2) {
24 const x = a + i * h;
25 sum += 2 * f(x);
26 }
27
28 return (h / 3) * sum;
29}
30
31// Rest of the code...
By providing detailed JSDoc comments like this, we enhance the readability and maintainability of our codebase. The documentation also serves as a reference point for developers who interact with these utilities and types.
Remember that proper in-code documentation, in the form of JSDoc comments, makes our codebase more self-explanatory and enables the generation of user-friendly documentation when needed.
Keep in mind, going overboard with it can backfire, since after all, they're just comments with their own set of downsides.
That's the long and short of how we dodge project chaos with our doc guidelines. It’s like having a friendly chat with every new project and getting to know each other before things get serious. Hopefully, our approach sparks some fresh ideas for handling your own project documentation.