Why nbdev
Popular Python documentation standards such as numpy docstrings and sphinx facilitate documentation of source code with docstrings, which are limited in their expressiveness and functionality. Notebooks, on the other hand, offer a richer medium for authoring documentation (with markdown and code cells) compared to docstrings, and unlock new ways of documenting your code that are otherwhise infeasible.
Furthermore, traditional testing frameworks such as pytest and unittest encourage writing tests in a separate context that is disjointed from the associated source code and documentation. With nbdev, you write tests in the same context as your source code and documentation, such that tests can optionally become part of the narrative within your documentation.
Since nbdev allows your colleagues and users to view the tests, code and documentation in a single context with a REPL that invites experimentation, the way you author code, documentation and tests in nbdev are very different than traditional software development workflows.
In Notebook Best Practices we compare a function coded, tested, and documented in nbdev versus ordinary .py files. Here are a few of the challenges we faced with other approaches that led us to using nbdev. In .py files:
- Docstrings repeat information that is already contained in the function signature, such as names of parameters, default values, and types
- Examples are manually entered. This requires the author to copy and paste both the code and outputs. Furthermore, the author must manually re-enter or change these examples anytime the code changes, which is an error-prone process
- Examples are limited to short code snippets and cannot contain rich output like plots or graphics
- Examples cannot have prose interleaved with code except for code comments
- Readers of your code must copy and paste contents of the docstring if they wish to reproduce the examples.