documentation-standards

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Documentation Standards

文档编写标准

README Template

README 模板

Every project README should follow this structure. Omit sections that genuinely do not apply, but default to including them.
markdown
undefined
每个项目的 README 都应遵循以下结构。若确实不适用的章节可省略,但默认需包含所有章节。
markdown
undefined

Project Name

项目名称

[Build Status][ci-link] [Coverage][coverage-link] [npm version][npm-link] [License][license-link]
One-paragraph description of what this project does, who it is for, and why it exists. Lead with the value proposition, not the technology.
[构建状态][ci-link] [覆盖率][coverage-link] [npm 版本][npm-link] [许可证][license-link]
一段简短的描述,说明本项目的功能、适用人群及存在价值。优先阐述价值主张,而非技术细节。

Table of Contents

目录

Installation

安装

Prerequisites

前置依赖

  • Node.js >= 18
  • PostgreSQL >= 14
  • Node.js >= 18
  • PostgreSQL >= 14

Steps

步骤

npm install project-name
npm install project-name

Quick Start

快速入门

Minimal working example — no more than 10 lines — that gets the reader from zero to "it works."
最简可运行示例 —— 不超过10行代码,帮助读者从零基础到成功运行项目。

Usage

使用方法

Common Use Cases

常见使用场景

Organize by task, not by API surface. Show the most common workflows first.
按任务组织内容,而非按 API 范围。优先展示最常用的工作流。

Advanced Usage

进阶使用

Edge cases, complex configurations, integration patterns.
边缘案例、复杂配置、集成模式。

API Reference

API 参考

Link to generated docs or inline the reference here.
链接至自动生成的文档,或在此处内嵌参考内容。

Configuration

配置

VariableDefaultDescription
PORT
3000
Server listening port
DATABASE_URL
PostgreSQL connection string
变量名称默认值描述
PORT
3000
服务器监听端口
DATABASE_URL
PostgreSQL 连接字符串

Architecture

架构

Brief overview or link to architecture docs.
简短概述或链接至架构文档。

Contributing

贡献指南

See CONTRIBUTING.md.
详见 CONTRIBUTING.md

License

许可证

MIT — see LICENSE file for details.
undefined
MIT —— 详见 LICENSE 文件内容。
undefined

README Checklist

README 检查清单

  • Title matches the package/repo name exactly
  • Description answers "what," "who," and "why" in one paragraph
  • Installation steps are copy-pasteable and tested on a clean machine
  • Quick Start example actually works — verify before merging
  • Badges are live and point to correct URLs
  • All links resolve (no 404s)
  • Configuration table covers every environment variable
  • License is explicitly stated and matches the LICENSE file

  • 标题与包/仓库名称完全一致
  • 描述部分用一段话回答“是什么”“给谁用”“为什么存在”
  • 安装步骤可直接复制粘贴,并在干净环境中测试通过
  • 快速入门示例确实可运行 —— 合并前需验证
  • 徽章为实时状态,且指向正确的 URL
  • 所有链接均可正常访问(无 404 错误)
  • 配置表格涵盖所有环境变量
  • 许可证已明确说明,且与 LICENSE 文件内容一致

Inline Code Comments

内联代码注释

When to Comment

何时添加注释

Comment the why, never the what. If you feel the need to explain what code does, refactor the code to be self-explanatory first.
注释应说明原因,而非内容。若你觉得需要解释代码的功能,应先重构代码使其具备自解释性。

Good Reasons to Comment

适合添加注释的场景

python
undefined
python
undefined

We retry up to 3 times because the upstream API occasionally

