Why This Matters
Notebooks are good for seeing an algorithm breathe: a BFS wavefront, a heap after each insertion, a dynamic-programming table filling row by row, or a runtime curve changing with input size.
They are weak as the final home for reusable algorithm code. Hidden state, out-of-order cells, and copied functions make notebooks easy to trust too much.
Core Idea
Use notebooks for exploration and communication. Use modules plus tests for durable code.
| Good notebook use | Better as tested module |
|---|---|
| Visualize pointer movement | Reusable two-pointer implementation |
| Plot runtime growth | Benchmark harness and fixtures |
| Trace Dijkstra step by step | Shortest-path library function |
| Compare variants interactively | CI-verified implementations |
Non-Example or Failure Mode
A notebook that only works because cells were run in a secret order is not a reliable artifact. Restart the kernel and run all cells before trusting it.
Worked Example
A good Dijkstra notebook should:
- Define a tiny graph.
- Render the current frontier.
- Step through each priority-queue pop.
- Compare final distances against a known answer.
- Import the real implementation from a Python module instead of keeping a second copy.
Common Mistakes
| Mistake | Correction |
|---|---|
| Treating notebook output as proof. | Add deterministic tests for the underlying function. |
| Keeping reusable code only in cells. | Move algorithms into importable modules. |
| Benchmarking once on one input. | Use multiple sizes and adversarial cases. |
| Mixing explanation, experiments, and production code. | Let notebooks explain; let modules run. |
Diagnostic Questions
| Question type | Question | Answer signal |
|---|---|---|
| Definition | What is a notebook good at? | Exploration, traces, plots, and explanation. |
| Example / non-example | Is a notebook a substitute for tests? | No. It can display results, but tests verify behavior repeatedly. |
| Computation | Why restart-and-run-all? | It detects hidden state and missing dependencies between cells. |
| Transfer | Why use notebooks for complexity? | Runtime curves make asymptotic growth visible. |
Exercises
Beginner:
- Sketch a notebook trace for binary search.
- List two variables you would plot for a heap benchmark.
- Explain why out-of-order cells are dangerous.
Intermediate:
- Build a notebook that imports a tested Python Dijkstra function and visualizes each pop.
- Convert one notebook-only helper into a Python module with tests.
Challenge:
- Create a benchmark notebook that compares heap top-k to full sorting across input sizes.
Diagram Recommendation
Type: notebook-to-module workflow.
Caption: "Explore in a notebook, extract implementation, verify with tests."
Purpose: Make notebooks part of a disciplined builder workflow instead of a dead end.
Next Topics
References
- Project Jupyter documentation. Notebook basics and execution model.
- Wilson et al. "Good Enough Practices in Scientific Computing." 2017.