Chapter 40: Documentation and Docstrings
Section 1
Documentation is how a program explains itself to people who were not involved in writing it, months later Code alone, however clean, what problem it solves, step by step, while documentation describes purpose, context, first, what arguments it accepts, and what it returns, without reading its implementation, which may be complex, to use it correctly. Documentation bridges that gap, between code as written, and code as used, by people, with different needs, with the program, as a whole, over its lifetime.
Documentation also matters for maintenance, because programs change, need to know, what was intended, before they change it, for a new requirement, or a bug fix, in the program, as a whole, over its run. Without documentation, from code alone, which is unreliable, when code is old, or when its original intent, was subtle, for a particular design decision, in that code, specifically, rather than, generally, for all code, at once, as a whole, over time. A maintainer who misreads intent, may “fix” code, that was actually correct, for its purpose, in the program, as a whole, over its run, or may, change a behaviour, that users depend on, without realising, that they depend on it, for their work, with the program, as a whole, over its run, in practice. Documentation that states, purpose, and constraints, plainly, for each major part, of a program, as a whole, over its run, helps maintainers, avoid those mistakes, by giving them, a standard, against which, to judge, whether a proposed change, preserves intent, for that part, of the program, in the program, as a whole, over its run, or whether, it changes intent, in a way, that should be, deliberate, and documented, itself, for future maintainers, who will, work with that code, over its lifetime, in practice.
Finally, for future readers, including yourself, because it acknowledges, that code, will be read, far more often, than it will be written, for a program, as a whole, over its run, and that, the time, spent writing, a clear explanation, now, saves, far more time, for every reader, who would otherwise, struggle, to understand, the code, without it, for that code, in the program, as a whole, over its run, in practice. That respect, does not mean, documenting, everything, in exhaustive detail, for every function, in a program, as a whole, over its run, because, exhaustive documentation, that no one, reads, is wasted effort, for its author, in the program, as a whole, over its run, and because, documentation, that is, too long, for its purpose, in the program, as a whole, over its run, is often, skipped, by readers, who need, only a quick answer, to a specific question, about a function, or a module, in the program, as a whole, over its run, in practice. It means, documenting, the things, that readers, actually need, to know, for a program, as a whole, over its run, at the level, they actually need, to know them, for that program, in the program, as a whole, over its run, in practice, which, is the subject, of this chapter, as a whole, from docstrings, for individual functions, to guides, for whole programs, and for the audiences, who will, use them, over a program's lifetime, in practice.
Check: Why can code alone, however clean, not fully replace documentation?
Section 2
A docstring is a string literal, placed, a class, that documents, that thing, for readers, that can, read it, a string, in code, rather than, a comment, beside code, it is, accessible, own attributes, which, means, without needing, to parse, comments, in practice. That accessibility, technical difference, between docstrings, and comments, and it, is why, docstrings, way, to document, public modules, classes, and functions, while, comments, are used, for explanations, inside code, that are, not needed, in practice, as discussed, for comments, generally, specifically, rather than, generally, at once, over time, where comments, were described, as explaining, why, code, was written, in practice.
Writing a good docstring, starts, stating, plainly, what, the thing, does, can grasp, immediately, without reading, further, itself, in practice. That summary, is what, documentation tools, display, in lists, of functions, or classes, and what, interactive help, shows, first, asks, for help, on it, in practice, so, informative, without relying, itself, to make, its meaning, clear, who may, never read, in practice. A summary, that merely, restates, without adding, any information, about what, wastes, and should, be rewritten, to state, its purpose, plainly, in terms, familiar, will understand, immediately, in practice, without needing, to read, its implementation, for that thing, in the program, as a whole, over its run, in practice.
After the summary, a docstring, may include, further detail, for that thing, in the program, as a whole, over its run, such as, how, it should be, used, for that thing, in the program, as a whole, over its run, what, its parameters, mean, for that thing, in the program, as a whole, over its run, what, it returns, for that thing, in the program, as a whole, over its run, and what, errors, it may raise, for that thing, in the program, as a whole, over its run, in practice, each of which, is covered, in later sections, of this chapter, generally, for docstring content, specifically, rather than, generally, for all content, at once, as a whole, over time, where the appropriate, level, of detail, for each kind, of thing, is discussed, for that kind, in the program, as a whole, over its run, in practice. The, overall principle, for docstrings, is the same, as for documentation, generally, in this chapter, what, a reader, actually needs, to know, to use, the thing, correctly, for that thing, in the program, as a whole, over its run, without repeating, information, that is, already obvious, for that thing, in the program, as a whole, over its run, as discussed, for type hints, generally, on type hints, specifically, rather than, generally, for all chapters, at once, as a whole, over time, where hints, already state, parameter types, for a function, in the program, as a whole, over its run, so that, a docstring, need not, repeat them, in prose, for that function, in the program, as a whole, over its run, unless, it adds, meaning, beyond the type, itself, for that parameter, in the program, as a whole, over its run, in practice, such as, what, values, are valid, for that parameter, in the program, as a whole, over its run, beyond merely, its type, for that parameter, in the program, as a whole, over its run, in practice.
Check: What makes a docstring different from an ordinary comment in Python?
Section 3
A module docstring, placed, before, documents, the module, for readers, who encounter, it, and who, what, the module, is for, before, they read, or classes, individually, in practice. It, should state, plainly, can grasp, immediately, without reading, in practice, and it, should mention, any important, assumptions, or constraints, such as, what, it expects, or what, external resources, it uses, in practice, should know, before, using it, in practice, generally, and specifically, must answer, the question, of what, the module, is for, before, in practice, generally.
A module docstring, should not, try, to list, every function, because, that list, will become, outdated, as functions, are added, or removed, and during, its maintenance, by developers, who must, current, as functions, change, in practice, and because, documentation tools, already, generate, such lists, automatically, without needing, in practice, generally, and specifically, should focus, on purpose, and context, rather than, in practice, generally. Instead, it, should explain, how, fit together, if, that is, not obvious, alone, in practice, and it, should give, if, helps, a reader, understand, its purpose, quickly, in practice, without needing, to read, in detail, in practice, generally, and specifically, clarifies, its purpose, as a whole, over its run, better, than prose, alone, for that module, in the program, as a whole, over its run, in practice, generally.
For, small modules, with a single, clear purpose, for that module, in the program, as a whole, over its run, a module docstring, of one, or two, sentences, may be, sufficient, for that module, in the program, as a whole, over its run, because, its purpose, is already, clear, from its name, and its contents, for that module, in the program, as a whole, over its run, in practice, and because, a longer docstring, in the program, as a whole, over its run, would, merely repeat, what, is already obvious, for that module, in the program, as a whole, over its run, without adding, any information, for a reader, who encounters it, for that module, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its docstring, should be, brief, and focused, on its purpose, for that module, in the program, as a whole, over its run, rather than, long, and exhaustive, for that module, in the program, as a whole, over its run, in practice, generally. For, larger modules, with several, related parts, for that module, in the program, as a whole, over its run, a longer docstring, may be, justified, for that module, in the program, as a whole, over its run, to explain, how, those parts, relate, to each other, for that module, in the program, as a whole, over its run, and how, a reader, should, approach, them, for their purpose, in the program, as a whole, over its run, in practice, without getting, lost, in details, for individual functions, in that module, in the program, as a whole, over its run, before, they understand, its overall purpose, for that module, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its docstring, serves, as an orientation, for new readers, who must, navigate, its contents, for their work, on that module, over its lifetime, generally.
Check: What should a module docstring focus on instead of listing every function it contains?
Section 4
A function docstring should begin, of what, the function, does, clear sentence, can understand, without reading, in practice, as discussed, generally, specifically, rather than, generally, at once, over time, for docstrings, generally. After, the summary, it, should describe, but, only, is not, already obvious, as discussed, generally, specifically, rather than, generally, at once, over time, where hints, already state, parameter types, so that, a docstring, need not, repeat them, in prose, unless, it adds, meaning, itself, in practice, such as, what, values, are valid, beyond merely, its type, in practice, generally, and specifically, description, must add, information, in practice, generally.
For, each parameter, a docstring, should state, what, it represents, rather than, merely restating, its name, in prose, without adding, any information, in practice, generally, and specifically, must be, informative, without relying, already knowing, what it, means, in practice, generally. It, should also, state, any constraints, such as, whether, it must, be non-empty, or within, or in, in practice, because, those constraints, are part, and because, callers, who violate, them, may cause, failures, without realising, that they, violated, a constraint, that was, never stated, plainly, in practice, generally, and specifically, must be, stated, explicitly, rather than, left implicit, in practice, generally.
A function docstring, should also, describe, what, the function, returns, for that function, in the program, as a whole, over its run, in terms, that a caller, can use, to understand, what, to do, with the result, for that function, in the program, as a whole, over its run, without reading, its implementation, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, for each function, in a program, must be, informative, on its own, for that function, in the program, as a whole, over its run, without relying, on the reader, already knowing, what it, returns, for that function, in the program, as a whole, over its run, in practice, generally. If, a function, may raise, an error, for certain inputs, for that function, in the program, as a whole, over its run, its docstring, should mention, that error, and the condition, that causes it, for that function, in the program, as a whole, over its run, so that, callers, can handle, it, appropriately, for that function, in the program, as a whole, over its run, rather than, being surprised, by it, at run time, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, for each function, in a program, where its errors, must be, documented, for its callers, in the program, as a whole, over its run, in practice, generally.
Keeping documentation close to the code it describes, and updating it in the same change, is the most reliable way to prevent it from drifting out of date as the program evolves.
Check: What should a function docstring describe about its parameters beyond their names and types?
Section 5
A class docstring documents, the class, for readers, who encounter, it, and who, what, it represents, before, they read, individually, in practice, generally, and specifically, must answer, the question, of what, the class, is, before, in practice, generally. It, should state, plainly, can grasp, immediately, without reading, its methods, in practice, and it, should mention, any important, invariants, such as, relationships, that must, always hold, in practice, should know, before, using it, in practice, generally, and specifically, must be, stated, explicitly, rather than, left implicit, in practice, generally.
A class docstring, should also, describe, how, instances, are meant, without repeating, the documentation, individually, in practice, generally, and specifically, pattern, must be, clear, alone, without needing, to read, in detail, in practice, generally. For, example, if, a class, represents, a collection, that must, be used, such as, adding, items, before, reading them, its docstring, should state, that usage, pattern, plainly, so that, callers, do not, misuse it, by reading, before adding, in practice, generally, and specifically, pattern, matters, for correctness, in practice, generally. It, should also, mention, any important, attributes, that are, part, and that, callers, are expected, to read, or set, directly, in practice, generally, and specifically, must be, clear, alone, without needing, to read, its methods, in detail, in practice, generally.
For, classes, that are, primarily, data holders, for that class, in the program, as a whole, over its run, as discussed, for data classes, generally, on type hints, specifically, rather than, generally, for all chapters, at once, as a whole, over time, where field hints, define, for that structure, in the program, as a whole, over its run, a class docstring, should focus, on what, the data, represents, for that class, in the program, as a whole, over its run, for that class, in the program, as a whole, over its run, rather than, merely listing, its fields, for that class, in the program, as a whole, over its run, without explaining, what, they mean, together, for that class, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its docstring, must explain, its data's meaning, for that class, in the program, as a whole, over its run, rather than, merely its structure, for that class, in the program, as a whole, over its run, in practice, generally. For, classes, with behaviour, for that class, in the program, as a whole, over its run, such as, services, or controllers, for that class, in the program, as a whole, over its run, a class docstring, should focus, on what, the class, does, for that class, in the program, as a whole, over its run, and how, its methods, work together, for that class, in the program, as a whole, over its run, to achieve, its purpose, for that class, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its docstring, must explain, its overall role, for that class, in the program, as a whole, over its run, rather than, merely listing, its methods, for that class, in the program, as a whole, over its run, in practice, generally, without explaining, how, they cooperate, for that class, in the program, as a whole, over its run, in practice, generally.
Check: What should a class docstring explain about a class as a whole, beyond its individual methods?
Section 6
Docstring styles are conventions, for how, docstrings, are formatted, such as, where, parameter descriptions, go, and how, return values, are described, in practice, generally, and specifically, in use, must be, followed, consistently, in practice, generally. Different, teams, and projects, use, different styles, for docstrings, some, placing, parameter descriptions, section, for parameters, others, describing, parameters, in prose, within, in practice, generally, and specifically, in use, must be, understood, by readers, who encounter, docstrings, written, in practice, generally. The, specific style, chosen, matters, less, than, consistency, because, readers, learn, a style, quickly, and then, unconsciously, to find, information, in docstrings, without thinking, about format, at all, in practice, generally, and specifically, must be, consistent, in practice, generally.
Consistency, in style, also, helps, documentation tools, that parse, docstrings, automatically, to generate, reference pages, alone, in practice, generally, and specifically, in use, depends, on docstrings, following, in practice, generally. If, docstrings, follow, different styles, within, tools, may parse, some correctly, and others, incorrectly, in practice, generally, and specifically, must be, uniform, to work, reliably, in practice, generally. A team, should therefore, choose, a style, early, document, it, briefly, joining, the team, with examples, of docstrings, written, in practice, generally, and specifically, must be, documented, together, generally, and it, should, enforce it, lightly, through review, for docstrings, rather than, through rigid, automated enforcement, that would, slow development, without improving, documentation quality, significantly, in practice, generally, and specifically, enforcement, must be, proportionate, in practice, generally.
When, choosing, a style, over its run, prefer, one, that is, widely used, for programs, as a whole, over their runs, and that, is supported, by common, documentation tools, for those programs, in the program, as a whole, over its run, in practice, generally, and specifically, where its style, choice, should consider, tool support, for that style, in the program, as a whole, over its run, in practice, generally, rather than, inventing, a new style, for that program, alone, in the program, as a whole, over its run, that no tool, supports, for that program, in the program, as a whole, over its run, and that, no other developer, will recognise, for that program, in the program, as a whole, over its run, in practice, generally. Whatever, style, is chosen, for a program, as a whole, over its run, the key, discipline, remains, the same, for all styles, in all programs, as a whole, docstrings, that state, what, a reader, actually needs, to know, to use, a thing, correctly, for that thing, in the program, as a whole, over its run, in a format, that readers, and tools, can find, easily, for that thing, in the program, as a whole, over its run, in practice, generally, and specifically, for each docstring, in a program, where its style, must serve, its readers, for that docstring, in the program, as a whole, over its run, rather than, distracting, them, with inconsistent, formatting, for that docstring, in the program, as a whole, over its run, in practice, generally.
Check: Why does consistency in docstring style matter more than which specific style is chosen?
Section 7
Documenting parameters and return values well requires, going, beyond, their names, to explain, what, they mean, as discussed, generally, specifically, rather than, generally, at once, over time, for docstrings, generally, and specifically, must add, information, in practice, generally. For, parameters, that means, stating, what, the parameter, represents, rather than, merely restating, its name, in prose, without adding, any information, in practice, generally, and specifically, must be, informative, without relying, already knowing, what it, means, in practice, generally. It, also, means, stating, any constraints, such as, whether, it must, be non-empty, or within, or in, in practice, because, those constraints, are part, and because, callers, who violate, them, may cause, failures, without realising, that they, violated, a constraint, that was, never stated, plainly, in practice, generally, and specifically, must be, stated, explicitly, rather than, left implicit, in practice, generally.
For, return values, documenting, well, means, stating, what, represents, rather than, merely stating, its type, without explaining, what, it means, in practice, generally, and specifically, must be, informative, without relying, already knowing, what it, returns, in practice, generally. If, a function, returns, a collection, its docstring, should state, what, the collection, contains, in the program, as a whole, over its run, and in, what order, for that function, in the program, as a whole, over its run, if, order, matters, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, for each function, returning, a collection, in a program, must clarify, its contents, and its order, for that function, in the program, as a whole, over its run, in practice, generally.
Documenting, parameters, and returns, should also, be, proportionate, for that function, in the program, as a whole, over its run, because, a simple function, with one, obvious parameter, for that function, in the program, as a whole, over its run, needs, only a brief, description, of that parameter, for that function, in the program, as a whole, over its run, if, it needs, any description, at all, beyond, its name, and its type, for that parameter, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its docstring, should be, brief, and focused, on its purpose, for that function, in the program, as a whole, over its run, rather than, long, and exhaustive, for that function, in the program, as a whole, over its run, in practice, generally. A complex function, with many, parameters, whose meaning, depends, on its inputs, for that function, in the program, as a whole, over its run, for that function, in the program, as a whole, over its run, needs, fuller documentation, for its parameters, and its return, for that function, in the program, as a whole, over its run, so that, callers, can use it, correctly, without reading, its implementation, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its docstring, must be, detailed, enough, for callers, to use it, safely, for that function, in the program, as a whole, over its run, in practice, generally.
Check: How should parameter and return documentation differ between simple and complex functions?
Section 8
Examples in docstrings help readers, understand, how, to use, a function, correctly, by showing, a concrete, use, can follow, easily, without needing, to construct, from scratch, in practice, generally, and specifically, documented, must be, realistic, rather than, contrived, that does, not reflect, how, it is, actually used, in practice, generally. A good example, uses, typical inputs, is likely, to encounter, in practice, in practice, generally, and specifically, must be, representative, rather than, edge cases, that confuse, who is, trying, to understand, basic use, before, they tackle, edge cases, in practice, generally. Edge cases, can be, documented, separately, after, basic use, is clear, in practice, generally, and specifically, documented, with examples, should come, first, before, edge cases, are introduced, in practice, generally.
Examples, in docstrings, can also, be, tested, automatically, by tools, that extract, examples, from docstrings, and run, them, as tests, verifying, match, the outputs, stated, itself, in practice, generally, and specifically, provides, for documentation, accuracy, in practice, generally. That, testability, benefit, over examples, in separate, documentation, files, which, are not, automatically, tested, against code, and which, can become, outdated, as code, changes, without any, test, failing, to alert, its author, in practice, generally, and specifically, must be, checked, manually, rather than, automatically, through tests, in practice, generally.
Examples, should be, kept, brief, for a docstring, in the program, as a whole, over its run, because, a docstring, is not, a tutorial, for that thing, in the program, as a whole, over its run, and because, a long example, for that thing, in the program, as a whole, over its run, can, obscure, the docstring's main, description, of what, the thing, does, for that thing, in the program, as a whole, over its run, for readers, who need, about that thing, in the program, as a whole, over its run, in practice, generally, and specifically, for each docstring, in a program, where its example, must be, concise, for that docstring, in the program, as a whole, over its run, rather than, exhaustive, for that docstring, in the program, as a whole, over its run, in practice, generally. One, or two, short examples, showing, typical use, for that thing, in the program, as a whole, over its run, are usually, sufficient, for a docstring, in the program, as a whole, over its run, in practice, generally, and specifically, for each docstring, in a program, where its examples, must be, limited, to typical use, for that thing, in the program, as a whole, over its run, rather than, covering, every possible, use, for that thing, in the program, as a whole, over its run, in practice, generally.
Keeping documentation close to the code it describes, and updating it in the same change, is the most reliable way to prevent it from drifting out of date as the program evolves.
Check: Why are examples in docstrings especially valuable when they can be run as tests?
Section 9
Keeping documentation accurate, as code, changes, is one, parts, of documentation, because, documentation, does not, affect, run-time behaviour, as discussed, for hints, generally, specifically, rather than, generally, at once, over time, visible failure, to prompt, their correction, in practice, generally, and specifically, of documentation, must be, detected, before it, misleads, readers, in practice, generally. A program, whose documentation, describes, old behaviour, that has, since changed, and during, its maintenance, by developers, who must, keep documentation, current, as code, changes, in practice, generally, will, mislead, readers, who trust, documentation, over code, itself, in practice, generally, and specifically, who trusts, stale documentation, generally, leading, to bugs, that uses, the program, incorrectly, based on, outdated documentation, in practice, generally, and specifically, must be, recognised, before it, can be, corrected, through updating, in practice, generally.
The, most effective, way, to keep, documentation, accurate, is to, update it, as part, that changes, code, rather than, leaving it, for later, that may, under pressure, that appears, to work, despite, in practice, generally, and specifically, to code, must be, updated, alongside, the code, itself, in practice, generally. That, means, that, a change, should include, an update, in practice, generally, and specifically, changed, must be, reviewed, as part, itself, in practice, generally, and that, a change, should include, an update, in practice, generally, and specifically, changed, must be, reviewed, as part, itself, in practice, generally. Reviewers, should therefore, check, documentation, as part, of reviewing, a change, asking, whether, its docstrings, still accurately, describe, in practice, generally, and specifically, reviewed, must be, verified, alongside, its code, in practice, generally.
Documentation, that is, generated, from code, such as, reference pages, generated, from docstrings, as discussed, generally, specifically, rather than, generally, at once, over time, generally, is, less prone, to staleness, than documentation, written, separately, from code, because, generated documentation, is, regenerated, for that program, in the program, as a whole, over its run, whenever, it is, rebuilt, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each piece, of generated documentation, in a program, where its accuracy, depends, on its docstrings, being, current, for that program, in the program, as a whole, over its run, in practice, generally. That, is another reason, to prefer, docstrings, close to code, for that code, in the program, as a whole, over its run, over separate, documentation, files, that duplicate, information, from code, for that code, in the program, as a whole, over its run, in practice, generally, and specifically, for each piece, of information, in a program, where its duplication, in separate documentation, risks, divergence, from code, for that information, in the program, as a whole, over its run, in practice, generally, because, duplication, must be, maintained, in two places, for that information, in the program, as a whole, over its run, instead of, one place, for that information, in the program, as a whole, over its run, in practice, generally, and because, a change, to code, for that information, in the program, as a whole, over its run, may update, one place, but, forget, the other, for that information, in the program, as a whole, over its run, in practice, generally, leading, to stale documentation, for that information, in the program, as a whole, over its run, generally.
Check: Why should documentation be updated in the same change as the code it describes?
Section 10
Documentation and comments serve different purposes, explain, code, for readers, and confusing, their roles, leads, to documentation, that is, misplaced, and therefore, less useful, in practice, generally, and specifically, of explanation, must match, its purpose, in practice, generally. Documentation, of docstrings, is for, users, telling them, what, it does, how, correctly, and what, to expect, from it, in practice, generally, and specifically, documented, must serve, its users, rather than, its implementers, in practice, generally. Comments, by contrast, are for, maintainers, of code, telling them, why, code, was written, as discussed, for comments, generally, specifically, rather than, generally, at once, over time, where comments, were described, as explaining, why, rather than, what, for code, in practice, generally, and specifically, must be, to explain, why, rather than, to document, in practice, generally.
That, distinction, helps, you decide, where, to put, an explanation, of code, when, in practice, generally, and specifically, must be, chosen, based on, its audience, in practice, generally. If, an explanation, is needed, by users, correctly, in practice, generally, and specifically, is users, in practice, generally, then, it belongs, where, users, in practice, generally. If, an explanation, is needed, to understand, why, it was, implemented, in practice, generally, and specifically, where its audience, is maintainers, for that explanation, in the program, as a whole, over its run, in practice, generally, then, it belongs, in a comment, inside, the function's body, for that function, in the program, as a whole, over its run, where, maintainers, reading, the implementation, will find it, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its placement, inside the body, matches, its maintainer audience, for that explanation, in the program, as a whole, over its run, in practice, generally.
Putting, user-facing explanations, in comments, instead of, docstrings, for a thing, in the program, as a whole, over its run, hides, them, from users, who rely, on documentation tools, for that thing, in the program, as a whole, over its run, to find, how, to use it, correctly, for that thing, in the program, as a whole, over its run, in practice, generally, and specifically, in a program, where its placement, in a comment, would, hide it, from users, for that explanation, in the program, as a whole, over its run, in practice, generally, because, comments, are not, accessible, through documentation tools, for that thing, in the program, as a whole, over its run, that docstrings, are, for that thing, in the program, as a whole, over its run, in practice, generally. Keeping, that distinction, clear, for every explanation, in a program, as a whole, over its run, therefore, improves, both, public documentation, for users, of a program, in the program, as a whole, over its run, and internal explanations, for maintainers, of that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each explanation, in a program, where its audience, determines, its placement, for that explanation, in the program, as a whole, over its run, in practice, generally.
Check: How do you decide whether an explanation belongs in a docstring or in a comment?
Section 11
A README file is the first document a reader meets when they encounter a project, and its job is to answer, quickly, what the project is for, how to install it, and how to use it for its most common purpose. A good README starts with a plain statement of purpose, in one or two sentences, that a stranger can understand, without knowing anything about the project's history, or its author's intentions, beyond what the README itself states. It then gives installation steps, that actually work, in order, for a fresh environment, without assuming tools, or settings, that the reader may not have, and without skipping steps, that the author performs, automatically, from habit, but that a new user would not know, to perform, on their own. It then shows a short example, of typical use, that a reader can copy, and run, to see, the project working, for themselves, before they commit, to learning it, in depth, for their own work, with the project, as a whole.
A README should also state, plainly, what the project does not do, where that limitation, matters, for a reader, deciding, whether to use it, for their purpose, because, a reader, who adopts, a project, on a false assumption, about its scope, will waste time, discovering, its limits, only after investing, effort, in learning it, for their work. It should link, to fuller documentation, for readers, who need, more detail, than the README, itself provides, for that project, rather than, trying to contain, all documentation, within the README, itself, which would make it, long, and hard to navigate, for readers, who need, only a quick start, for that project, in practice. It should also state, how, to get help, or to report, a problem, for that project, in a way, that a new user, can follow, without prior knowledge, of the project's community, or its processes, for handling, reports, from users, who encounter problems, with the project, in practice.
Finally, a README must be kept current, as the project changes, because a README that describes, old installation steps, or old usage, for a project, misleads, new users, at the very moment, they are forming, their first impression, of that project, and deciding, whether to trust it, for their work. When installation changes, or when the main example changes, the README should change, in the same update, as the code, itself, for that change, rather than, being left, for a later documentation update, that may never happen, under pressure, from new work, on the project, as a whole. Reviewers should therefore check, the README, as part, of reviewing, any change, that affects, installation, or basic use, for that project, asking, whether a new user, following, the README, alone, could still, install, and run, the project, successfully, after that change, for that project, in practice. That simple test, of following, the README, from scratch, is one of the most effective, ways, to catch, documentation drift, before it affects, real new users, who depend on it, for their first experience, of a project, as a whole.
Check: What three things must a README answer quickly for a new reader?
Section 12
API reference documentation describes, each public function, class, and module, in a library, in a systematic way, so that, a user, who already knows, what they want, to do, can find, the exact function, they need, and learn, how to call it, correctly, without reading, its implementation, or searching, through tutorials, for a passing mention, of that function, in a longer narrative, about the library, as a whole. A good reference entry, therefore, begins, with the docstring's summary, followed, by its parameter, and return descriptions, and by any, examples, that clarify, typical use, for that function, or class, in the library, as a whole.
Reference documentation should be organised, for lookup, rather than, for learning, in sequence, because, its readers, typically, arrive, with a specific question, such as, what arguments, does this function, take, for that function, in the library, as a whole, or what, does this class, do, for that class, in the library, as a whole, and they, want an answer, quickly, without reading, a whole guide, from start to finish, for that library, in the library, as a whole. That means, reference pages, should be, searchable, and indexed, by name, for each function, and class, in the library, as a whole, so that, a reader, can find, the entry, they need, by searching, for its name, directly, for that entry, in the reference, as a whole, rather than, browsing, through a long, narrative document, for that library, in the library, as a whole, in practice. It also means, that each entry, should stand alone, for that entry, in the reference, as a whole, without assuming, that the reader, has read, other entries, first, for that library, in the library, as a whole, in practice, because, reference readers, jump, directly, to the entry, they need, for their question, at that moment, during their work, with the library, as a whole, in practice, rather than, reading, the reference, from start to finish, as a book, for that library, in the library, as a whole, in practice.
Reference documentation should also distinguish, clearly, between public, and private, parts, of a library, for that library, in the library, as a whole, because, users, should rely, only on public parts, for their work, with the library, as a whole, while, private parts, may change, without notice, for that library, in the library, as a whole, as discussed, for public interfaces, generally, in earlier chapters, on refactoring, and on clean code, for programs, as a whole, over their runs. Including, private parts, in reference documentation, without marking them, as private, for that library, in the library, as a whole, misleads, users, into depending, on them, for their work, with the library, as a whole, and then, suffering, when they, change, for that library, in the library, as a whole, in a later version, of the library, as a whole, in practice.
Check: How does reference documentation differ from tutorial documentation in organisation and purpose?
Section 13
A tutorial, guides, a reader, through a realistic task, from start to finish, for that task, in the program, as a whole, over its run, explaining, each step, as it arises, for that task, in the program, as a whole, over its run, and showing, what, the reader, should see, after each step, for that task, in the program, as a whole, over its run, in practice, so that, the reader, finishes, with a working result, for that task, in the program, as a whole, over its run, and with, an understanding, of how, the program, was used, to achieve it, for that task, in the program, as a whole, over its run, in practice. That, narrative structure, is essential, for learning, because, beginners, need, context, and sequence, for a task, in the program, as a whole, over its run, not, isolated facts, about individual functions, in the program, as a whole, over its run, that they, must assemble, themselves, into a working task, for that program, in the program, as a whole, over its run, in practice, without guidance, on order, or on purpose, for each step, in that task, in the program, as a whole, over its run, in practice.
A documentation set, that contains, only tutorials, for a program, as a whole, over its run, frustrates, experienced users, who need, a quick answer, for a specific question, about a function, in the program, as a whole, over its run, in practice, because, they must, search, through narratives, for a passing mention, of that function, in the program, as a whole, over its run, in practice, rather than, finding, its entry, directly, in a reference, for that program, in the program, as a whole, over its run, in practice. A set, that contains, only reference, for a program, as a whole, over its run, frustrates, beginners, who need, guidance, through a first task, for that program, in the program, as a whole, over its run, in practice, because, they must, assemble, isolated facts, into a working task, themselves, for that program, in the program, as a whole, over its run, without any, narrative, to guide them, through that task, in the program, as a whole, over its run, in practice, from start to finish, for that task, in the program, as a whole, over its run, in practice.
That, linking, between kinds, is part, of good documentation design, for a program, as a whole, over its run, because, it, recognises, that readers, move, between learning, and lookup, as their needs, change, for that program, in the program, as a whole, over its run, during their work, with it, over its lifetime, in practice, rather than, staying, in one mode, for all their work, with that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each reader, of documentation, for a program, where their needs, shift, between learning, and lookup, over time, during their work, with that program, in the program, as a whole, over its run, in practice, generally.
Check: Why does a documentation set need both tutorials and reference material?
Section 14
Private code, code not meant, to be used, outside its own module, or package, for that code, in the program, as a whole, over its run, needs, far less, public documentation, than public code, for that code, in the program, as a whole, over its run, because, its readers, are only, the maintainers, of that module, for that code, in the program, as a whole, over its run, who can, read its implementation, directly, for that code, in the program, as a whole, over its run, to understand, what it does, for that code, in the program, as a whole, over its run, in practice, rather than, relying, solely, on its documentation, for that code, in the program, as a whole, over its run, in practice, generally, and specifically, for each piece, of private code, in a program, where its audience, is limited, to maintainers, of its module, for that code, in the program, as a whole, over its run, in practice, generally.
A public function, with an unclear docstring, for that function, in the program, as a whole, over its run, will, be misused, by some users, for that function, in the program, as a whole, over its run, who guess, at its behaviour, from its name, alone, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, for each public function, in a program, where its docstring, must be, clear, enough, for strangers, to use it, safely, for that function, in the program, as a whole, over its run, in practice, generally. That, difference, in audience, between private, and public, code, for that code, in the program, as a whole, over its run, is why, documentation effort, should be, concentrated, on public code, for that code, in the program, as a whole, over its run, rather than, spread, evenly, across all code, regardless, of its audience, for that code, in the program, as a whole, over its run, in practice, generally, and specifically, for each program, where its documentation, effort, must be, allocated, by audience, for that program, in the program, as a whole, over its run, over its lifetime, generally.
Marking, code, as private, or public, clearly, for that code, in the program, as a whole, over its run, is itself, part, of documentation, for that code, in the program, as a whole, over its run, because, readers, need to know, whether, they may, safely depend, on a thing, for their work, with the program, as a whole, over its run, or whether, it may change, without notice, for that thing, in the program, as a whole, over its run, as discussed, for public interfaces, generally, in earlier chapters, on refactoring, and on clean code, for programs, as a whole, over their runs.
Keeping documentation close to the code it describes, and updating it in the same change, is the most reliable way to prevent it from drifting out of date as the program evolves.
Check: Why should documentation effort concentrate on public code rather than spreading evenly?
Section 15
Breaking changes, deserve, particular prominence, for that version, in the program, as a whole, over its run, because, they, require, users, to change, their own code, for that version, in the program, as a whole, over its run, to keep, working, with the new version, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each breaking change, in a version, where its prominence, must reflect, its impact, on users, for that version, in the program, as a whole, over its run, in practice, generally.
An entry, that states, that an internal function, was refactored, for that function, in the program, as a whole, over its run, without saying, how, that refactoring, affects, users, for that function, in the program, as a whole, over its run, helps, no user, decide, whether, to update, for that version, in the program, as a whole, over its run, in practice, generally, and specifically, for each such entry, in a changelog, where its user effect, must be, stated, plainly, for that entry, in the program, as a whole, over its run, rather than, merely its internal cause, for that entry, in the program, as a whole, over its run, in practice, generally. An entry, that states, that a function, now accepts, a new argument, for that function, in the program, as a whole, over its run, and that, old calls, continue, to work, for that function, in the program, as a whole, over its run, helps, users, understand, both, the new capability, for that function, in the program, as a whole, over its run, and the safety, of updating, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, for each such entry, in a changelog, where its user effect, and its compatibility, must both, be stated, plainly, for that entry, in the program, as a whole, over its run, in practice, generally.
A changelog, should be, updated, as part, of each release, for that program, in the program, as a whole, over its run, not, reconstructed, afterwards, from memory, for that release, in the program, as a whole, over its run, because, reconstruction, from memory, for that release, in the program, as a whole, over its run, inevitably, omits, changes, that seemed, minor, at the time, for that release, in the program, as a whole, over its run, but that, affect, some users, for that release, in the program, as a whole, over its run, in practice, generally, and specifically, for each release, in a program, where its changelog, must be, built, incrementally, as changes, are made, for that release, in the program, as a whole, over its run, rather than, at the end, for that release, in the program, as a whole, over its run, in practice, generally.
Check: Why should changelog entries describe user-visible effects rather than internal implementation details?
Section 16
Documentation generation tools turn docstrings, and other, structured documentation, in code, for a program, as a whole, over its run, into readable, reference pages, for that program, in the program, as a whole, over its run, that users, can browse, and search, for that program, in the program, as a whole, over its run, without reading, source files, directly, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each tool, in use, for a program, where its output, must be, readable, for users, of that program, in the program, as a whole, over its run, in practice, generally.
Generated documentation, should be, checked, after generation, for a program, as a whole, over its run, by reading, its output, for that program, in the program, as a whole, over its run, as a user, would, for that program, in the program, as a whole, over its run, rather than, assuming, that generation, succeeded, correctly, for that program, in the program, as a whole, over its run, merely because, the tool, ran, without errors, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each generation, run, for a program, where its output, must be, inspected, for that run, in the program, as a whole, over its run, in practice, generally. Checking, generated output, therefore, is part, of documentation work, for a program, as a whole, over its run, not, an optional extra, for that program, in the program, as a whole, over its run, to be, skipped, under deadline pressure, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each documentation build, for a program, where its output, must be, verified, before, it is published, for that program, in the program, as a whole, over its run, in practice, generally.
A documentation set, that contains, only generated reference, for a program, as a whole, over its run, frustrates, beginners, who need, guidance, through a first task, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each beginner, using documentation, for a program, where their need, is guidance, for that program, in the program, as a whole, over its run, rather than, lookup, for that program, in the program, as a whole, over its run, in practice, generally. Generated reference, should therefore, be, combined, with hand-written, guides, for a program, as a whole, over its run, that explain, its overall purpose, and its typical uses, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each program, where its documentation, set, must be, complete, for both learning, and lookup, for that program, in the program, as a whole, over its run, over its lifetime, generally.
Check: Why must generated documentation be inspected after generation, even when the tool reports no errors?
Section 17
Experienced users, need, reference, that answers, specific questions, quickly, for that program, in the program, as a whole, over its run, without repeating, basic concepts, that they, already understand, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each experienced user, using documentation, for a program, where their need, is lookup, for that program, in the program, as a whole, over its run, rather than, learning, for that program, in the program, as a whole, over its run, in practice, generally. Maintainers, need, internal documentation, about design decisions, for that program, in the program, as a whole, over its run, and about, why, code, was written, a certain way, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each maintainer, using documentation, for a program, where their need, is design context, for that program, in the program, as a whole, over its run, rather than, user guidance, for that program, in the program, as a whole, over its run, in practice, generally.
Writing, for a specific audience, for documentation, in a program, as a whole, over its run, means, using, language, that audience, understands, for that audience, in the program, as a whole, over its run, without assuming, knowledge, that audience, does not, have, for that audience, in the program, as a whole, over its run, in practice, generally, and specifically, for each audience, for documentation, in a program, where its language, must match, that audience's background, for that audience, in the program, as a whole, over its run, in practice, generally. A tutorial, for beginners, for a program, as a whole, over its run, should explain, terms, that beginners, may not, know, for that program, in the program, as a whole, over its run, when, those terms, first appear, for that tutorial, in the program, as a whole, over its run, in practice, generally, and specifically, for each term, introduced, in a tutorial, where its explanation, must be, clear, for beginners, of that tutorial, in the program, as a whole, over its run, in practice, generally, rather than, assuming, that beginners, already know, those terms, for that tutorial, in the program, as a whole, over its run, in practice, generally.
Choosing, an audience, clearly, for each document, in a program, as a whole, over its run, and writing, for that audience, specifically, for that document, in the program, as a whole, over its run, in practice, generally, is therefore, a key, documentation skill, for programs, as a whole, over their runs, that must be, practised, deliberately, for each document, in a program, as a whole, over its run, over its lifetime, generally.
Keeping documentation close to the code it describes, and updating it in the same change, is the most reliable way to prevent it from drifting out of date as the program evolves.
Check: Why does trying to serve all audiences in one document usually serve none of them well?
Section 18
Diagrams in documentation can clarify, structures, and flows, that prose, alone, struggles, to convey, for a program, as a whole, over its run, such as, how, modules, relate, to each other, for that program, in the program, as a whole, over its run, or how, data, flows, through a pipeline, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each diagram, in documentation, for a program, where its purpose, must be, to clarify, a structure, or a flow, for that program, in the program, as a whole, over its run, rather than, to decorate, documentation, for that program, in the program, as a whole, over its run, in practice, generally. A diagram, that shows, data flow, through stages, for a pipeline, in the program, as a whole, over its run, similarly, clarifies, order, and transformation, for that pipeline, in the program, as a whole, over its run, in a way, that prose, listing, stages, in sequence, for that pipeline, in the program, as a whole, over its run, can, approximate, but, not match, for visual clarity, for that pipeline, in the program, as a whole, over its run, in practice, generally, and specifically, for each pipeline, documented, with a diagram, where its flow, must be, visible, at a glance, for that pipeline, in the program, as a whole, over its run, in practice, generally.
Diagrams, should be, kept, simple, for documentation, in a program, as a whole, over its run, because, a diagram, with too many, boxes, and arrows, for that diagram, in the program, as a whole, over its run, becomes, as hard, to read, as the prose, it was, meant, to clarify, for that diagram, in the program, as a whole, over its run, in practice, generally, and specifically, for each diagram, in documentation, for a program, where its simplicity, must be, preserved, for that diagram, in the program, as a whole, over its run, rather than, sacrificed, for completeness, for that diagram, in the program, as a whole, over its run, in practice, generally.
Diagrams, stored, as text, in a form, that can be, versioned, alongside code, for that program, in the program, as a whole, over its run, are easier, to keep current, for that program, in the program, as a whole, over its run, than diagrams, stored, as images, that must, be redrawn, manually, for each change, to structure, for that program, in the program, as a whole, over its run, in practice, generally, and specifically, for each diagram, in documentation, for a program, where its storage, format, affects, its maintainability, for that diagram, in the program, as a whole, over its run, over its lifetime, generally, because, text diagrams, can be, updated, in the same change, as code, itself, for that diagram, in the program, as a whole, over its run, in practice, generally, while, image diagrams, require, separate, editing, for that diagram, in the program, as a whole, over its run, that is, easily forgotten, for that diagram, in the program, as a whole, over its run, under deadline pressure, for that program, in the program, as a whole, over its run, in practice, generally.
Check: Why should diagrams be kept simple and stored in a form that can be versioned with code?
Section 19
Documentation review should be part, of code review, for a change, in the program, as a whole, over its run, because, a change, that alters, behaviour, for that change, in the program, as a whole, over its run, but, does not, update, its documentation, for that change, in the program, as a whole, over its run, in practice, generally, and specifically, for each change, reviewed, where its documentation, must be, checked, alongside, its code, for that change, in the program, as a whole, over its run, in practice, generally, will, leave, documentation, stale, for that change, in the program, as a whole, over its run, misleading, future readers, who trust, documentation, over code, itself, for that change, in the program, as a whole, over its run, in practice, generally, and specifically, for each reader, who trusts, stale documentation, for that change, in the program, as a whole, over its run, over the program's lifetime, generally, leading, to bugs, in their code, that uses, the program, incorrectly, based on, outdated documentation, for that change, in the program, as a whole, over its run, in practice, generally, and specifically, for each such bug, caused, by stale documentation, in a program, where its prevention, through review, must be, prioritised, for that documentation, in the program, as a whole, over its run, in practice, generally.
A reviewer, reading, documentation, as a stranger, would, for that documentation, in the program, as a whole, over its run, without prior knowledge, of the change, itself, for that documentation, in the program, as a whole, over its run, in practice, generally, and specifically, for each reviewer, reading documentation, for a change, where their fresh perspective, reveals, unclear passages, for that documentation, in the program, as a whole, over its run, in practice, generally, that the author, who wrote, both code, and documentation, for that change, in the program, as a whole, over its run, in practice, generally, may have, overlooked, for that documentation, in the program, as a whole, over its run, in practice, generally, because, the author, already understands, the change, for that change, in the program, as a whole, over its run, in practice, generally, and therefore, cannot, easily judge, whether, its documentation, is clear, to someone, who does not, already understand it, for that change, in the program, as a whole, over its run, in practice, generally.
That, constructive approach, to documentation review, for a change, in the program, as a whole, over its run, mirrors, the constructive approach, to code review, generally, in earlier chapters, on clean code, and on refactoring, for programs, as a whole, over their runs, where review comments, should suggest, concrete improvements, for a change, in the program, as a whole, over its run, rather than, merely criticising, it, for that change, in the program, as a whole, over its run, in practice, generally, and specifically, for each review, where its tone, shapes, whether, authors, welcome, review, as helpful, for their work, on shared code, in the program, as a whole, over its run, or dread it, as obstructive, for their work, on shared code, in the program, as a whole, over its run, in practice, generally, over the team's work, together, on shared code, in the program, as a whole, over its run, generally.
Check: What should a reviewer check about documentation when reviewing a code change?
Section 20
Keeping documentation from duplicating itself means, writing, each piece, of information, once, in one place, for that information, in the program, as a whole, over its run, and referring, to it, from other places, for that information, in the program, as a whole, over its run, rather than, copying, it, into many places, for that information, in the program, as a whole, over its run, in practice, generally, and specifically, for each piece, of information, in documentation, for a program, where its single source, must be, identified, for that information, in the program, as a whole, over its run, in practice, generally.
For, example, a tutorial, that needs, to describe, a function, for that tutorial, in the program, as a whole, over its run, should, link, to that function's reference entry, for that function, in the program, as a whole, over its run, rather than, copying, its parameter descriptions, into the tutorial, itself, for that tutorial, in the program, as a whole, over its run, in practice, generally, and specifically, for each tutorial, in a program, where its links, must replace, copies, for that tutorial, in the program, as a whole, over its run, in practice, generally, so that, when, the function's documentation, changes, for that function, in the program, as a whole, over its run, the tutorial, remains, correct, for that function, in the program, as a whole, over its run, without needing, any update, to the tutorial, itself, for that tutorial, in the program, as a whole, over its run, in practice, generally, and specifically, for each such link, in documentation, for a program, where its stability, depends, on single-sourcing, for that documentation, in the program, as a whole, over its run, in practice, generally.
What, single-sourcing, does, mean, for documentation, in a program, as a whole, over its run, is that, factual details, such as, parameter meanings, for a function, in the program, as a whole, over its run, and return values, for that function, in the program, as a whole, over its run, should have, one authoritative source, for those details, in the program, as a whole, over its run, typically, its docstring, for that function, in the program, as a whole, over its run, in practice, generally, and specifically, for each factual detail, in documentation, for a program, where its authoritative source, must be, clear, for that detail, in the program, as a whole, over its run, in practice, generally, while, other documents, may, present, those details, differently, for their audiences, for those details, in the program, as a whole, over its run, in practice, generally, and specifically, for each presentation, of a factual detail, in documentation, for a program, where its presentation, must not, contradict, its authoritative source, for that detail, in the program, as a whole, over its run, in practice, generally, but, should, refer, to it, for authoritative detail, for that detail, in the program, as a whole, over its run, in practice, generally.
Check: How does single-sourcing documentation prevent inconsistency as code changes?
Section 21
A script written for personal use still benefits from a short docstring at the top, because the person who returns to it after months away is, in effect, a stranger to their own earlier thinking. That top-of-file docstring should state what the script does, what input it expects, and what output it produces, in a few sentences, so that a reader does not have to reverse-engineer the whole file before deciding whether it is the right script for the job. It should also name any assumptions the script makes, such as the expected layout of a folder it reads, or the format of a file it writes, because those assumptions are exactly the things that break silently when the script is reused in a different setting. A script with no header docstring forces every future reader to infer its purpose from variable names and file operations, which is slow and error-prone, especially when the script is long or when its purpose is not obvious from its filename alone.
Scripts used by a team need more care, because several people may run them, and each of them needs the same reliable information. The header docstring should therefore also explain how to run the script, including the command and any required arguments, so that a colleague does not have to ask the author or guess at the invocation. If the script has command-line options, the docstring can summarise them briefly, while the full option help belongs with the argument definitions, where it is shown when the script is run with a help flag. This division keeps the docstring short while still giving users a route to full detail. It is also worth noting, in the docstring, any side effects the script has, such as deleting files, overwriting output, or sending messages, because a user who runs a script without knowing its side effects can cause harm that is hard to undo.
Finally, a script's docstring should record anything that would surprise a careful reader, such as a hard-coded limit, a default value chosen for a particular situation, or a step that is deliberately skipped. These notes save future maintainers from "fixing" behaviour that was intentional, and they save future users from being surprised by it. When the script changes, the docstring should change with it, in the same update, so that the two never drift apart. A habit worth building is to read the header docstring before editing a script, and to ask whether the edit makes any sentence in it untrue. If it does, update that sentence before finishing the change, and the script's documentation will stay trustworthy for the next person who runs it.
A script that will be run by other people should also say who to contact, or where to report a problem, so that a user who hits an unexpected result is not left guessing about what to do next.
Check: What should a script's top-of-file docstring state for a future reader?
Section 22
Data formats deserve documentation because data outlives the code that first produced it, and because a file or message whose format is undocumented becomes unreadable once its original author is unavailable. Documenting a format means stating, plainly, what each field means, what type it has, which fields are required and which are optional, and what values are allowed for fields with a limited set of meanings. It also means giving an example of a complete, valid record, so that a reader can compare their own data against a known-good sample and spot mistakes quickly. Without that example, readers must guess at details such as date formats, whether numbers are integers or decimals, or whether text fields may contain special characters, and those guesses are a common source of bugs in programs that exchange data.
Documentation of a format should also cover edge cases, because edge cases are where misunderstandings cause real damage. State what an empty field means, as opposed to a missing field, if the format distinguishes them, and state how missing data should be represented, if it can occur at all. State the ordering of records, if order matters, and state how duplicates should be handled, if duplicates can appear. These details often seem obvious to the person who designed the format, but they are not obvious to someone meeting it for the first time, and the cost of leaving them unstated is paid later, in debugging time, when two systems disagree about what a record means. A format document that answers these questions in advance prevents that disagreement before it starts.
Where a format changes over time, its documentation must record the change, and explain how old and new versions relate. Readers need to know whether a new field was added, whether an old field changed meaning, and whether files written in the old format can still be read by new code. Versioning a format, and documenting each version, is therefore part of documenting the format itself, not an optional extra. The simplest reliable habit is to keep the format document in the same place as the code that reads and writes the format, and to update it in the same change as any code change that alters the format. That way, a reader who finds the code will also find its format, and a reader who finds the format document will be reading the current version.
When a format is shared between teams, its documentation should also name the person or team responsible for it, so that questions about the format have a clear destination and changes to it are coordinated rather than made in isolation. Shared ownership of a format also makes it easier to agree on changes, because every team that uses the format has a voice in decisions that affect them.
Check: Why should a data format document include a complete example record and its edge cases?
Section 23
Configuration is the set of values that change how a program behaves without changing its code, such as file paths, thresholds, or connection details, and documenting it is essential because configuration is where users, rather than developers, make decisions. Each configuration option should be documented with its name, its purpose in plain language, its expected type, its default value, and what happens if it is left unset. A reader who finds an option without this information must guess at its purpose from its name, and names are often ambiguous, especially when they were chosen quickly during development. Documenting defaults is particularly important, because a user who does not know the default cannot tell whether their program is behaving as designed or whether a setting they forgot is silently shaping its behaviour.
Configuration documentation should also explain the interaction between options, where one option affects another, because users set options in combination, not in isolation. If raising one threshold makes another option irrelevant, or if two options must be set together to take effect, that relationship should be stated where both options are documented, so that a reader setting one of them learns about the other. It should also state the valid range for numeric options, and what happens outside that range, whether the program rejects the value, clamps it, or behaves unpredictably. Leaving range behaviour unstated invites users to set values that the program was never tested with, and then to report the resulting behaviour as a bug, when the real fault was missing documentation.
Finally, configuration documentation should tell users where each option can be set, if there is more than one place, such as a configuration file, an environment variable, or a command-line flag, and which source wins when the same option is set in several places. That precedence rule matters, because users who set an option in one place and see no effect will assume the program is broken, when in fact another source is overriding their setting. Keeping configuration documentation in the same file or help text that lists the options themselves, and updating it whenever an option is added, removed, or renamed, is the simplest way to keep it accurate. A configuration option that is undocumented is, for practical purposes, an option that does not exist for users.
It is also worth documenting how configuration values are validated, so that a user who mistypes a value learns about the mistake from a clear error message rather than from strange behaviour that is hard to trace back to a setting. Validation messages should name the option involved and state the acceptable values, so that a user can correct the mistake without searching through unrelated documentation. Clear messages save time.
Check: What five pieces of information should each configuration option's documentation include?
Section 24
Error handling deserves documentation because the way a program fails is part of its behaviour, and users and callers need to know what failures to expect. A function that can fail in a particular way should document that failure in its docstring, stating the condition that causes it and what the caller should do about it, in plain language. For example, a function that reads a file should say what happens when the file is missing, and a function that validates input should say what happens when the input is invalid. This information lets callers write correct handling code instead of guessing, and it lets them decide, in advance, whether a failure is something they can recover from or something they should let propagate to a higher level.
Documentation of errors should distinguish between different failure modes, because different failures need different responses. A missing file and a file with the wrong format are not the same problem, and a caller who handles both in the same way will either hide useful information or fail to recover when recovery was possible. Where a function raises exceptions, the docstring should name the exception types it can raise, and the conditions for each, so that callers can catch the specific exceptions they can handle and let others propagate. Where a function returns a special value to signal failure, the docstring should say exactly what that value is, and how it differs from a valid result, because a caller who cannot distinguish failure from success will treat failures as data.
Error documentation should also be kept honest, which means updating it when error behaviour changes, and not documenting errors that no longer occur. Stale error documentation is worse than missing error documentation, because it sends callers down the wrong path, writing handling code for failures that will never happen, while missing the failures that actually will. A good habit is to review the error section of a docstring whenever the function's failure behaviour changes, in the same update as the code change, and to ask whether each documented failure still occurs and whether any new failure has been introduced. That review costs little and prevents the slow accumulation of misleading error claims that erode trust in the documentation as a whole.
Documenting errors also helps when a program is maintained by a new team, because the new maintainers can see, from the documentation alone, which failures the original authors expected and which failures would indicate a genuinely new problem. That shared understanding reduces the time spent investigating failures, because maintainers can distinguish expected errors from genuine surprises at a glance. That clarity saves real debugging time for every team involved. That clarity matters greatly.
Check: Why should a docstring distinguish between different failure modes of a function?
Section 25
Documentation, like code, has versions, and readers need to know which version of the documentation matches the version of the program they are using. When a program changes, its documentation should change with it, but old versions of the documentation should remain available for users who have not yet updated, because those users still need accurate guidance for the version they actually run. A documentation set that only describes the latest version leaves users of older versions with guidance that does not match their program, and those users will either follow incorrect instructions or conclude that the documentation cannot be trusted. Keeping versioned documentation, where each release has its own matching set, solves this by giving every user the documentation that corresponds to their version.
Versioning documentation also helps when a reader is deciding whether to update. A changelog, as discussed earlier, summarises what changed, but versioned documentation lets a reader compare the full guidance for their current version against the guidance for a new version, and see, in detail, what would change for their workflow. This is especially useful for large updates, where the changelog may summarise broadly but the reader needs specifics about a feature they rely on. Clear version labels on every documentation page, showing which program version the page describes, prevent the common confusion of reading guidance for the wrong version, which is a frequent cause of wasted time when a reader follows instructions that do not apply to their installation.
A practical approach is to generate or publish documentation as part of each release, so that the documentation for a version is produced at the same time as the version itself, and to keep those published sets accessible, with the current version shown by default and older versions reachable through a version selector. That habit makes versioning automatic rather than a manual task that is easily forgotten under release pressure. It also means that fixing a documentation error in an old version is a deliberate decision, not an accident, because the published set for that version is a fixed record of what its users were told. Versioned documentation is therefore both a service to users of older versions and a discipline that keeps the documentation process honest.
When a documentation error is found in an old version, the fix should be recorded clearly, so that readers of that version can see the correction without having to guess whether the version they are reading has been updated. A clear correction note also protects users who printed or saved the older version, because they can compare what they have against the corrected guidance. Such notes keep older documentation honest and genuinely useful. Such notes genuinely keep documentation honest.
Check: Why should old versions of documentation remain available after a new release?
Section 26
Accessible documentation is documentation that people with different abilities can read and use, and it is a requirement, not a favour, because documentation that some users cannot read fails those users entirely. The most important accessibility habit is to write in plain, clear language, with short sentences and common words where possible, because clear writing helps everyone, including readers who use translation tools, readers with limited time, and readers who are not fluent in the documentation's language. Headings should be used in a logical order, so that readers who navigate by headings, including readers using screen readers, can understand the structure of a document and jump to the section they need without reading everything before it. Skipping heading levels, or using headings for visual effect rather than structure, breaks that navigation and makes documents harder to use for everyone who relies on structure.
Images and diagrams in documentation need text alternatives, because a reader who cannot see an image cannot learn from it unless its content is described in words. A diagram that shows a program's architecture should have a caption or accompanying text that states the same structure in prose, so that the information is available to all readers, not only to those who can see the diagram. Similarly, colour should never be the only way information is conveyed, because readers who cannot distinguish certain colours will miss information that is encoded only in colour. Labels, patterns, or text should always accompany colour, so that the same information is available through more than one channel. These habits cost little when they are built into the writing process, but they are expensive to add afterwards to a large documentation set.
Finally, documentation should be tested for accessibility in the same way it is tested for accuracy, by checking that pages work with keyboard navigation alone, that text contrasts well with its background, and that links have descriptive text rather than generic phrases that give no clue about their destination. A link labelled with the name of the page it leads to is useful to every reader, but it is essential to a reader who hears links read aloud out of context. Accessibility, like accuracy, is therefore best treated as part of the writing and review process, checked as each document is written, rather than as a separate audit at the end. Documentation written with accessibility in mind serves more readers, and serves all readers better.
Documentation written in plain language also benefits readers who are learning the subject itself, because they can focus on the concepts being taught rather than struggling with unnecessarily complex sentences. Plain language also makes documentation easier to translate, which extends its reach to readers who work in other languages and rely on translation tools.
Check: Why must colour never be the only way information is conveyed in documentation?
Section 27
A team that writes documentation together needs a shared style guide, because without one, each writer makes different choices about wording, structure, and formatting, and the resulting documentation set feels inconsistent, which undermines readers' confidence in it. A style guide for documentation does not need to be long; it needs to answer the questions writers actually ask, such as how to format function names, how to write parameter descriptions, what tense to use in summaries, and how to structure tutorials. Answering those questions once, in a shared document, saves every writer from deciding them afresh, and saves reviewers from debating them on every change. The guide should be short enough to read in one sitting, and it should be kept where writers will actually find it, not buried in a folder nobody opens.
A style guide works best when it is treated as a living document that the team can improve, rather than as a set of rules imposed once and never revisited. When a writer encounters a situation the guide does not cover, they should be able to propose an addition, and the team should discuss it and update the guide, so that the next writer facing the same situation has an answer. This process also prevents the guide from becoming a source of arguments, because decisions are made once, recorded, and then applied consistently, instead of being relitigated on every document. A guide that nobody follows is worse than no guide, because it creates the appearance of consistency while the actual documentation remains inconsistent, so the team should review, periodically, whether the guide is being followed and whether it still matches how the team actually writes.
The style guide should also cover the review process for documentation, stating who reviews it, what they check, and how disagreements are resolved, because documentation review, as discussed earlier, is part of code review, and it needs the same clarity about expectations. A new team member who reads the guide should be able to write a first document that matches the team's existing style, without needing to ask many questions, and a reviewer should be able to point to the guide when suggesting a change, rather than relying on personal preference. That shared reference makes documentation work faster, fairer, and more consistent, and it lets the team spend its review time on content and clarity, rather than on formatting debates.
A style guide should also include examples of good and bad documentation, because an example shows a writer what the guide means in practice far more clearly than a rule stated in the abstract. Examples in a style guide also speed up onboarding, because new writers can imitate a good example long before they have memorised every rule.
Check: What makes a documentation style guide useful rather than a source of arguments?
Section 28
Tests deserve documentation because a test suite is itself a kind of specification, and readers who cannot understand what a test checks cannot tell whether the program it tests is behaving correctly. Each test should have a name, or a short comment, that states what behaviour it verifies, in plain language, so that a reader scanning the test list can see, at a glance, which behaviours are covered and which are not. A test named only with a number, or with a vague label, tells a future maintainer nothing about its purpose, and when it fails, that maintainer cannot tell, from the test alone, whether the failure means a real bug or an outdated expectation. Clear test names are therefore a form of documentation, and they are often the first documentation a maintainer reads when investigating a failure.
Documentation for tests should also explain, where it is not obvious, why a particular case is tested, especially for edge cases and for cases that guard against a past bug. A test that checks an unusual input may look unnecessary to a reader who does not know the history behind it, and that reader may be tempted to remove it as redundant, only to reintroduce the bug it guarded against. A short comment explaining the reason for the test, such as the bug it prevents or the edge case it covers, protects the test from well-meaning removal and helps future maintainers understand the program's history. This is the same principle as documenting design decisions in code, applied to the test suite, where the cost of losing a test is the return of a bug that was once fixed.
Finally, the test suite as a whole should be documented at a higher level, stating how to run it, what setup it needs, and how long it takes, so that a new contributor can run the tests without asking for help. That high-level documentation belongs in the project's contributing guide or README, where new contributors will look for it, rather than hidden in individual test files. It should also state which tests, if any, need special conditions, such as network access or a particular environment, so that a contributor whose tests fail for environmental reasons does not mistake those failures for bugs in their change. Documented tests are easier to maintain, easier to trust, and easier for new contributors to join.
When a test suite grows large, a short overview of its structure, grouping tests by the area they cover, helps new contributors find the tests relevant to their change without reading the whole suite. A structural overview also helps reviewers, who can check that a change includes tests in the right area rather than hunting through unrelated test files.
Check: Why should a test that guards against a past bug carry a comment explaining its reason?
Section 29
A glossary is a list of terms used in a project, with a short definition for each, and it earns its place in documentation because every project develops its own vocabulary, and newcomers cannot be expected to know it. Terms that seem obvious to long-standing team members, such as the name of an internal component, or a shortened form of a longer concept, are often opaque to new readers, who must either ask someone or guess, and both options waste time and risk misunderstanding. A glossary that defines those terms, in plain language, gives newcomers a single place to look them up, and it gives existing team members a shared reference that prevents the same term from being used with different meanings by different people. That shared meaning matters, because a term used inconsistently across documentation and code creates confusion that is hard to trace.
A glossary should be kept short and focused, defining only the terms that are specific to the project or that are used in a special sense within it, rather than defining every general programming term, which readers can find elsewhere. Each definition should be one or two sentences, written for a reader who is meeting the term for the first time, and it should avoid using other undefined project terms, so that a reader does not have to chase definitions through a chain of cross-references. Where a term has a fuller explanation elsewhere in the documentation, the glossary entry can link to it, but the entry itself should still be understandable on its own, so that a reader who only needs a quick reminder does not have to read a whole guide. Keeping definitions short also makes the glossary easier to maintain, because short entries are easier to keep current than long ones.
The glossary should be updated whenever a new project term is introduced, in the same change as the code or documentation that introduces it, so that the term is defined from the moment it first appears. A term that appears in documentation before it appears in the glossary leaves early readers without a definition, and a term that appears in the glossary but is no longer used in the project clutters the list and reduces trust in it. Periodic review, removing terms that are no longer used and adding terms that have crept in without definition, keeps the glossary useful over time. A well-kept glossary is a small investment that pays off every time a new person joins a project and can understand its vocabulary without interrupting anyone.
A glossary is also useful for writers, because it gives them a shared set of definitions to use consistently, so that the same term does not drift into different meanings across different documents.
Check: What should a project glossary define, and what should it leave out?
Section 30
Documentation habits matter more than documentation tools, because a team with good habits and simple tools will produce better documentation than a team with powerful tools and no habit of writing. The most important habit is to write documentation at the same time as the code it describes, rather than postponing it to the end of a project, when the details are no longer fresh and when deadline pressure makes documentation the first thing to be cut. Writing as you go also improves the code itself, because trying to explain a function clearly often reveals that the function is confusing, or that its purpose is unclear, and that revelation is useful while the code is still easy to change. A developer who writes the docstring first, or alongside the code, is forced to think about the function's purpose before its implementation, which is a discipline that benefits both.
A second habit is to read documentation as a user would, before publishing it, by following its instructions from scratch, in a fresh environment, without relying on knowledge the reader would not have. That test catches the missing steps, the assumed settings, and the outdated examples that authors overlook because they know their own program too well to notice what a stranger would miss. It is the documentation equivalent of testing code, and it should be done with the same seriousness, because documentation that cannot be followed is not documentation at all, however well written it appears to its author. A team can build this habit into its review process, by asking reviewers to follow new documentation steps, or at least to read them as a stranger would, before approving a change.
A third habit is to treat documentation debt like code debt, by noting, openly, where documentation is missing or outdated, and by planning time to fix it, rather than letting it accumulate silently until the documentation set is untrustworthy. A short list of known documentation gaps, kept where the team can see it, is honest and actionable, while silent gaps are discovered only when a user is misled by them. These three habits, writing as you go, testing by following, and tracking gaps openly, are simple, but together they keep documentation current, accurate, and trusted, which is the real goal of all the techniques in this chapter. Tools and styles support those habits, but they cannot replace them.
A team that reviews its documentation habits regularly, asking which habits are working and which have slipped, will keep its documentation healthy far longer than a team that sets its habits once and never revisits them. Regular review of habits also lets a team drop practices that no longer help, keeping the documentation process lean instead of letting it accumulate needless ceremony.
Check: Why is writing documentation at the same time as code better than postponing it?
Section 31
Documentation for external users of an API carries a heavier responsibility than documentation for internal code, because external users cannot ask the author questions, cannot read private discussions about design decisions, and must rely entirely on what is published. The first duty of such documentation is therefore completeness for the public surface: every public function, class, and option should be documented, with its purpose, its parameters, its return value, and its failure behaviour, as discussed in earlier sections on function and class docstrings. Gaps in external API documentation are not minor omissions; they are places where users are forced to guess, and guessing about an API leads to code that works by accident, breaks on update, or misuses the API in ways the author never intended. A complete public surface, documented consistently, is the foundation of trust between a library and its users.
External API documentation should also be written from the user's point of view, starting from the tasks users want to accomplish rather than from the internal structure of the library. A user who wants to send a message, or to store a record, thinks in terms of that task, not in terms of the library's class hierarchy, and documentation organised by task helps them find the right entry point quickly. This does not mean abandoning reference documentation, which remains essential for lookup, but it means providing guides that lead users from their goal to the functions they need, with examples that show the whole task, not just a single call in isolation. Examples in external documentation should be complete enough to run, because a user who copies an example and finds it does not work loses confidence in the whole documentation set, and may abandon the library for one whose examples they can trust.
Finally, external API documentation must be honest about stability, stating clearly which parts are stable, which are experimental, and which may change, so that users can make informed decisions about what to depend on. An experimental feature documented without warning invites users to build on it, and then to complain, fairly, when it changes. A stable feature documented as experimental discourages use of something reliable. Marking stability clearly, and keeping those markings current as features mature, is therefore part of honest external documentation. When a public API changes in a breaking way, the documentation should say so prominently, in the changelog and in the affected entries, so that users updating to the new version are not surprised by failures in code that previously worked.
External documentation should also include a quick-start guide that takes a new user from installation to a first working result in a few minutes, because that early success convinces users that the library is worth learning in depth, and it gives them a working example they can adapt to their own task.
Check: Why does external API documentation carry a heavier responsibility than internal documentation?
Section 32
README-driven development is the practice of writing the README, or at least its main sections, before writing the code, and using it as a design tool rather than as a description written afterwards. The idea is simple: if you cannot explain, in a README, what a program does, how to install it, and how to use it for its main purpose, then you do not yet understand the program well enough to build it. Writing the README first forces the developer to decide on the program's purpose, its main workflow, and its public interface, before those decisions are locked in by code that is hard to change. It also exposes awkwardness early, because a feature that is hard to explain in a README is usually hard to use, and discovering that awkwardness before implementation is far cheaper than discovering it after users have learned the awkward interface.
A README written first also serves as a specification that the implementation can be checked against, because the developer, and any reviewer, can ask whether the finished program actually does what its README promises, and whether its installation and usage match the steps the README describes. When the implementation diverges from the README, one of them must change, and that decision is a design decision worth making deliberately, rather than a drift that happens unnoticed. This check is especially valuable for small projects, where formal specifications would be disproportionate, but where a README is already expected, so using it as the specification costs nothing extra. It also helps collaborators, who can read the README to understand what the project is meant to be, before they read any code, and who can therefore contribute in line with the project's intent.
README-driven development does not mean that the README, once written, is fixed, because programs evolve and their documentation must evolve with them, as discussed throughout this chapter. It means that the README is written early, used to guide design, and then kept current as the program changes, so that it remains an accurate description of the finished program. The habit is most useful at the start of a project, when decisions are still cheap to reverse, and it remains useful later, whenever a new feature is planned, because writing its README section first clarifies what the feature should do and how users will invoke it. That clarity, gained before coding begins, is the real benefit of the practice.
A README written first also helps when a project is handed to someone else, because the new maintainer can read the README to understand what the project was meant to be, rather than inferring its purpose from code that may have drifted from its original intent over time.
Check: How does writing a README before coding improve a program's design?
Section 33
Documentation in open source projects carries particular weight, because open source users and contributors are volunteers, and they choose where to spend their time based on how welcoming and understandable a project appears. A project with clear documentation, starting with a README that explains its purpose and how to contribute, attracts users who can get started without help, and contributors who can make their first contribution without asking many questions. A project with poor documentation, by contrast, loses potential users who cannot work out how to install it, and loses potential contributors who cannot work out where to begin, even though those people might have become valuable members of the community. Documentation is therefore not just a technical asset for open source projects; it is a community asset, and it shapes who joins and who stays.
Open source documentation should pay special attention to contribution guidance, because contributors need to know how to set up a development environment, how to run the tests, how to submit a change, and what standards their change will be judged against. That guidance should be written for a newcomer, not for an existing maintainer, because existing maintainers already know the process and do not need it explained, while newcomers, who do need it, are the audience that matters. It should also be honest about the project's current state, including known gaps and areas where help is welcome, because a newcomer who is directed towards a real, achievable task is far more likely to contribute than one who is left to guess at what the project needs. Labelling beginner-friendly tasks, and keeping that list current, is a practical way to turn documentation into an invitation.
Finally, open source documentation should be maintained with the same care as code, because outdated documentation in a public project misleads strangers at scale, and because contributors who find documentation they cannot trust are less likely to trust the project itself. Reviewing documentation changes with the same seriousness as code changes, and thanking contributors who improve documentation, signals that documentation work is valued, which encourages more of it. Many open source projects struggle to attract documentation contributors precisely because documentation work is undervalued compared with code, and treating it as first-class work, in review and in recognition, is the simplest way to change that. A project that values its documentation will, over time, have documentation worth valuing.
Documentation contributors should also be welcomed explicitly, with guidance on how to propose a documentation change, because many people who are unsure about contributing code feel confident about fixing a typo, clarifying a sentence, or adding an example, and those small contributions improve the project. Such contributions also build confidence, encouraging first-time contributors to attempt larger changes later.
Check: Why is documentation a community asset for open source projects, not just a technical one?
Section 34
Documentation that cannot be found is nearly as useless as documentation that does not exist, because readers who cannot locate the page they need will either guess, ask someone, or give up, and all three outcomes waste time. Search and navigation are therefore part of documentation design, not an afterthought to be added once the content is written. A documentation set should have a clear structure, with sections grouped by topic and by audience, so that a reader can browse from a general overview down to the specific page they need, without getting lost in an unstructured list of pages. That structure should be visible in a table of contents or sidebar that is present on every page, so that a reader who arrives at a page through search can still see where they are in the whole set, and can move to related pages without returning to the start.
Search within a documentation set should work well for the terms readers actually use, which means that pages should be titled with the words readers search for, rather than with clever or abbreviated titles that hide their content. A page about configuring a program should be titled in a way that a reader searching for configuration will find, and its first paragraph should state its topic plainly, so that search results are informative. Indexing and search tools can help, but they cannot rescue pages whose titles and introductions do not state what they are about, because search relies on the words on the page. Writers should therefore think, for each page, about what a reader would type when looking for it, and make sure those words appear in the title and opening paragraph, where search tools give them the most weight.
Navigation should also provide routes between related pages, through links in the text, through "next" and "previous" sequences for tutorials, and through cross-references from reference entries to guides that use them, as discussed earlier for linking between tutorials and reference material. These routes matter because readers rarely need only one page; they need a path through several pages, from learning a concept, to finding a function, to seeing an example, and a documentation set that provides those paths feels coherent, while one that leaves readers to find their own way feels fragmented. Testing navigation, by asking a newcomer to find a specific answer using only the documentation set, is a practical way to discover where structure and search fail, before real users encounter those failures.
Search results within documentation should also show a short summary of each page, so that a reader can judge, before clicking, whether a result is relevant, rather than opening several pages in turn to find the one that answers their question.
Check: Why are search and navigation part of documentation design rather than an afterthought?
Section 35
Deprecated features are features that still work but are planned for removal, and documenting them well is important because users who depend on them need time and guidance to move away. A deprecated feature should be marked clearly, wherever it is documented, so that a reader who encounters it knows, immediately, that it is not the recommended way to do something, and that new code should use the replacement instead. That marking should name the replacement, so that a reader does not have to search for what to use instead, and it should state when the feature is expected to be removed, if that date is known, so that users can plan their migration. A deprecation notice that says only that something is deprecated, without saying what to use instead, leaves users stuck, because they know their code is on borrowed time but not how to move off it.
Deprecation documentation should also explain, briefly, why the feature is being deprecated, because users who understand the reason are more likely to accept the migration, and less likely to work around the deprecation in ways that create new problems. If a feature is deprecated because it is unsafe, that should be said plainly, so that users do not continue to use it casually. If it is deprecated because a better alternative exists, the advantages of the alternative should be stated, so that users can see the benefit of migrating rather than feeling forced into pointless change. The explanation does not need to be long, but it should be honest, because users who feel that a deprecation is arbitrary are less likely to follow it, and more likely to pin their version to avoid it, which creates long-term maintenance problems for everyone.
Finally, deprecation documentation should be kept until the feature is actually removed, and then removed with the feature, so that the documentation set never describes a feature that no longer exists, and never fails to warn about a feature that still does. During the deprecation period, the changelog should record the deprecation, so that users updating to the version that introduces it learn about it even if they do not read the affected reference entry. A well-documented deprecation is therefore a bridge, giving users a clear path from the old way to the new way, with enough time and information to cross it safely, rather than a cliff edge that surprises them when the feature disappears.
A deprecated feature that is still widely used deserves a migration guide, not just a notice, because users with large amounts of code depending on it need step-by-step help to move, and a guide reduces the risk that they will postpone migration indefinitely. A guide saves time for everyone involved in the migration.
Check: What three things should a deprecation notice state for users who depend on the feature?
Section 36
Release notes are the announcement that accompanies a new version, and they differ from a changelog in tone and purpose, even though they cover similar ground. A changelog, as discussed earlier, is a systematic record of changes, grouped by kind, for users who want to check whether an update affects them. Release notes, by contrast, are written to be read, often by a broader audience that includes users who do not follow every version, and they therefore highlight the most important changes, explain them in terms of their benefit to users, and give the release a narrative, such as a theme or a focus, that helps readers understand what the release is for. A release that only fixes bugs may have short release notes, while a release that adds a major feature deserves notes that explain that feature, show how to use it, and link to fuller documentation for readers who want more detail.
Good release notes start with a summary that a busy reader can absorb in under a minute, stating the headline changes and who they matter for, before going into detail for readers who want it. That summary respects the reader's time, because most users will not read a long list of every change, but they do want to know whether this release is worth their attention. The detail that follows should be organised by importance, not by the order in which changes were made, so that the most significant changes come first and minor fixes do not bury them. Each highlighted change should link to its fuller documentation, so that a reader who is interested can learn more without searching, and so that the release notes themselves stay concise rather than duplicating full documentation, which would violate the single-source principle discussed earlier.
Release notes should also be honest, acknowledging known issues and limitations in the release, rather than presenting it as flawless, because users who discover a known issue on their own, after reading notes that omitted it, will trust future notes less. Acknowledging a limitation, with a workaround if one exists, or with a statement about when it will be fixed, is far better than silence, because it lets users plan around the issue instead of being surprised by it. Finally, release notes should be published where users will find them, alongside the release itself, and announced through the channels the project's users actually follow, because notes that are written but never seen help nobody. A release whose notes are clear, honest, and easy to find builds confidence in the project as a whole.
Release notes for a major version should also mention any support changes, such as a change in the versions of Python supported, because users planning an upgrade need to know whether their environment will still work with the new release.
Check: How do release notes differ from a changelog in tone and purpose?
Section 37
Onboarding documentation is the documentation that helps a new person become productive in a project, whether that person is a new user, a new contributor, or a new team member, and it deserves special care because the first days of using a project shape a person's long-term impression of it. Good onboarding documentation starts with the smallest useful task, something a newcomer can complete quickly and successfully, rather than with a comprehensive overview that overwhelms them before they have done anything. That first success matters, because it gives the newcomer confidence, and because it proves, to them, that the documentation works and that the project is usable. A newcomer who completes a small task on their first day is far more likely to return on the second day than one who spent the first day reading without doing.
Onboarding documentation should be written as a sequence, with each step building on the previous one, and with clear checkpoints where the newcomer can verify that they are on track, such as expected output after a command, or a screen they should see. Those checkpoints are essential, because a newcomer who goes wrong early, without realising it, will fail at every later step, and will not know where the failure began. The sequence should also anticipate common mistakes, and state, near the step where they occur, what to do if something goes wrong, rather than leaving troubleshooting to a separate page that the newcomer may not think to consult. Anticipating mistakes in place, at the point of failure, is one of the most helpful things onboarding documentation can do, and it requires the author to remember, or to learn, what actually goes wrong for newcomers, rather than what the author imagines might go wrong.
Finally, onboarding documentation should be tested with real newcomers, because authors, who already know the project, cannot reliably judge whether their onboarding sequence works for someone who does not. Watching a newcomer follow the documentation, without helping them, reveals the missing steps, the unclear instructions, and the assumed knowledge that the author overlooked, and fixing those gaps, based on observation rather than guesswork, is the fastest way to improve onboarding. That testing does not need to be formal; asking a colleague who has not used the project to follow the guide, and noting where they stall, is enough to find the most important problems. Onboarding documentation that has been tested in this way is a gift to every future newcomer, and it repays its cost many times over.
Onboarding documentation should also tell newcomers where to ask for help, and what information to include when they do, so that a newcomer who gets stuck can ask a question that others can actually answer, rather than struggling in silence.
Check: Why should onboarding documentation start with the smallest useful task rather than a full overview?
Section 38
Maintaining documentation over time is the hardest part of documentation work, because writing a document once is easy, but keeping it accurate as code, users, and projects change is a continuing effort that competes with every other demand on a team's time. The key insight is that maintenance must be built into the development process, rather than treated as a separate activity that happens when someone finds time, because time for separate documentation work is rarely found. When documentation updates are part of the same change as code updates, as discussed throughout this chapter, they happen naturally, because the person making the change is the person who knows what changed, and the review process checks both together. When documentation updates are deferred to a later task, they are made by someone who must reconstruct what changed, from code and from memory, which is slower, less accurate, and more likely to be postponed again.
A second maintenance habit is to review documentation periodically, even for parts of a project that have not changed recently, because documentation can become outdated through changes elsewhere, such as a change in a dependency, a change in the environment, or a change in the project's own conventions. A periodic review, even a light one, that checks whether examples still run, whether links still work, and whether instructions still match reality, catches decay before it misleads users. That review can be shared across the team, with different people checking different sections, so that no single person bears the whole burden, and so that fresh eyes, which notice problems that familiar eyes overlook, are brought to each section. Scheduling that review, rather than leaving it to chance, is what turns good intentions about maintenance into actual maintenance.
Finally, maintaining documentation means being willing to delete it, because documentation that is no longer relevant, that describes a removed feature, or that duplicates a better document, does more harm than good by confusing readers and by consuming maintenance effort that could be spent on current documents. Deleting outdated documentation should be treated as a normal, welcome part of maintenance, not as a loss, because a smaller, accurate documentation set serves readers better than a larger set that mixes current and stale guidance. A team that regularly prunes its documentation, updates it with its code, and reviews it periodically, will have a documentation set that users trust, and that trust is the real measure of documentation maintenance.
Maintenance also benefits from feedback, because users who report outdated documentation are doing the project a favour, and responding to those reports promptly, and thanking the reporter, encourages more reports and keeps the documentation set honest. Prompt responses also show users that their feedback is valued.
Check: Why must documentation maintenance be built into the development process rather than deferred?
Section 39
Documentation as code means treating documentation files like code files, storing them in version control, reviewing them through the same process as code, and building them with automated tools, so that documentation benefits from the same discipline that keeps code reliable. The most immediate benefit is versioning, because documentation stored in version control changes alongside code, and any version of the program can be matched with the documentation that described it, which solves the versioning problem discussed earlier without extra effort. It also means that documentation changes are reviewed, because a change to a documentation file goes through the same review process as a change to a code file, and reviewers can check accuracy and clarity together, as discussed for documentation review. That shared process is the practical mechanism that keeps documentation current, because it makes documentation updates part of every change, not an optional extra.
A second benefit is automation, because documentation stored as text files can be built, checked, and published automatically, in the same way code is built and tested. Automated checks can verify that examples in documentation still run, that links still resolve, that code samples match the current API, and that formatting is consistent, catching errors that human reviewers might miss, and catching them before publication rather than after users have read the faulty document. Automated publishing also means that documentation is rebuilt whenever it changes, so that the published set always reflects the current files, without a manual step that can be forgotten. These automations do not replace human review, because they cannot judge clarity or accuracy of explanation, but they remove a whole class of mechanical errors, freeing reviewers to focus on content.
Documentation as code also lowers the barrier to contributing documentation, because anyone who can contribute code, by editing a file and submitting a change, can contribute documentation in the same way, using the same tools and the same process. That familiarity matters, because a separate documentation system, with its own editor and workflow, discourages contributions from developers who already know the code workflow, and it creates a division between code contributors and documentation contributors that harms both. Treating documentation as code, therefore, is not just a technical choice about file formats; it is a choice about who can contribute, and about whether documentation is treated as part of the project or as an afterthought. Projects that make that choice consistently tend to have documentation that is better maintained, because more people can maintain it.
Documentation as code also makes it easy to check who changed a document and why, because version control records every change with its author and message, which helps future maintainers understand the history behind a piece of documentation.
Check: How does treating documentation as code lower the barrier to contributing documentation?
Section 40
Good documentation is valuable because it multiplies the value of code, by making that code usable by people who did not write it, and by preserving knowledge that would otherwise be lost when authors move on. Code without documentation can only be used by those who can read and understand its implementation, which is a small group, while code with good documentation can be used by anyone who can read its guides and reference, which is a far larger group. That difference in audience is the difference between a program that serves its author and a program that serves a community, and it is why documentation effort, which can seem like time taken away from coding, is actually time invested in the program's reach and longevity. A program whose documentation is clear will be adopted more widely, will attract more contributors, and will survive longer, because its knowledge is not locked in a few people's heads.
Good documentation also saves time, in ways that are easy to underestimate, because every question that documentation answers is a question that does not need to be asked, and answered, by a person. A team that writes clear documentation spends less time answering the same questions repeatedly, and its members spend less time interrupting each other for explanations that could have been written down once. Users, similarly, spend less time guessing, experimenting, and recovering from mistakes caused by missing information, and that saved time, across many users, far exceeds the time spent writing the documentation in the first place. Documentation is therefore not a cost to be minimised, but an investment whose return grows with the number of people who use the program, which is why the most widely used programs tend to have the most thorough documentation.
Finally, good documentation reflects respect for its readers, because it says, in effect, that their time matters, that they deserve clear guidance, and that the author has thought about their needs rather than only about their own. That respect builds trust, and trust is the foundation of any lasting relationship between a program and its users, whether that program is a library, a tool, or a service. The techniques in this chapter, from docstrings to style guides, from changelogs to documentation as code, are all means to that end, and they share a single principle, which is to write for the reader, not for the writer, and to keep what is written accurate, clear, and current. A learner who adopts that principle, and the habits that support it, will produce documentation that serves its readers well, and will be welcomed, as a contributor, by any team that values its users.
A learner who writes good documentation also learns the subject more deeply, because explaining something clearly requires understanding it well, and the act of writing often reveals gaps in that understanding that reading alone would not expose.
Check: Why is documentation an investment whose return grows with the number of users?
Section 41
Some readers of documentation are not programmers, and writing for them requires a different approach, because they cannot be expected to know programming terminology, to read code examples, or to follow instructions that assume familiarity with development tools. Documentation for non-technical readers, such as end users of a tool, or managers deciding whether to adopt a program, should focus on what the program does for them, in terms of their own goals, rather than on how it works internally. A user who wants to convert files, or to generate a report, cares about the steps they must take and the result they will get, not about the functions involved, and documentation that leads with internal details will lose them before it helps them. Leading with outcomes, and keeping technical detail in clearly marked sections for readers who want it, serves both audiences without forcing either to wade through material meant for the other.
Language is the most important choice when writing for non-technical readers, because jargon that programmers use without thinking is opaque to everyone else. Terms should be explained when they first appear, or replaced with plain words where a plain word exists, and instructions should use the reader's vocabulary, such as naming buttons, menus, and files as the reader sees them, rather than naming internal concepts. Sentences should be short, steps should be numbered, and each step should describe a single action, so that a reader can follow the sequence without having to hold several instructions in mind at once. Screenshots, or descriptions of what the reader should see after each step, help non-technical readers verify that they are on track, because they cannot judge, from code or logs, whether a step succeeded, and they need a visible confirmation that matches what the documentation promised.
Finally, documentation for non-technical readers should be tested with such readers, in the same way onboarding documentation is tested with newcomers, because programmers cannot reliably judge what a non-programmer will find clear. Watching a non-technical reader follow the documentation, and noting where they hesitate or go wrong, reveals assumptions that the author did not realise they were making, such as assuming the reader knows how to open a terminal, or where to find a downloaded file. Fixing those gaps, by adding the missing steps or explanations, makes the documentation genuinely usable by its intended audience, rather than usable only by programmers pretending to be non-technical readers. Documentation that serves non-technical readers well also serves technical readers, because clarity helps everyone, while documentation that only serves technical readers excludes a large group who deserve to use the program too. Clear documentation for non-technical readers also reduces support requests, because readers who can follow instructions unaided do not need to ask for help.
Check: Why should documentation for non-technical readers lead with outcomes rather than internal details?
Section 42
Dependencies are the external libraries and tools a program relies on, and documenting them matters because a program that cannot be installed, or that behaves differently with different dependency versions, is a program that users cannot trust. Dependency documentation should start with a complete list of what the program needs, including the names of the dependencies and the versions, or version ranges, that are known to work, so that a user installing the program can set up an environment that matches the one it was developed and tested in. That list should be kept in a machine-readable file where possible, so that installation tools can use it automatically, but it should also be explained in human-readable documentation, where a user who encounters an installation problem can see what is expected and compare it with what they have. A list that exists only in a file, without explanation, helps automated tools but not confused users, while a list that exists only in prose, without a machine-readable form, helps users but not tools, so both forms have a role.
Dependency documentation should also explain why each dependency is needed, at least for the less obvious ones, because a maintainer deciding whether a dependency can be removed, or replaced, needs to know what it provides and where it is used. A dependency added for a single feature, or for a convenience that could be replaced with a small amount of code, is a different proposition from a dependency that the whole program is built on, and that difference should be visible in the documentation, so that future decisions about dependencies are informed rather than guessed. It should also state, for each dependency, whether it is required for all uses of the program, or only for optional features, because a user who only needs the core functionality should not be forced to install everything, and a user who wants an optional feature should know which extra dependency it needs.
Finally, dependency documentation should cover what happens when a dependency changes, because dependencies are maintained by other people, and their updates can affect the program in ways that are not obvious from the program's own changelog. When a dependency releases a new version that changes its behaviour, the program's documentation should note the change, and the program's tests should be run against the new version, so that any incompatibility is found before users encounter it. Keeping dependencies documented, and their versions pinned or ranged deliberately, is therefore part of keeping the program itself reliable, because a program is only as stable as the dependencies it stands on, and documentation that makes those dependencies visible makes their risks manageable. That visibility helps everyone involved in the project.
Check: Why should dependency documentation include both a machine-readable list and a human-readable explanation?
Section 43
Performance characteristics deserve documentation because users make decisions based on them, such as whether a program can handle their data, or whether a function is fast enough for their use, and undocumented performance leaves those decisions to guesswork. Documenting performance does not mean publishing precise timings, which depend on hardware and data, and which would quickly become outdated, but it means describing, in general terms, how a function's cost grows with its input, and what factors affect it most. For example, a function that reads a whole file into memory should say so, because a user with a very large file needs to know that memory use will grow with file size, while a function that processes a file line by line can say that its memory use stays roughly constant, which is useful information for a user choosing between them. Those qualitative statements, about growth and about bottlenecks, are stable across hardware, and they help users reason about suitability without needing exact numbers.
Performance documentation should also state any limits or recommended ranges, such as the largest input a program is designed to handle comfortably, or the conditions under which it performs best, because users who exceed those limits without warning will experience slow performance, or failures, that they may blame on bugs rather than on exceeding the program's design. Stating limits honestly is not a weakness; it helps users plan, by telling them when they need a different approach, or when they should split their work into smaller pieces. It also helps maintainers, because a documented limit gives them a clear target when they improve performance, and a clear criterion for deciding whether an improvement is needed. A limit that is undocumented, by contrast, is discovered only through failure, which is the worst way to learn about it.
Finally, performance documentation should be updated when performance changes, in the same way other documentation is updated with code, because a performance improvement that is not documented may go unnoticed by users who worked around the old limitation, and a performance regression that is not documented will surprise users who relied on the old behaviour. The changelog should note significant performance changes, so that users updating to a new version learn about them, and the affected reference entries should be updated to reflect the new characteristics. Documenting performance, in qualitative terms, with limits and with updates, is therefore part of honest documentation, because performance is part of a program's behaviour, and users deserve to know how a program behaves before they commit their data and their time to it. Documenting performance honestly also builds trust, because users who know a program's limits can plan around them instead of discovering them through failure.
Check: Why should performance be documented in qualitative terms rather than precise timings?
Section 44
Security considerations deserve a place in documentation, because users need to know how to use a program safely, and developers need to know what safe use looks like, and documentation is where that guidance belongs. This section is about documenting safe use, not about attacking systems, and its focus is on helping users protect their data and their programs. Documentation should state, plainly, what sensitive data a program handles, such as passwords, tokens, or personal information, and how that data should be protected, for example by storing secrets in environment variables or a secure store rather than in code or in files that are shared. It should also state what a program does not do with sensitive data, such as never logging it, or never sending it to an external service, because users who know what a program does not do can trust it more, and can verify its behaviour against that claim. These statements are part of the program's contract with its users, and they should be kept current as the program changes.
Documentation should also guide users towards safe defaults, by explaining which settings are secure, which settings weaken security, and why, so that a user who changes a setting understands the trade-off they are making. For example, a setting that disables a security check for convenience should be documented with a clear warning, and with guidance on when, if ever, disabling it is appropriate, because a user who disables a check without understanding its purpose may expose their data without realising it. Similarly, documentation should explain how to report a security problem, giving a contact or a process, so that a user who discovers a weakness can report it responsibly, rather than discussing it publicly before it can be fixed. That reporting guidance is itself a security measure, because it channels reports to people who can act on them.
Finally, documentation for developers who use a library should highlight the safe way to use each feature, and warn against common unsafe patterns, without providing instructions for attacking anything. For example, documentation for a function that accepts user input should show how to validate that input, and documentation for a function that builds a query should show how to parameterise it, so that users who follow the examples are safe by default. Examples in documentation are copied by users, often without change, so examples that show safe practice spread safe practice, while examples that show unsafe shortcuts spread those shortcuts. Documenting security, therefore, is not a separate task from documenting use; it is part of documenting use well, because safe use is correct use, and documentation that shows the safe way is documentation that serves its readers best.
Check: Why should documentation examples show safe practice by default?
Section 45
Giving feedback on someone else's documentation is a skill, because documentation is personal in a way that code is not always, and a careless comment can discourage a writer who was trying to help. Feedback should start with what works, naming specific passages that are clear or helpful, before moving to what needs improvement, because a writer who hears only criticism may conclude that their whole document is bad, when in fact most of it is good and only a few passages need work. Specific praise also teaches the writer what to repeat, while vague praise, such as saying a document is good, teaches nothing, because the writer cannot tell which parts earned that praise. The same principle applies to criticism, which should be specific, pointing to the exact passage that is unclear, and explaining what a reader might misunderstand, rather than saying the document is confusing in general, which leaves the writer guessing at what to fix.
Feedback should also suggest, where possible, rather than only criticise, by offering a clearer wording, or by asking a question that reveals the gap, such as asking what a term means, or what a reader should do at a particular step. A suggestion gives the writer something concrete to work with, and it shows that the reviewer has engaged with the document as a reader, not just as a judge. When the reviewer is unsure what the writer meant, asking is better than assuming, because documentation feedback based on a misunderstanding can push a document in the wrong direction, while a question clarifies the writer's intent and leads to a better fix. That collaborative approach, where reviewer and writer work together to make the document clearer, mirrors the approach to code review discussed earlier, and it produces better documentation than a process where reviewers dictate and writers obey.
Finally, feedback should consider the reader, not just the reviewer's own preferences, because documentation is written for its audience, and a style choice that the reviewer dislikes may still serve the audience well. A reviewer should ask whether a passage will be clear to its intended readers, rather than whether it matches the reviewer's personal taste, and should distinguish, in their comments, between changes that are necessary for clarity or accuracy, and changes that are merely a matter of taste. That distinction helps writers prioritise, because they can address necessary changes first, and discuss taste changes separately, rather than treating every comment as equally urgent. Feedback given in this spirit, specific, constructive, and reader-focused, improves documentation and encourages writers to keep writing, which benefits every future reader of the project. Reader-focused feedback also builds a culture where writers welcome review, because they know it aims to help readers rather than to impose personal taste.
Check: Why should documentation feedback distinguish necessary changes from matters of taste?
Section 46
Commit messages are documentation, because they record why a change was made, and they are read, often years later, by maintainers trying to understand a piece of code, or by users trying to understand a version. A good commit message starts with a short summary, in plain language, stating what the change does, so that a reader scanning a history can see, at a glance, what each change was about, without reading the code itself. It then explains, briefly, why the change was made, because the reason for a change is often more important, and harder to recover, than the change itself, which can be seen in the code. A message that says only what changed, without saying why, leaves future readers to guess at the motivation, and that guess may be wrong, leading them to revert a change that was made for a good reason, or to keep a change whose reason no longer applies. Stating why, in a sentence or two, prevents that guesswork and preserves the decision behind the change.
Commit messages should also mention, where relevant, what the change does not do, or what alternatives were considered and rejected, because that information helps future maintainers avoid repeating work that was already tried, or avoid reintroducing a problem that was already fixed. A message that records that a simpler approach was tried and found insufficient, for example, saves a future maintainer from trying the same approach again, and a message that records a known limitation of a change helps future readers understand its scope. These notes do not need to be long, but they should be honest, because a commit history that only records successes, without recording limitations or rejected alternatives, gives a misleading picture of how a project developed, and of what its current state actually is.
Finally, commit messages should be written for future readers, not just for the author at the moment of writing, which means avoiding shorthand that only the author understands, and avoiding references to conversations or tickets that future readers cannot access, without explaining them. A message that says "fix it" or "as discussed" tells a future reader nothing, while a message that states the problem, the fix, and the reason, in plain language, remains useful long after the original context is forgotten. Treating commit messages as documentation, with the same care about clarity and audience as other documentation, is therefore a habit that pays off every time someone reads the project's history, which, for a long-lived project, is often. A clear commit history also helps new maintainers, because they can trace how a project evolved and why its code looks the way it does today. That history is genuinely valuable.
Check: Why should a commit message explain why a change was made, not just what changed?
Section 47
Examples and sample projects are a powerful form of documentation, because they show a program in use, in a complete, working form, rather than describing it in the abstract, and readers often learn faster from a working example than from a description. A good sample project is small enough to understand in a short time, but realistic enough to show how the program is actually used, including the setup, the main workflow, and the handling of a typical result, rather than a trivial snippet that omits the parts a real user must deal with. It should be complete, meaning that a reader can run it without filling in missing pieces, and it should be kept current, because a sample that no longer runs, due to changes in the program it demonstrates, misleads readers more than no sample at all, by giving them code that fails for reasons they cannot diagnose. Keeping samples current, by testing them as part of the project's test suite where possible, is therefore part of maintaining them as documentation.
Sample projects should also be documented themselves, with a short explanation of what they demonstrate, how to run them, and what a reader should notice in them, because a sample without explanation is just code, and a reader who does not know what to look for may miss its point entirely. That explanation should highlight the choices the sample makes, such as why a particular function is used, or why a particular pattern is followed, so that a reader who adapts the sample to their own task understands which parts are essential and which are incidental. A sample that is copied without understanding is a source of bugs, because the copier may carry over assumptions that do not apply to their task, while a sample that is understood can be adapted safely. Documentation around a sample, therefore, is what turns it from a piece of code into a teaching tool.
Finally, samples should cover a range of uses, from the simplest case to a more complex one, so that readers at different levels can find a sample that matches their needs, without being overwhelmed by a single sample that tries to show everything at once. A simple sample, for beginners, and a more complete sample, for experienced users, serve different audiences, as discussed earlier for audience-specific documentation, and both have a place in a documentation set. Samples should also be easy to find, linked from the main documentation, and from the README, so that a reader who wants to learn by example can find them without searching, because a sample that is hidden is a sample that will not be used, however good it is. Well-chosen, well-documented, well-maintained samples are among the most valuable documentation a project can offer.
Check: Why should a sample project be documented itself, not just provided as code?
Section 48
Translating documentation extends its reach to readers who work in other languages, and it is worth doing well, because a poor translation can mislead readers more than no translation, by giving them confidence in instructions they have misunderstood. Translation should start with the most important documents, such as the README and the main guides, rather than attempting to translate everything at once, because a complete translation of a large set is a huge task, and a partial translation that covers the most-used pages serves more readers than an abandoned attempt at completeness. The translated documents should be clearly marked with the language they are written in, and with the version of the original they were translated from, so that a reader can tell whether the translation matches the current original, or whether it lags behind it, which matters when the original has changed since the translation was made. That version marking, like versioned documentation generally, prevents readers from following outdated translated guidance without realising it.
Translation also requires care with terminology, because technical terms may not have a direct equivalent in another language, and different translators may choose different words for the same term, creating confusion within a single translated set. A glossary of translated terms, agreed in advance, helps translators use the same words consistently, and it helps readers, who can learn the translated terms once and then recognise them throughout the set. Code, function names, and commands should generally not be translated, because they must match the program itself, and translating them would make examples unusable, so translators need clear guidance on what to translate and what to leave in its original form. That guidance, like a style guide for original documentation, should be written down and shared, so that all translators work to the same standard.
Finally, translated documentation must be maintained, because an original that changes without its translations being updated will drift apart from them, until the translations describe a program that no longer exists. Maintenance can be managed by noting, for each translated page, when it was last updated and which version of the original it matches, and by prioritising updates to translations of pages that change most often, or that are most widely read. Contributors who translate documentation should be thanked and recognised, in the same way as other contributors, because translation is skilled, valuable work, and because a project that values its translators will keep them, while one that treats translation as an afterthought will lose them. Translated documentation, maintained with the same care as the original, opens a project to a global audience, and that openness is worth the effort it requires. Clear version marking also protects translators, because they can see at a glance which pages need updating when the original changes.
Check: Why should a translated document state which version of the original it was translated from?
Section 49
Measuring documentation quality is difficult, because quality is not a single number, but there are useful signals that a team can watch, to learn whether its documentation is serving its readers. One signal is feedback from readers, whether through questions, corrections, or comments, because a documentation set that generates many questions about the same topic is likely unclear on that topic, while a set that generates corrections is likely inaccurate in specific places that can be fixed. Tracking which pages generate the most questions, or the most corrections, gives a team a prioritised list of pages to improve, rather than leaving improvement to guesswork about which pages need work. That feedback should be welcomed, not resented, because readers who report a problem are helping the project, and a team that responds to reports promptly will receive more of them, which is a good thing, because it means problems are being found and fixed.
Another signal is whether readers can complete tasks using only the documentation, which can be tested, as discussed for onboarding, by watching newcomers follow a guide without help, and noting where they stall. That test measures the documentation's real effectiveness, rather than its appearance, because a document that looks polished but cannot be followed is not good documentation, while a plain document that guides a reader to success is. Teams can also check mechanical signals, such as whether examples still run, whether links still work, and whether pages are up to date with the current version, because those checks, which can be automated, catch decay before it affects readers. A documentation set that passes its mechanical checks, and that guides newcomers successfully, and that generates few repeated questions, is a set that can be trusted, even if no single number captures its quality.
Finally, measuring quality should lead to improvement, not just to measurement, because a team that collects feedback but never acts on it will soon stop receiving feedback, as readers conclude that reporting is pointless. Improvement should be planned, with time set aside for documentation fixes, in the same way time is set aside for code fixes, and with the most impactful fixes, those that affect the most readers or the most important tasks, done first. A team that measures, prioritises, and improves, in a regular cycle, will see its documentation get better over time, and will see its readers' questions become fewer and more specific, which is itself a sign of progress. Quality, in documentation as in code, is not achieved once, but maintained through a cycle of feedback and improvement, and that cycle is the real measure of a team's commitment to its readers. Watching those signals over time also shows whether improvements are working, because falling question counts suggest readers are finding answers unaided.
Check: What signals can a team watch to learn whether its documentation is serving readers?
Section 50
Bringing the ideas of this chapter together, a documentation plan for a project should start by identifying its audiences, because every other decision, from what to write, to how to organise it, to what style to use, depends on who will read it. A plan that names its audiences, such as new users, experienced users, contributors, and maintainers, and that states, for each audience, what documents they need, gives the team a clear picture of what to write, and prevents the common mistake of writing only for one audience while neglecting the others. That plan should also name the documents themselves, such as a README, tutorials, reference, a changelog, and a contributing guide, and should state, for each document, who maintains it, and when it is updated, so that maintenance is assigned rather than assumed. A plan that is written down, and shared, is far more likely to be followed than a plan that exists only as good intentions in a meeting.
A documentation plan should also set standards, by adopting, or writing, a style guide, as discussed earlier, and by deciding on tools, such as a documentation generator, and on processes, such as review and versioning, before the documentation set grows large, because retrofitting standards onto a large, inconsistent set is far harder than applying them from the start. Those standards should be proportionate to the project, because a small project does not need the elaborate process of a large one, and imposing heavy standards on a small project will discourage documentation rather than encourage it. The plan should therefore match its ambition to the project's size and audience, starting with the essentials, a clear README, accurate docstrings, and a changelog, and adding more, such as tutorials and translated guides, as the project grows and its audience widens. That gradual approach keeps documentation achievable, while still moving it in the right direction.
Finally, a documentation plan should be reviewed, like the documentation itself, because a project's audiences, and its needs, change over time, and a plan that suited a small project may not suit a larger one, or a project with a new audience. Reviewing the plan, asking whether its documents still serve their audiences, whether its standards are still followed, and whether its maintenance process still works, keeps the plan honest and useful, rather than letting it become a document that is cited but never followed. The goal of all of this, as this chapter has argued throughout, is documentation that readers can trust, that helps them use a program well, and that is maintained as part of the program itself, not as an afterthought. A learner who can make such a plan, and follow it, will produce documentation that serves its readers, and that reflects well on every project they work on.
Check: What should a documentation plan name for each audience it serves?
Practical Task
Pick a small Python program or module you have written, or write a short new one of about fifty lines, and give it a complete documentation treatment. Write a module docstring, a docstring for every function, a README that explains its purpose, installation, and a working example, and a changelog entry for its first version. Then ask a friend, or a fellow learner, to install and run it using only your documentation, without help from you, and note every place where they stall, ask a question, or go wrong. Fix those gaps, update the documentation, and write a short note on what the test revealed about your documentation.
Chapter Questions
- Why is a docstring more useful than a comment for describing a function's public behaviour?
- How does keeping documentation in the same change as code prevent documentation drift?
- What is the difference between tutorial documentation and reference documentation, and why does a project need both?
- Why should a deprecation notice name a replacement and state when removal is expected?
- How does treating documentation as code improve its maintenance and its accessibility to contributors?