Whenever I write any code my goal is to make it as readable and easy to understand as possible. A computer can understand my code as long as it is syntactically correct, but other programmers (and I myself) can only understand the code if it is clear, focused and documented.
Small and simple modules are easy to document using a single README markdown file, even if including unit tests as examples. Larger projects with multiple separate features might be harder to explain. Even the author of the project might forget what each step of a complicated algorithm involves. To alleviate this problem I use two approaches.
Runnable stand alone code
I leave runnable code inside each CommonJS file. Typically a CommonJS file only exports a main function / object used somewhere else in the main algorithm. To remember what this particular code does I leave executable code inside a guard block.
1 | // src/complex-something.js |
This way, the module is normally called from another module, thus the code inside if (!module.parent) { ... }
does not execute. Whenever I need to remember what this particular code produces, I just run it by itself
DEBUG=example node src/complex-something.js
There might be multiple examples inside the guarded code block: complexSomethingExample1
, complexSomethingExample2
,
and I prefer to give them descriptive names. I also use either debug or
debug-logdown to print messages only when running as a stand alone
code (by setting the environment variable DEBUG=example
).
An example of runnable blocks can be found in bahmutov/changed-log repo inside files src/get-comments-between-commits.js and src/report.js.
Example NPM scripts
I usually have the default npm test
script run just the unit tests. In addition I write script commands
to show basic usage of an application or library. For example, bahmutov/changed-log has
a couple of such scripts in its package.json
1 | "scripts": { |
The command npm run chalk
produces the output I included in the changed-log/README,
while npm run example
is another shorter example from a repository I control. Having these examples makes
it simpler for me to go back and resume coding the changed-log
tool
after a few days or even months of inactivity.
Conclusion
Having examples in each file is much simpler than unit testing a piece of code, or fully describing its purpose
and expected inputs / outputs. A few larger use cases can be coded inside the scipts
section of a
package.json
file, showing the main command line switches in action.