我们最多重试3次,因为上游 API 在部署期间偶尔会返回503错误(详见事件 #247)。

returns 503 during deployments (see incident #247).

for attempt in range(3): response = call_api() if response.status != 503: break
for attempt in range(3): response = call_api() if response.status != 503: break

Sorting by created_at DESC intentionally — the UI shows newest

特意按 created_at 降序排序 —— UI 会优先展示最新内容,而客户端侧重新排序会导致可见的闪烁问题。

first and re-sorting client-side causes a visible flicker.

queryset = queryset.order_by("-created_at")
queryset = queryset.order_by("-created_at")

HACK: The PDF library misreports page count for encrypted files.

临时解决方案:PDF 库会错误统计加密文件的页数。

Remove this workaround when upstream fixes #892.

当上游修复 #892 问题后,移除该临时方案。

page_count = max(pdf.page_count, 1)
undefined
page_count = max(pdf.page_count, 1)
undefined

Bad Comments — Remove or Refactor

应删除或重构的不良注释

python
undefined
python
undefined

Increment counter

递增计数器

counter += 1 # REMOVE: the code says this already
counter += 1 # 移除:代码已明确表达此含义

Check if user is admin

检查用户是否为管理员

if user.role == "admin": # REMOVE: rename to is_admin check
if user.role == "admin": # 移除:可重命名为 is_admin 检查

This function gets the user

此函数用于获取用户

def get_user(id): # REMOVE: the function name says this ...
undefined
def get_user(id): # 移除:函数名称已明确表达此含义 ...
undefined

Comment Types and When to Use Them

注释类型及适用场景

TypeUse When
TODO
Known work remains; include a ticket number
FIXME
Known bug or fragile code; include a ticket number
HACK
Intentional shortcut with known trade-offs; explain why
NOTE
Non-obvious design decision that future readers need
WARNING
Code that will break if assumptions change
Always attach a ticket or issue number to
TODO
and
FIXME
so they can be tracked and cleaned up.

类型适用场景
TODO
已知有未完成的工作;需包含工单编号
FIXME
已知存在 bug 或脆弱代码;需包含工单编号
HACK
有意采用的捷径,且已知其权衡;需解释原因
NOTE
未来读者需要了解的非显而易见的设计决策
WARNING
若假设条件改变,代码会出现问题
务必为
TODO
FIXME
添加工单或问题编号,以便跟踪和处理。

JSDoc and Docstring Conventions

JSDoc 与 Docstring 规范

JavaScript / TypeScript (JSDoc)

JavaScript / TypeScript(JSDoc)

typescript
/**
 * Calculate the compounded interest for a given principal.
 *
 * @param principal - Initial investment amount in cents
 * @param rate - Annual interest rate as a decimal (e.g., 0.05 for 5%)
 * @param periods - Number of compounding periods
 * @returns The total value after compounding, in cents
 * @throws {RangeError} If rate is negative or periods is less than 1
 *
 * @example
 * ```ts
 * const total = compoundInterest(10000, 0.05, 12);
 * // => 10511
 * ```
 */
function compoundInterest(
  principal: number,
  rate: number,
  periods: number
): number {
  // ...
}
typescript
/**
 * 计算给定本金的复利。
 *
 * @param principal - 初始投资金额(单位:分)
 * @param rate - 年利率(小数形式,例如 0.05 代表 5%)
 * @param periods - 复利计算期数
 * @returns 复利计算后的总金额(单位:分)
 * @throws {RangeError} 若利率为负数或期数小于1
 *
 * @example
 * ```ts
 * const total = compoundInterest(10000, 0.05, 12);
 * // => 10511
 * ```
 */
function compoundInterest(
  principal: number,
  rate: number,
  periods: number
): number {
  // ...
}

Python (Google Style Docstrings)

Python(Google 风格 Docstring)

python
def compound_interest(principal: int, rate: float, periods: int) -> int:
    """Calculate the compounded interest for a given principal.

    Args:
        principal: Initial investment amount in cents.
        rate: Annual interest rate as a decimal (e.g., 0.05 for 5%).
        periods: Number of compounding periods.

    Returns:
        The total value after compounding, in cents.

    Raises:
        ValueError: If rate is negative or periods is less than 1.

    Example:
        >>> compound_interest(10000, 0.05, 12)
        10511
    """
    ...
python
def compound_interest(principal: int, rate: float, periods: int) -> int:
    """计算给定本金的复利。

    参数:
        principal: 初始投资金额(单位:分)。
        rate: 年利率(小数形式,例如 0.05 代表 5%)。
        periods: 复利计算期数。

    返回:
        复利计算后的总金额(单位:分)。

    异常:
        ValueError: 若利率为负数或期数小于1。

    示例:
        >>> compound_interest(10000, 0.05, 12)
        10511
    """
    ...

Docstring Checklist

Docstring 检查清单

  • First line is a concise imperative summary (e.g., "Calculate..." not "This function calculates...")
  • All parameters documented with types and constraints
  • Return value described, including edge cases (what does it return on empty input?)
  • Exceptions/errors documented
  • At least one usage example included
  • Units specified where applicable (cents, milliseconds, bytes)

  • 第一行是简洁的祈使句摘要(例如:“计算...”而非“此函数用于计算...”)
  • 所有参数均已记录类型及约束条件
  • 返回值已描述,包括边缘情况(空输入时返回什么?)
  • 已记录异常/错误情况
  • 至少包含一个使用示例
  • 适用时已指定单位(分、毫秒、字节)

Changelog Format

变更日志格式

Follow Keep a Changelog conventions.
markdown
undefined
遵循 Keep a Changelog 规范。
markdown
undefined

Changelog

变更日志

All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
本项目所有重要变更均会记录在此文件中。
格式基于 Keep a Changelog, 且本项目遵循 语义化版本控制

[Unreleased]

[未发布]

Added

新增

  • OAuth2 PKCE flow for single-page applications (#452)
  • 为单页应用添加 OAuth2 PKCE 流程 (#452)

Changed

变更

  • Rate limiter now uses sliding window algorithm (#448)
  • 速率限制器现在使用滑动窗口算法 (#448)

Deprecated

弃用

  • Basic auth support — will be removed in v3.0 (#460)
  • 基础认证支持 —— 将在 v3.0 版本中移除 (#460)

Fixed

修复

  • Connection pool exhaustion under sustained load (#455)
  • 持续负载下连接池耗尽的问题 (#455)

[2.1.0] - 2025-03-15

[2.1.0] - 2025-03-15

Added

新增

  • Webhook retry with exponential backoff (#430)
  • Webhook 重试功能,支持指数退避算法 (#430)

Security

安全

  • Upgrade jsonwebtoken to 9.0.1 to fix CVE-2023-XXXXX (#441)
undefined
  • 升级 jsonwebtoken 至 9.0.1 版本,修复 CVE-2023-XXXXX 漏洞 (#441)
undefined

Changelog Categories (in order)

变更日志分类(按顺序)

  1. Added — new features
  2. Changed — changes to existing functionality
  3. Deprecated — features that will be removed
  4. Removed — features that have been removed
  5. Fixed — bug fixes
  6. Security — vulnerability patches
  1. 新增 —— 新功能
  2. 变更 —— 现有功能的变更
  3. 弃用 —— 即将移除的功能
  4. 移除 —— 已移除的功能
  5. 修复 —— bug 修复
  6. 安全 —— 漏洞补丁

Changelog Rules

变更日志规则

  • Write entries from the user's perspective, not the developer's
  • Link every entry to an issue or PR number
  • Use past tense for Fixed ("Fixed crash when...") and present tense for behavioral descriptions ("Rate limiter now uses...")
  • Group the Unreleased section at the top
  • Never delete old entries — the log is append-only

  • 从用户视角撰写条目,而非开发者视角
  • 每个条目均需链接至对应的问题或 PR 编号
  • 修复类条目使用过去式(“修复了...时崩溃的问题”),行为描述类使用现在式(“速率限制器现在使用...”)
  • 将“未发布”部分放在顶部
  • 切勿删除旧条目 —— 日志仅可追加

Architecture Documentation

架构文档

C4 Model Levels

C4 模型层级

Document architecture at four levels of abstraction.
LevelAudienceShows
ContextEveryoneSystem and its external actors
ContainerTechnical leadsApplications, databases, message queues
ComponentDevelopersMajor components within a container
CodeIndividual devsClasses, modules (usually auto-generated)
从四个抽象层级记录架构。
层级受众展示内容
上下文所有人员系统及其外部参与者
容器技术负责人应用、数据库、消息队列
组件开发人员容器内的主要组件
代码个体开发人员类、模块(通常自动生成)

Architecture Decision Records (ADRs)

架构决策记录(ADR)

Use ADRs to capture significant design decisions.
markdown
undefined
使用 ADR 记录重要的设计决策。
markdown
undefined

ADR-007: Use PostgreSQL for primary data store

ADR-007: 使用 PostgreSQL 作为主数据存储

Status

状态

Accepted
已接受

Context

背景

We need a relational database that supports JSONB columns for semi-structured metadata, strong consistency, and row-level security.
我们需要一个支持 JSONB 列的关系型数据库,用于存储半结构化元数据,同时具备强一致性和行级安全特性。

Decision

决策

We will use PostgreSQL 15+ as our primary data store.
我们将使用 PostgreSQL 15+ 作为主数据存储。

Consequences

影响

  • Gain: JSONB support, mature ecosystem, RLS for multi-tenancy
  • Cost: Team must learn PostgreSQL-specific features
  • Risk: Vendor lock-in on PG-specific extensions (mitigated by limiting use of pg_trgm to search module only)
undefined
  • 收益:支持 JSONB、成熟的生态系统、多租户行级安全(RLS)
  • 成本:团队必须学习 PostgreSQL 特定功能
  • 风险:依赖 PG 特定扩展导致厂商锁定(通过限制仅在搜索模块使用 pg_trgm 来缓解)
undefined

Diagram Guidelines

图表指南

  • Use text-based diagram tools (Mermaid, PlantUML, D2) so diagrams live in version control
  • Every diagram must have a title and a date or version
  • Prefer sequence diagrams for workflows, C4 diagrams for architecture
  • Keep diagrams focused — one diagram per concern

  • 使用基于文本的图表工具(Mermaid、PlantUML、D2),以便图表可纳入版本控制
  • 每个图表必须包含标题和日期或版本
  • 工作流优先使用序列图,架构优先使用 C4 图
  • 图表需聚焦单一关注点 —— 每个图表对应一个主题

Runbook Format

运行手册格式

Runbooks are step-by-step guides for operational tasks. They should be executable by someone unfamiliar with the system under stress.
markdown
undefined
运行手册是操作任务的分步指南。即使是不熟悉系统的人员,在压力下也能按手册执行操作。
markdown
undefined

Runbook: Database Failover

运行手册:数据库故障转移

When to Use

适用场景

  • Primary database is unreachable for more than 60 seconds
  • Monitoring alert:
    db-primary-unreachable
    fires
  • 主数据库不可达时间超过60秒
  • 监控告警:
    db-primary-unreachable
    触发

Prerequisites

前置条件

  • Access to AWS Console or
    aws
    CLI with admin credentials
  • VPN connected to production network
  • 拥有 AWS 控制台或
    aws
    CLI 的管理员权限
  • 已连接至生产网络 VPN

Steps

步骤

  1. Verify the primary is truly down:
    bash
    pg_isready -h primary.db.internal -p 5432
  2. Promote the replica:
    bash
    aws rds failover-db-cluster --db-cluster-identifier prod-cluster
  3. Verify the new primary is accepting writes:
    bash
    psql -h primary.db.internal -c "SELECT pg_is_in_recovery();"
    # Expected: f (false)
  4. Update the application config if not using DNS-based routing.
  1. 验证主数据库确实已宕机:
    bash
    pg_isready -h primary.db.internal -p 5432
  2. 提升副本为主数据库:
    bash
    aws rds failover-db-cluster --db-cluster-identifier prod-cluster
  3. 验证新主数据库可接受写入:
    bash
    psql -h primary.db.internal -c "SELECT pg_is_in_recovery();"
    # 预期结果:f(false)
  4. 若未使用基于 DNS 的路由,需更新应用配置。

Rollback

回滚

  • No rollback needed — the old primary becomes the new replica automatically after recovery.
  • 无需回滚 —— 旧主数据库恢复后会自动成为新副本

Escalation

升级处理

  • If failover does not complete in 10 minutes, page the DBA on-call.
undefined
  • 若故障转移在10分钟内未完成,需呼叫值班 DBA。
undefined

Runbook Checklist

运行手册检查清单

  • Title clearly states the operational task
  • "When to Use" section ties to specific alerts or symptoms
  • Prerequisites list all access, tools, and permissions needed
  • Every step includes the exact command to run and expected output
  • Rollback procedure is documented
  • Escalation path is defined with specific contacts or rotations
  • Tested by someone who did not write it

  • 标题明确说明操作任务
  • “适用场景”部分关联特定告警或症状
  • 前置条件列出所有所需的访问权限、工具和许可
  • 每个步骤包含可直接运行的命令及预期输出
  • 已记录回滚流程
  • 已定义升级路径及特定联系人或轮值人员
  • 由非编写者测试通过

Technical Writing Principles

技术写作原则

Audience Awareness

受众意识

Before writing, answer these questions:
  • Who will read this? (New hire? Senior engineer? External user?)
  • What do they already know?
  • What action should they take after reading?
写作前,先回答以下问题:
  • 谁会阅读本文?(新员工?资深工程师?外部用户?)
  • 他们已经了解哪些知识?
  • 阅读后他们应采取什么行动?

Active Voice

主动语态

Passive (avoid)Active (prefer)
The request is validated by...The middleware validates the request
An error will be thrown if...The function throws an error if...
The configuration can be changed...Change the configuration by...
被动语态(避免使用)主动语态(推荐使用)
请求由...验证中间件验证请求
当...时会抛出错误函数在...时会抛出错误
配置可通过...修改通过...修改配置

Concrete Examples Over Abstract Descriptions

具体示例优先于抽象描述

Bad: "The function accepts various configuration options."
Good: "Pass
{ retries: 3, timeout: 5000 }
to retry failed requests up to three times with a five-second timeout."
不良示例:“该函数接受多种配置选项。”
良好示例:“传入
{ retries: 3, timeout: 5000 }
可让失败请求最多重试3次,超时时间为5秒。”

Progressive Disclosure

渐进式披露

Structure documentation in layers:
  1. Quick Start — Get running in under 2 minutes
  2. Guides — Task-oriented walkthroughs for common use cases
  3. Reference — Exhaustive API surface, every option documented
  4. Internals — How it works under the hood, for contributors
按以下层级组织文档:
  1. 快速入门 —— 2分钟内完成项目启动
  2. 指南 —— 面向常见使用场景的任务导向型教程
  3. 参考 —— 详尽的 API 说明,所有选项均已记录
  4. 内部实现 —— 底层工作原理,面向贡献者

Formatting Rules

格式规则

  • Use numbered lists for sequential steps
  • Use bullet lists for unordered sets
  • Use tables for comparing options or listing configuration
  • Use code blocks for anything the reader should type or read verbatim
  • Use admonitions (Note, Warning, Tip) sparingly — if everything is a warning, nothing is
  • Keep paragraphs to 3-4 sentences maximum
  • One idea per paragraph
  • 顺序步骤使用编号列表
  • 无序集合使用项目符号列表
  • 比较选项或列出配置时使用表格
  • 读者需直接输入或查看的内容使用代码块
  • 谨慎使用提示框(Note、Warning、Tip)—— 若所有内容都是警告,就没有真正的警告了
  • 段落最多包含3-4个句子
  • 每个段落仅表达一个观点

Review Checklist for Any Documentation

任何文档的通用检查清单

  • Can a new team member follow this without asking questions?
  • Are all code examples tested and working?
  • Are technical terms defined on first use?
  • Does every heading use sentence case?
  • Are links to external resources still live?
  • Is the document dated or versioned?
  • Has someone other than the author reviewed it?
  • 新团队成员无需提问即可按本文操作?
  • 所有代码示例均已测试且可运行?
  • 技术术语在首次使用时已定义?
  • 所有标题均使用句首大写格式?
  • 外部资源链接均有效?
  • 文档已标注日期或版本?
  • 已由非作者人员审核?