Objects and Classes. What is a natural way to represent real-world “things” in code, and how can we organize that code so that it’s easier to understand, test, and extend?
Finding Duplicate Files. Comparing each file to others is unworkably slow for large sets of files. How about generating a short label that depends only on the file contents and comparing that instead?
Matching Patterns. Implement the filename matching used in the Unix shell to show how more complicated tools like regular expressions work.
Parsing Text. Build a parser for the simple filename matching patterns implemented in the previous chapter.
Running Tests. How tools to collect tests, run them, and report their results are built. Highlights the idea that programs are just another kind of data.
An Interpreter. A program in memory is just a data structure, each of whose elements trigger some operation in the interpreter that’s executing it. Build a simple interpreter and evaluate the design by asking how extensible it is.
Functions and Closures. Extends the little interpreter to allow function definitions. Shows that handling variable scope is a design choice. How closures enable programs to encapsulate information in useful ways.
Protocols. How to simplify testing by temporarily replacing real functions with ones that return predictable values. Motivate ways that programmers can hook their own code into the Python interpreter.
A File Archiver. Explore the core of a simple version control system by building a file archiver that avoids creating duplicates of the same files.
An HTML Validator. Build a tool to check the structure of web pages. Introduces a design pattern frequently used to manage irregular data structures.
A Template Expander. Build a simple static site generator to show how modern websites create pages from templates. Reinforces earlier lessons about creating little programming languages.
A Code Linter. How one program can check the structure of another. Remember, programs are just another kind of data.
Page Layout. Build a small HTML layout engine that takes text and formatting instructions, and decides where to put each character and image. Introduces ideas about recursion and multiple inheritance.
Performance Profiling. Implement the kind of multi-column table used in data science to enforce the value of abstraction and how systematic performance testing can be used to decide between different implementation strategies.
Object Persistence. Complex data structures require a framework capable of handling aliasing and circularity. Build such a framework and learn how libraries for handling JSON and other formats work.
Binary Data. High-level programming languages abstract away bits and bytes, but sooner or later, the abstraction breaks down. Explore how computers represent numbers and text.
A Database. Build a simple database that appends every new copy of a record to a running log of operations.
A Build Manager. Build a simple build manager. Introduce some fundamental algorithms on directed graphs.
A Package Manager. How to find a workable installation of packages or prove that there isn’t one.
Transferring Files. Build a simple low-level client-server program to move files from one machine to another.
Serving Web Pages. Build a simple web server that understands the basics of HTTP and how to test programs of this kind.
A File Viewer. Build a tool for viewing files. Moving a cursor, inserting and deleting characters, etc., are not covered.
Undo and Redo. Modify the file viewer from the preceding chapter to add and delete text, and implement the undo design pattern.
A Virtual Machine. Build a simulator of a small computer and an assembler for a very simple language that can be used to program it.
A Debugger. Build a simple single-stepping debugger for the virtual machine of the previous chapter. Show how we can test it and other interactive applications.