关于 documentation
面向编写和审查软件文档的开发者,依据 Microsoft 的契约优先约定,强调清晰描述行为与契约,并避免冗余或过时内容。
主要功能
- 01记录意图与契约
- 02摘要控制为一行
- 03说明错误与边界情况
- 04避免重复函数签名
- 05按格式选择文档规范
- 06审查过时及冗余注释
适用场景
- 01编写 API 与代码文档
- 02审查现有文档块
- 03整理文档健康状况报告
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ alexander-danilenko/ cortex-claude-code-plugins --skill documentation安装后在 Claude Code 中输入/documentation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-docs.mdcoverage-reports.mdpython-docstrings.mdtypescript-jsdoc.md详细介绍
文档
Microsoft 合约优先约定。文档说明合约——某项内容的作用和原因——而不是其内部实现方式。
为什么规则旨在精简
代码会变更,旁边的注释通常不会。时间久了,文档就会变得不实,但读者仍会相信它——过时的注释比没有注释更糟,因为它会主动误导读者。因此,要养成两种习惯,下面的每条规则都是其中一种习惯的具体应用:
精简表面内容。 文字越少,过时的内容就越少。注释是最后手段,而不是第一步:写注释前,先想想更准确的名称、更小的函数或命名类型是否能表达其含义。文字说明只用于补充代码确实无法表达的内容。
**每条事实只放在一个地方,**紧挨着负责维护它的代码,这样恰好只需更新一处。当签名、类型或测试已经说明某件事时,文字说明就不应再重复。
最简原则
签名已经包含名称、参数名称和类型、返回类型及修饰符(readonly、?、async)。文档只补充读者无法从签名推断出的内容:意图、单位、范围、默认值、边界值含义、错误情况和不变量。
每个公开成员仍需提供简短摘要,以便生成的文档和 IDE 工具提示有内容——用一个简短句子说明意图,绝不改写签名。
对于 @param 和 @returns,如果标签只会重复签名内容,就完全删掉该标签。 只有在回答以下问题时,标签才有必要:单位是什么?范围或钳制值是多少?省略时的默认值是什么?边界值代表什么(0 表示禁用,-1 表示不限制,空值 = 全部)?null 与抛出异常分别表示什么?
@throws 的默认规则恰好相反——只要代码可能抛出异常,就记录下来,因为签名无法体现可能抛出的异常。
文档块的形式
文档块会显示在 IDE 工具提示、悬停卡片和代码审查差异中——这些界面会展示开头,然后截断其余内容。因此,篇幅按渲染后的行数计算,而不是按句子数计算:
- 摘要——恰好一行。 用一个句子说明意图,单独放在文档块顶部。不能占两行,也不能写两个句子。
- 详情——最多三行,放在一个空行之后,并且只有在摘要确实无法涵盖合约时才添加。只写主要内容:操作的作用及其约束条件,而不是分支方式。
- 行内
//或#注释——最多三行,最好一行。
内容超出限制时,不能靠重新换行来解决;这意味着内容放错了位置。分支行为、边界情况和约束背后的理由应放到 @remarks(Python 中为 Note: / Notes)中,这样文档块的开头才能保持易读。
格式化后再衡量,而非格式化前。 写好文档块后,使用项目的格式化工具,按照配置的宽度重新排版(检测顺序见 Conventions),再统计生成的行数。若摘要被折成两行,就超出了限制:删减文字,直到它能放在一行内——不要把它拆成第二个句子,因为那样的句子只是伪装成摘要的详情。格式化工具或 max-len 规则将行内注释延展到三行以上时,也要进行同样的检查。
文档表述方式
你在这里写的每句话——摘要、保留下来的 @param 说明、@throws 条件、端点描述——都会在调试过程中被阅读,而读者可能不会说你的第一语言。请深入掌握 simple-english 技能(/cortex-communication:simple-english practical),并在写作时遵循其规则。要在写第一个文档块之前就运用它,而不是事后再润色:改写已经提交的文字,比一开始就写对更费力。
它对文档块的具体影响:
- 整个文件中,一个概念只用一个词。
@param写“validate”,摘要却写“check”,读者会以为这是两个不同的操作,然后开始寻找它们之间的区别。 - 描述性句子不超过 25 个词,祈使句不超过 20 个词。 摘要超过这个长度,就承载了不止一个事实,应该放在
@remarks中。通常行宽限制会先起作用,因此要把词数视为上限,并以实际排版后的行作为检验。 - 用
can、will、must,绝不使用should。 契约若说调用方“should”传入已排序的数组,读者就会猜测这条规则是否具有约束力。请写must,或说明调用方不这样做时会发生什么。 - 先写条件,再写后果。 “如果
retries为0,调用会立即失败”优于调换顺序,因为读者先能判断句子是否适用于自己,再理解结果。 - 没有衡量依据,就不要用形容词。 “高效地缓存”毫无意义。请给出界限,或删掉这个词。
标识符、代码示例和引用的错误字符串必须保持原样——规范将它们视为技术名称,读者复制“修正”后的内容会遇到新的错误。
约定
- 代码符号的摘要使用第三人称——“计算……”“查找……”“初始化一个新的……”——符合 Microsoft API 参考文档惯例。两种情况仍使用祈使句:表示操作步骤的行内
//注释,以及 API 操作的summary字段(OpenAPI、@ApiOperation、extend_schema),其中“Create a new user”是既定写法。 - 接口说明抽象内容:用途、抛出的错误、返回语义、不变量。实现细节(缓存、查询、算法)应放在实现中——阅读接口的使用者不应了解可能因重构而失效的内容。
- 数据结构说明是什么,而不是什么原因。 DTO、记录、结构体,或描述它们的
interface/type,应说明每个成员_是什么_——含义、单位、格式、允许值,以及类型本身无法表达的约束。不要解释字段存在的原因。函数契约确实包含操作的原因;而数据字段是在使用时读取的,设计缘由(“保留此字段以便账单系统可以核对……”)会逐渐过时,应该放在生成或使用该字段的行为说明中。例外情况——维护者绝不能破坏的非显而易见约束——可少量写在@remarks中,绝不能作为默认写法。 - 不要在实现中重复接口说明。 继承文档(
@inheritDoc或该语言的等效写法),只补充实现特有的说明。 - 只使用多行文档块。 每个
/**后,正文都必须另起一行;不允许使用单行/** … */。 - 除非明确要求,否则不要添加发布标签(
@public、@beta、@alpha、@internal)。 - 只提供测试套件会运行的示例。 未执行的示例会逐渐过时,成为又一条错误注释。运行时会执行的 Python doctest 符合要求(
pytest --doctest-modules);工具不会执行 TSDoc@example块,因此应将其省略,让测试说明行为。 - 按照项目配置的行宽换行。 按以下顺序检测:
.editorconfig中的max_line_length→ 格式化工具配置(printWidth、line-length)→ 代码检查工具配置(max-len、max-line-length)。只有都未定义时,才使用 80。
看到就删除的注释
审查时,删除这些注释和补齐文档缺漏同样重要——它们都可能导致信息与事实脱节:
- 已注释掉的代码——版本控制已经记录了它,保留它只会让读者疑惑它是否仍有用。
- 日志或变更记录注释(“2024-03 added retry logic”)——
git log能准确记录这些信息。 - 署名行(“added by …”)——
git blame可以解答,无需让署名信息逐渐过时。 - 横幅、位置标记、右花括号标签(
// ===== helpers =====、} // end if)——代码本身应体现结构。 - 任何复述名称、类型或签名,或陈述显而易见内容的注释(
/** Default constructor */)。
处理文档任务
开始前,先询问项目使用哪种格式(或从现有文件中识别),并识别其框架——不同框架的 API 文档策略各不相同,套用错误的策略会产出无人使用的规范。
汇报质量,而非数量。目标不是让每个成员都有文档块,尤其是其中一半都在复述签名时。应汇报具体改进:删除了冗余内容、修正了过时文档、补充了意图摘要和 @throws。覆盖率百分比只是最低限度的参考——它能找出空白成员,却无法区分有价值的文档块和空洞的文档块。
参考资料
| 参考资料 | 何时加载 |
|---|---|
references/python-docstrings.md | Python——Google、NumPy 或 Sphinx 风格 |
references/typescript-jsdoc.md | TypeScript/JavaScript——TSDoc 标签、@inheritDoc、格式 |
references/api-docs.md | REST API 文档——NestJS、Express、FastAPI、Django |
references/coverage-reports.md | 审查文档;生成文档健康报告 |