第10章 编写项目文档

第10章 编写项目文档

学习目标

  • 能为一段接口改出可执行的文档示例并说明其失败语义
  • 能用 Sphinx 在 CI 中把断链和严重警告判为构建失败
  • 自测:为什么一个超长 README 不能替代按受众分层的信息架构?

为什么需要项目文档

想象你接手一台别人搭好的机器,说明书只写着"按这个按钮就行",却没说它吃什么、坏在哪、怎么停。你不敢动它,因为任何意外都可能算到你头上。文档就是这份让你敢接手、敢修、敢交出去的说明书。

没有它,代码再好也只有作者一个人能用。新人一脸懵,接手的人改一处怕崩一片,发布时连"这个版本对应哪份说明"都对不上。等作者离职,项目只剩下一堆没人敢碰的代码。

好的文档不是写得多,而是让对的人在对的地方找到对的信息——把作者脑子里的隐含知识,变成任何一台干净机器都能重放的显式步骤。

文档的五个支柱

先预测:一段示例在作者机器上跑通了,是否就能证明它可维护?不能。还要说清解释器与依赖、输入边界、失败路径、可观察结果和重建步骤。本章围绕五个支柱展开,每个支柱都回答"谁在什么时候需要什么信息"。

编写项目文档
技术写作七原则、reStructuredText、Sphinx、受众、验收七原则技术写作七原则reSTreStructure…SphinxSphinx构建受众文档组合与受众验收文档验收
技术写作七原则

先写结构再润色,面向明确读者,示例真实且最小,用模板保持一致。信息轻量但充分。

下面逐个拆解这五个支柱,先看每个支柱是什么,再看它防住哪种失败。

支柱一:技术写作七原则

原书总结的 ,核心是"先写结构再润色"。先定好面向哪个读者、覆盖哪些主题、用什么模板,再去打磨文字;示例要真实且最小,信息轻量但充分。先写出公共行为和失败类型,再选择语法或工具,这样即使工具从原书生态迁到当前生态,调用者仍能依据相同契约判断结果。

def parse(payload: bytes) -> list[Entry]:
    """Parse one feed payload.
 
    Raises:
        ParseError: If the document is malformed.
    """
    ...

这段 docstring 先声明公共行为(解析一条 feed)和失败类型(malformed 抛 ParseError),正是"先写契约"在文档层的落地:调用者不读实现也能判断结果。

支柱二:reStructuredText

原书用 表达标题、列表、内联标记、代码块和链接。关键认知是:标记语法服务于语义结构,不能用视觉缩进替代可解析层级。下面是一段最小示例:

Atomisator Parser
==================
 
Parse a feed::
 
   entries = parser.parse(payload)
 
See :class:`atomisator.Parser`.

标题用下划线表示层级,:: 引出代码块,:class: 是交叉引用角色。它们都是可被解析器识别的语义标记,不是"缩进好看"的视觉效果——这也是它和随手敲 Markdown 的本质差别。

支柱三:Sphinx 构建

文档工具 把源文档、自动 API 和交叉引用构建成可发布站点。构建必须在 CI 中把断链和严重警告当作失败,否则断链会悄悄堆积到没人管。

sphinx-build -W --keep-going docs docs/_build/html
python -m doctest docs/examples.txt
python -m unittest discover -s tests

-W 把警告升级为错误,--keep-going 让构建尽量跑完再报全部问题,doctest 把文档里的示例变成可执行证据。三者组合,让"文档过时"在 CI 阶段就暴露,而不是等用户照抄报错。

支柱四:文档组合与受众

设计、使用和运维文档回答的是不同问题,这正是 这套方法要解决的事。生产者需要搭建指南,消费者需要使用教程,运维人员需要排障手册。一个超长 README 把三者混在一起,会让每类读者都在错误的地方翻找。正确做法是按受众分入口,让每类读者第一时间看到自己关心的信息。

支柱五:文档验收

