The most obvious way to document program details, behaviour and specification are to document it in text, preferable in the source code close to the subject. This 'closeness' is key to both discovery and keeping the documentation up-to-date. If is in separate documents that a mentally far-away, it will be ignored and forgotten about.
This helps both in on-boarding and discovery, and if code is legacy enough, maintaining it will most likely be a process of discovery.
Comments should describe why not how
Document preconditions and post-conditions of the system
Document behavior that can't be derived from types, etc.
The usual issues are that documentation and comments decays by becoming irrelevant, if they are not updated to reflect future code changes. This is especially due to the fact that documentation don't (usually) have to pass compilation, linting or tests.
Writing documentation can be a tedious process, and at times pointless. It is therefore key to know when to write documentation and what actually needs to be documented. This can be both in comments and/or documentation blocks, depending on if the reader consumes the functionality as a public interface or the reader has to understand the code inside the functionality.
Code should preferable be self evident in what it does and not need comments, however when performing otherwise unnatural or rule breaking behaviour it is important to comment why. In general comments should describe why and not how. Documentation can also take advantage of special syntax, that link to arguments, fields and types. Documentation good to describe preconditions of the of the function and how it can be used.
Besides documentation inside the code, it is also good practice to write a README and/or CONTRIBUTING document, especially in open source development. to aid the setup of or understanding of a given software project. This can speed-up the process when using custom or otherwise arcane build scripts. Likewise it can good to provide an ARCHITECTURE document outlining the more abstract structure of a project.
Sites like GitHub also provides integration with special project files like CODEOWNERS which defines who is owns parts of the project. This can can be useful for very large projects, where a given owner would be the do a code review of a given part.
While documentation normally is not tested, there exists systems that combine tests and documentation. Examples here are Python and Rust, that have doctests. Here you can write your test as an example in the documentation, and have it run as unit test. Thus ensuring that your documentation stays up to date.
Here is an example in Python.
python
def add(a: int, b: int): """ Given two integers, return the sum. :param a: int :param b: int :return: int >>> add(2, 3) 5 """ return a + b
And similarly for Rust:
rs
/// Given two integers, return the sum////// # Example:/// ```/// let sum = add(2, 3);/// assert!(sum, 5);/// ```fn add(a: i32, b: i32) -> i32 { a + b}
The Python case is written as if there calling the function using the REPL, while the Rust case is written as a unit test with an assertion.
Documentation
Docs, Comments and None-Code
The most obvious way to document program details, behaviour and specification are to document it in text, preferable in the source code close to the subject. This 'closeness' is key to both discovery and keeping the documentation up-to-date. If is in separate documents that a mentally far-away, it will be ignored and forgotten about.
This helps both in on-boarding and discovery, and if code is legacy enough, maintaining it will most likely be a process of discovery.
The usual issues are that documentation and comments decays by becoming irrelevant, if they are not updated to reflect future code changes. This is especially due to the fact that documentation don't (usually) have to pass compilation, linting or tests.
Writing documentation can be a tedious process, and at times pointless. It is therefore key to know when to write documentation and what actually needs to be documented. This can be both in comments and/or documentation blocks, depending on if the reader consumes the functionality as a public interface or the reader has to understand the code inside the functionality.
Code should preferable be self evident in what it does and not need comments, however when performing otherwise unnatural or rule breaking behaviour it is important to comment why. In general comments should describe why and not how. Documentation can also take advantage of special syntax, that link to arguments, fields and types. Documentation good to describe preconditions of the of the function and how it can be used.
Besides documentation inside the code, it is also good practice to write a
README
and/orCONTRIBUTING
document, especially in open source development. to aid the setup of or understanding of a given software project. This can speed-up the process when using custom or otherwise arcane build scripts. Likewise it can good to provide anARCHITECTURE
document outlining the more abstract structure of a project.Sites like GitHub also provides integration with special project files like
CODEOWNERS
which defines who is owns parts of the project. This can can be useful for very large projects, where a given owner would be the do a code review of a given part.Doctests
While documentation normally is not tested, there exists systems that combine tests and documentation. Examples here are Python and Rust, that have doctests. Here you can write your test as an example in the documentation, and have it run as unit test. Thus ensuring that your documentation stays up to date.
Here is an example in Python.
And similarly for Rust:
The Python case is written as if there calling the function using the REPL, while the Rust case is written as a unit test with an assertion.