documentation-standards
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocumentation Standards
文档规范
Universal principles for effective documentation. Language-agnostic—focus on what and when to document, not syntax.
有效文档的通用原则。与编程语言无关——重点在于要文档化什么以及何时文档化,而非语法细节。
Core Principle
核心原则
Good code documents itself. Comments explain what code cannot.
Prefer clear names and simple structure over comments. Write comments for reasoning, not restating.
好的代码自文档化。注释用于解释代码无法表达的信息。
优先使用清晰的命名和简洁的结构,而非注释。注释应用于解释设计思路,而非重复代码内容。
Comments vs Code
注释 vs 代码
When to Comment
何时需要注释
ALWAYS comment:
-
Why (reasoning, trade-offs, decisions)
- "Use exponential backoff to avoid overwhelming API during outages"
- "Chose algorithm X over Y because of O(n) vs O(n²) performance"
-
Non-obvious decisions
- "Cache invalidation: 5 minutes chosen to balance freshness vs load"
- "Intentionally skipping validation here—already validated upstream"
-
Workarounds
- "Temporary fix for bug in library X version 1.2.3"
- "Work around browser quirk in Safari < 15"
-
Gotchas and constraints
- "Must call init() before use or will throw"
- "Not thread-safe—caller must synchronize"
- "Order matters: must authenticate before making requests"
SOMETIMES comment:
-
Complex algorithms (high-level what, not line-by-line)
- "Binary search to find insertion point in sorted array"
- "Dijkstra's algorithm for shortest path"
-
Business rules
- "Tax calculation per regulation ABC-123 effective Jan 2024"
- "Discount tiers: 10% for >100 items, 20% for >500"
RARELY comment:
- What (code should be self-documenting)
- If you need to explain what, improve naming/structure first
NEVER comment:
- Obvious code
- Bad:
i++ // Increment i
- Bad:
- Commented-out code (delete it—it's in git)
- Lies (outdated comments worse than no comments)
务必添加注释的场景:
-
原因(设计思路、权衡方案、决策依据)
- "使用指数退避算法,避免在服务中断时压垮API"
- "选择算法X而非Y,因为前者时间复杂度为O(n),后者为O(n²)"
-
非直观的决策
- "缓存失效时间设为5分钟,以在数据新鲜度和服务负载间取得平衡"
- "此处刻意跳过验证——上游已完成验证"
-
临时变通方案
- "针对库X 1.2.3版本的Bug的临时修复"
- "兼容Safari < 15版本的浏览器特性问题"
-
注意事项与约束条件
- "必须先调用init()再使用,否则会抛出异常"
- "非线程安全——调用方需自行处理同步"
- "调用顺序重要:必须先完成认证再发起请求"
有时需要添加注释的场景:
-
复杂算法(仅需说明整体功能,无需逐行解释)
- "使用二分查找在有序数组中找到插入位置"
- "使用Dijkstra算法计算最短路径"
-
业务规则
- "根据法规ABC-123计算税费,2024年1月生效"
- "折扣规则:购买100件以上享10%折扣,500件以上享20%折扣"
几乎不需要添加注释的场景:
- 代码内容(代码应具备自解释性)
- 如果需要注释来解释代码做了什么,优先重构代码的命名和结构
绝对不能添加注释的场景:
- 显而易见的代码
- 错误示例:
i++ // 递增i
- 错误示例:
- 被注释掉的代码(直接删除——Git中已保留历史版本)
- 过时的注释(错误的注释比没有注释更糟)
"Why Not What" Principle
"解释原因而非内容"原则
✅ Good comments (explain reasoning):
// Use exponential backoff to prevent thundering herd
retryDelay = baseDelay * Math.pow(2, attempt)
// Cache for performance—database query is expensive
const cachedResult = cache.get(key)❌ Bad comments (restate code):
// Set retry delay to base delay times 2 to the power of attempt
retryDelay = baseDelay * Math.pow(2, attempt)
// Get cached result from cache
const cachedResult = cache.get(key)✅ 优质注释(解释设计思路):
// 使用指数退避算法防止雪崩效应
retryDelay = baseDelay * Math.pow(2, attempt)
// 缓存以提升性能——数据库查询开销较大
const cachedResult = cache.get(key)❌ 劣质注释(重复代码内容):
// 将重试延迟设置为基础延迟乘以2的尝试次数次方
retryDelay = baseDelay * Math.pow(2, attempt)
// 从缓存中获取缓存结果
const cachedResult = cache.get(key)Exceptions to "Why Not What"
"解释原因而非内容"原则的例外情况
Complex algorithms benefit from high-level "what":
// Find longest common subsequence using dynamic programming
// Returns length and the subsequence itself
function longestCommonSubsequence(s1, s2)Public API contracts (inputs, outputs, errors):
// Authenticates user with email and password
// Returns: User object on success
// Throws: AuthError if credentials invalid
// Throws: NetworkError if connection fails
function authenticate(email, password)复杂算法可添加整体功能说明:
// 使用动态规划寻找最长公共子序列
// 返回:子序列长度及子序列本身
function longestCommonSubsequence(s1, s2)公共API契约(输入、输出、异常):
// 使用邮箱和密码对用户进行认证
// 返回:认证成功时返回User对象
// 抛出:凭证无效时抛出AuthError
// 抛出:连接失败时抛出NetworkError
function authenticate(email, password)Comment Density: Minimal
注释密度:尽量精简
Prefer over comments:
- Better names
- Simpler code structure
- Extracted functions (self-documenting)
- Smaller modules
Rule: If you need a comment to explain what code does, refactor first.
Comments should add information code cannot express.
优先选择以下方式替代注释:
- 更清晰的命名
- 更简洁的代码结构
- 提取独立函数(具备自解释性)
- 拆分更小的模块
规则: 如果需要注释来解释代码功能,先重构代码。
注释应补充代码无法表达的信息。
README and Technical Docs
README与技术文档
README.md Structure
README.md结构
Every project needs a README.
Minimal required sections:
-
What (one sentence)
- Clear, concise description
- "Task management CLI tool for developers"
-
Why (problem it solves)
- "Existing task managers don't integrate with git/editors"
-
Quick Start (fastest path to running)
- Installation
- Basic usage example
- This comes FIRST after description
-
Setup (getting started)
- Prerequisites
- Installation steps
- Configuration
Optional sections (add as needed):
- Examples (common use cases)
- Features (capabilities)
- Documentation (link to detailed docs)
- Contributing (how to help)
- License
- Troubleshooting (common issues)
每个项目都需要README文档。
必填的最小化章节:
-
是什么(一句话描述)
- 清晰、简洁的说明
- 示例:"面向开发者的任务管理CLI工具"
-
为什么(解决的问题)
- 示例:"现有任务管理器无法与Git/编辑器集成"
-
快速入门(最快上手路径)
- 安装步骤
- 基础使用示例
- 此章节应紧跟项目描述之后,放在最前面
-
设置步骤(完整入门指南)
- 前置依赖
- 安装步骤
- 配置说明
可选章节(按需添加):
- 示例(常见使用场景)
- 功能特性(核心能力)
- 文档链接(指向详细文档)
- 贡献指南(如何参与项目)
- 许可证
- 故障排查(常见问题)
README Anti-Patterns
README反模式
❌ Novel-length README
- Save detailed docs for separate files
- README should get you started, not cover everything
❌ Out-of-date examples
- Worse than no examples
- Update with breaking changes or delete
❌ No quick start
- Forcing users to read entire doc before trying it
- Put fastest path to success up front
❌ Installation that doesn't work
- Test your own installation instructions
- What works on your machine ≠ what works elsewhere
❌ 过长的README
- 详细文档应放在单独的文件中
- README只需帮助用户快速上手,无需覆盖所有细节
❌ 过时的示例
- 比没有示例更糟
- 发生破坏性变更时更新示例,或直接删除
❌ 没有快速入门
- 强迫用户通读全文才能尝试使用
- 将最快成功路径放在最前面
❌ 无法正常运行的安装步骤
- 自行测试安装说明
- 你本地能运行不代表其他环境也能运行
Other Documentation Types
其他文档类型
ADRs (Architecture Decision Records):
- What: Record of architectural decisions
- When: Making significant architectural choices
- Format: Context, Decision, Consequences
- Example: "Why we chose database X over Y"
ARCHITECTURE.md:
- What: High-level system design
- When: System complex enough to need overview
- Content: Components, relationships, data flow
- Keep: Updated with major changes
CONTRIBUTING.md:
- What: How to contribute to project
- When: Accepting external contributors (open source, team projects)
- Content: Setup, workflow, standards, review process
CHANGELOG.md:
- What: What changed between versions
- When: Project has releases/versions
- Format: Chronological, grouped by version
- Include: Added, Changed, Fixed, Removed
API Documentation:
- What: Public API reference
- When: Building libraries for others
- Best: Generated from code comments (stays in sync)
- Avoid: Manually maintained separate docs (get stale)
ADRs(架构决策记录):
- 定义: 记录架构决策的文档
- 适用场景: 做出重大架构选择时
- 格式: 背景、决策、影响
- 示例: "为什么选择数据库X而非Y"
ARCHITECTURE.md:
- 定义: 系统高层设计文档
- 适用场景: 系统复杂度较高,需要整体概览时
- 内容: 组件、关系、数据流
- 维护: 随重大变更更新
CONTRIBUTING.md:
- 定义: 项目贡献指南
- 适用场景: 接受外部贡献时(开源项目、团队协作项目)
- 内容: 环境搭建、工作流程、规范、评审流程
CHANGELOG.md:
- 定义: 版本间变更记录
- 适用场景: 项目有版本发布时
- 格式: 按时间倒序,按版本分组
- 内容: 新增功能、变更内容、修复问题、移除功能
API文档:
- 定义: 公共API参考文档
- 适用场景: 为其他开发者提供的类库
- 最佳实践: 从代码注释自动生成(保持与代码同步)
- 避免: 手动维护独立的API文档(容易过时)
When to Create Each Document
各类文档的创建时机
- README: ALWAYS (every project)
- ADRs: Significant architectural decisions
- ARCHITECTURE.md: Complex system needing diagram
- CONTRIBUTING.md: Accepting external contributions
- CHANGELOG: Versioned releases
- API docs: Libraries meant for other developers
- README: 必须创建(所有项目)
- ADRs: 做出重大架构决策时
- ARCHITECTURE.md: 系统复杂到需要可视化概览时
- CONTRIBUTING.md: 接受外部贡献时
- CHANGELOG: 版本化发布时
- API文档: 开发供其他开发者使用的类库时
Documentation Maintenance
文档维护
When to Update Docs
何时更新文档
ALWAYS update:
- Breaking changes (users depend on documented behavior)
- New features (users need to discover them)
- Deprecated features (warn before removal)
USUALLY update:
- Bug fixes that change behavior
- New configuration options
- Performance improvements (if significant)
RARELY update:
- Internal refactors (implementation changes)
- Bug fixes that don't change behavior
- Code cleanup
必须更新的场景:
- 破坏性变更(用户依赖文档记录的行为)
- 新增功能(用户需要了解新特性)
- 废弃功能(在移除前发出警告)
通常需要更新的场景:
- 改变功能行为的Bug修复
- 新增配置选项
- 重大性能优化
几乎不需要更新的场景:
- 内部重构(仅实现细节变更)
- 不改变功能行为的Bug修复
- 代码清理
Stale Docs Are Worse Than No Docs
过时的文档比没有文档更糟
Users trust documentation.
Wrong documentation is worse than no documentation—it wastes time and builds mistrust.
If you can't maintain docs:
- Delete them (better than lying)
- Or clearly mark as outdated
- Or link to code as source of truth
用户会信任文档内容。
错误的文档比没有文档更糟——它会浪费用户时间,并且破坏信任。
如果无法维护文档:
- 删除文档(比错误的文档好)
- 或明确标记为过时
- 或指向代码作为事实来源
Documentation Debt
文档债务
When to defer documentation:
- Experimental features (still exploring)
- Internal tools (team already knows)
- Prototypes (may be discarded)
When documentation debt becomes unacceptable:
- Feature shipping to users
- Onboarding new team members
- Open sourcing project
可暂时推迟文档编写的场景:
- 实验性特性(仍在探索阶段)
- 内部工具(团队成员已熟悉)
- 原型(可能会被丢弃)
文档债务不可接受的场景:
- 特性面向用户发布时
- 新团队成员入职时
- 项目开源时
Automated Documentation Quality
自动化文档质量检查
Link Checking (lychee - Rust binary):
bash
lychee **/*.md --offline --cache- Single binary, no Node.js
- ~40x faster than markdown-link-check
- Works offline completely
- Install:
brew install lychee
Style Linting (Vale - Go binary):
bash
vale docs/- Enforces style guides (Google, Microsoft, write-good)
- Single binary, 100% offline
- YAML configuration ()
.vale.ini - Install:
brew install vale
Freshness Detection (git-based):
bash
undefined链接检查(lychee - Rust二进制工具):
bash
lychee **/*.md --offline --cache- 单二进制文件,无需Node.js
- 速度比markdown-link-check快约40倍
- 完全支持离线运行
- 安装方式:
brew install lychee
风格检查(Vale - Go二进制工具):
bash
vale docs/- 可强制执行风格指南(Google、Microsoft、write-good等)
- 单二进制文件,100%离线运行
- 通过YAML配置文件()进行定制
.vale.ini - 安装方式:
brew install vale
新鲜度检测(基于Git):
bash
undefinedFind docs not updated in 90 days
查找90天未更新的文档
find docs -name '*.md' | while read f; do
age=$(( ($(date +%s) - $(git log -1 --format=%ct -- "$f")) / 86400 ))
[ $age -gt 90 ] && echo "$f: $age days stale"
done
**CI Integration**: All run in GitHub Actions without external services
---find docs -name '*.md' | while read f; do
age=$(( ($(date +%s) - $(git log -1 --format=%ct -- "$f")) / 86400 ))
[ $age -gt 90 ] && echo "$f: $age days stale"
done
**CI集成**:所有检查均可在GitHub Actions中运行,无需外部服务
---Diagrams
图表
When to Use Diagrams
何时使用图表
✅ Use diagrams when they clarify:
- System architecture (components, relationships)
- Data flow (how data moves through system)
- State machines (states and transitions)
- Complex interactions (sequence diagrams)
❌ Don't use diagrams:
- As decoration (diagrams should clarify, not prettify)
- For simple systems (often code is clearer)
- Without maintaining them (stale diagrams mislead)
✅ 以下场景使用图表可提升清晰度:
- 系统架构(组件、关系)
- 数据流(数据在系统中的流转路径)
- 状态机(状态及转换逻辑)
- 复杂交互(序列图)
❌ 以下场景不应使用图表:
- 仅作为装饰(图表应用于提升清晰度,而非美化)
- 简单系统(代码本身通常更清晰)
- 无法维护的图表(过时的图表会误导用户)
Diagram Principles
图表设计原则
Keep simple:
- Complex diagrams become stale
- Focus on high-level relationships
- Details belong in code
Text-based preferred:
- Version control friendly
- Easy to update
- Tools: Any text-based diagram format your team prefers
Maintain or delete:
- Update diagrams with system changes
- Or delete outdated diagrams (don't let them lie)
保持简洁:
- 复杂图表容易过时
- 重点展示高层关系
- 细节应体现在代码中
优先使用文本格式:
- 友好支持版本控制
- 易于更新
- 工具:团队偏好的任意文本格式图表工具
要么维护,要么删除:
- 随系统变更更新图表
- 或删除过时的图表(不要保留错误的图表)
Quick Reference
快速参考
Documentation Checklist
文档检查清单
Before writing comment:
- Can I make code clearer instead?
- Am I explaining "why" or just "what"?
- Would future me find this helpful?
- Is this non-obvious or a gotcha?
Before shipping feature:
- README updated (if user-facing)?
- Breaking changes documented?
- Examples still work?
- Quick start still accurate?
Starting new project:
- README with What, Why, Quick Start, Setup
- License (if sharing)
- .gitignore (keep docs, ignore build artifacts)
When making architectural decision:
- Should this be an ADR?
- Will team need context in 6 months?
- Is this a significant departure from current approach?
编写注释前:
- 我能否通过优化代码使其更清晰?
- 我是在解释原因还是重复内容?
- 未来的我会觉得这个注释有帮助吗?
- 这是非直观的内容或注意事项吗?
发布特性前:
- README已更新(如果是面向用户的特性)?
- 破坏性变更已记录?
- 示例仍可正常运行?
- 快速入门指南仍准确?
启动新项目时:
- README包含“是什么、为什么、快速入门、设置步骤”?
- 已添加许可证(如果对外共享)?
- 已添加.gitignore(保留文档,忽略构建产物)?
做出架构决策时:
- 是否需要将其记录为ADR?
- 团队在6个月后还需要这个背景信息吗?
- 这是否与当前方案有重大差异?
Philosophy
设计理念
"Code tells you how. Comments tell you why."
The best documentation is code that doesn't need documentation. But when code can't express intent, comments bridge the gap.
Documentation is for humans:
- Future you (6 months from now)
- Team members (new and experienced)
- Users (trying to use your code)
Documentation is not:
- A substitute for clear code
- A place to explain bad design
- Something to write and forget
Remember: Undocumented code is hard to use. Documented wrong code is harder.
“代码告诉你怎么做。注释告诉你为什么这么做。”
最好的文档是无需额外文档的代码。但当代码无法表达意图时,注释可以填补这一空白。
文档是为人类编写的:
- 未来的你(6个月后的自己)
- 团队成员(新成员和老成员)
- 用户(尝试使用你的代码的人)
文档不是:
- 清晰代码的替代品
- 糟糕设计的遮羞布
- 写完就可以遗忘的内容
请记住: 未文档化的代码难以使用。文档化错误的代码更难使用。
Exit Codes and Error Codes
退出码与错误码
Documentation drift is silent. When documenting exit codes, error codes, or error-to-behavior mappings:
- Trace actual code paths. Don't document intent—document what the code actually does.
- Check all callers. An error code might be defined but never used, or used differently than named.
- Grep for the constant. reveals actual usage.
grep -rn "ExitCodeFoo" internal/
Verification rule: After writing error/exit code docs, verify each code against its actual trigger in the codebase.
文档漂移是隐性的。 当文档化退出码、错误码或错误与行为的映射关系时:
- 跟踪实际代码路径。 不要记录预期行为——记录代码实际的行为。
- 检查所有调用方。 某个错误码可能被定义但从未使用,或使用方式与命名不符。
- 全局搜索常量。 可以揭示实际使用情况。
grep -rn "ExitCodeFoo" internal/
验证规则: 编写错误/退出码文档后,逐一验证每个代码在代码库中的实际触发场景。