最后由 负责收束。代码示例应可执行,版本与配置要明确,发布时文档和制品同版本;过期页面应删除或标明适用范围,而不是长期保留冲突答案。保存解释器、依赖锁定、输入、命令、退出状态、关键输出和制品摘要,才能让另一台干净机器重放同一结论。

实战验收清单

  1. 在隔离环境运行三段示例,记录解释器实现、版本和依赖来源。
  2. 为核心行为增加正常、空输入、失败和重复执行测试,先看到失败再修改实现。
  3. 清理缓存和临时文件后重跑,证明结果不依赖工作区残留。
  4. 对历史命令写出当前替代路径,并说明保留的架构不变量与不再采用的安全默认。

迁移决策题

设想团队正在维护一个运行多年的 Python 服务:它仍依赖本章对应的历史工具,但业务不能停机。先不要直接重写。第一步列出技术写作七原则承担的真实输入和输出,再用 reStructuredText 识别构建或运行时依赖;第二步把 Sphinx 构建放进隔离实验,证明当前行为与失败类型;第三步用文档组合与受众设计兼容层,让旧入口和新入口在同一组契约测试下运行;最后以文档验收保存制品摘要、行为差异与回滚条件。只有新路径在正常、边界和故障输入上都达到既定条件,才逐步切换。这样迁移的是可验证契约,而不是把一个旧命令盲目替换为一个新命令。

常见误区

误区 1

现象 → 文档写了却没人看,照样踩坑 原因 → 没有先定结构和受众,把所有信息塞进一个 README 修法 → 先按受众分层再填内容,每类读者给独立入口

误区 2

现象 → Sphinx 构建一堆警告,大家习惯了直接忽略 原因 → CI 没把警告判为失败,断链悄悄堆积 修法 → 构建加 -W --keep-going,警告即失败、阻断合并

误区 3

现象 → 文档里的示例跑不通,读者照抄就报错 原因 → 示例未纳入 CI 验证,文档随代码漂移 修法 → doctest 纳入构建,示例与制品同版本发布

小结

  • 先写结构再润色,面向明确读者,示例真实且最小
  • reStructuredText 的标记服务于语义结构,不用视觉缩进替代可解析层级
  • Sphinx 构建在 CI 中把断链和严重警告判为失败
  • 设计、使用、运维文档面向不同受众,需不同入口
  • 代码示例可执行,版本配置明确,过期页面标明适用范围

练习

练习

问题 1:(改代码型)把下面 docstring 改成先声明失败类型、再补一句边界说明,并说明它如何帮助验收。

def parse(payload: bytes) -> list[Entry]:
    """Parse one feed payload."""
    ...

问题 2:(问答型)为什么一个超长 README 不能替代按受众分层的信息架构?

问题 3:(独立实现型)为一个已有 Python 包写一份最小 Sphinx 构建配置,要求构建失败即阻断合并。

名词解释

名词解释

本章出现的专业名词,用大白话再讲一遍。

技术写作七原则

先写结构再润色、面向明确读者、示例真实且最小的写作约束集。就像盖房子先搭框架再装修,框架没立好,装修再漂亮也会塌。

reStructuredText

一种用标题、列表、代码块等语义标记表达文档结构的纯文本标记语言。类似 Markdown,但更强调"标记代表含义"而不是"标记只是好看"。

Sphinx

把 reStructuredText 源文档、自动 API 和交叉引用构建成可发布站点的文档工具。相当于文档界的编译器,把一堆文本文件编成一个能点能跳的网站。

文档组合与受众

按设计、使用、运维等不同读者分层提供不同入口的信息架构方法。好比一本说明书拆成"快速上手""完整教程""故障排查"三本小册子,各给对应的人。

文档验收

用可执行示例、明确版本和制品同版本证明文档有效且不过期的验收手段。即文档不只是写出来,还要能像代码一样被跑、被检查、被对版本。

资料与写作方式声明

本章以Tarek Ziade《Expert Python Programming》合法公开试读核定可见范围,并以目录限定未公开部分,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…