code-quality
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode Quality Standards
代码质量标准
Non-negotiable code quality standards. These are not preferences — they are requirements.
不可妥协的代码质量标准。这些并非偏好选择——而是硬性要求。
Testing Standards
测试标准
The Testing Pyramid
测试金字塔
| Layer | What it Tests | Speed | Purpose |
|---|---|---|---|
| Unit Tests | Individual functions/components | Fast | TDD lives here. Catches logic errors early. |
| Integration Tests | Components working together | Medium | Catches connection and data flow issues. |
| E2E Tests | Full user flows | Slowest | Confirms the system does the thing. |
| Human Review | Visual correctness, UX | Manual | Irreducible quality judgment. |
| 层级 | 测试对象 | 执行速度 | 核心目的 |
|---|---|---|---|
| 单元测试 | 独立函数/组件 | 极快 | TDD的核心应用场景,尽早捕获逻辑错误。 |
| 集成测试 | 协同工作的组件 | 中等 | 捕获组件间的连接与数据流问题。 |
| 端到端(E2E)测试 | 完整用户流程 | 最慢 | 确认系统可完成预期业务功能。 |
| 人工评审 | 视觉正确性、用户体验(UX) | 手动 | 无法替代的主观质量判断环节。 |
Test-Driven Development (TDD)
测试驱动开发(TDD)
TDD is mandatory at the unit test level:
- Tests are written BEFORE implementation — Never implement without a failing test first
- Red -> Green -> Refactor is mandatory — No exceptions
- Tests define behavior — Implementation serves tests
- Small incremental steps — Tiny, safe changes over large speculative edits
- Tests are the source of truth — If it's not tested, it doesn't work
When in doubt: Slow down, write the test, make the smallest possible change.
单元测试级别必须遵循TDD:
- 先写测试,再实现代码 —— 绝不要在没有失败测试的情况下开始开发
- 严格遵循红→绿→重构流程 —— 无例外
- 测试定义行为 —— 代码实现为测试服务
- 小步增量迭代 —— 优先小幅、安全的变更,而非大规模 speculative 编辑
- 测试是事实依据 —— 未经过测试的功能视为不可用
存疑时: 放慢速度,先写测试,再做最小必要变更。
What Makes a Good Test
优质测试的标准
Structure every test as Arrange-Act-Assert:
python
def test_apply_discount_reduces_total():
# Arrange — set up the scenario
cart = Cart(items=[Item(price=100)])
discount = Discount(percent=20)
# Act — perform the action under test
cart.apply_discount(discount)
# Assert — verify the outcome
assert cart.total == 80One concept per test. If a test name has "and" in it, split it into two tests.
Name tests to describe behavior, not implementation:
| Bad | Good |
|---|---|
| |
| |
| |
Tests must be:
- Isolated — No test depends on another test's state or execution order
- Deterministic — Same input, same result. No randomness, no clock dependency, no network calls.
- Fast — Unit tests run in milliseconds. If they're slow, they're not unit tests.
- Readable — A failing test name should tell you what broke without reading the test body
所有测试需遵循Arrange-Act-Assert结构:
python
def test_apply_discount_reduces_total():
# Arrange — set up the scenario
cart = Cart(items=[Item(price=100)])
discount = Discount(percent=20)
# Act — perform the action under test
cart.apply_discount(discount)
# Assert — verify the outcome
assert cart.total == 80每个测试仅验证一个概念。如果测试名称中包含"and",则拆分为两个独立测试。
测试名称需描述行为,而非实现细节:
| 不良示例 | 优质示例 |
|---|---|
| |
| |
| |
测试必须满足:
- 隔离性 —— 测试之间不依赖彼此的状态或执行顺序
- 确定性 —— 相同输入必产生相同结果。无随机逻辑、无时钟依赖、无网络调用。
- 高速性 —— 单元测试需在毫秒级完成。如果执行缓慢,则不属于单元测试范畴。
- 可读性 —— 失败测试的名称应直接告知问题所在,无需阅读测试代码
Unit Tests
单元测试
- Foundation of testing
- Run in milliseconds
- Test one function/component in isolation
- Mock external dependencies, not internal logic
- 测试体系的基础
- 毫秒级执行
- 孤立测试单个函数/组件
- 模拟外部依赖,而非内部逻辑
Integration Tests
集成测试
- Verify modules work together
- Use test databases or containers, not mocks
- Reset state between tests
- 验证模块间的协同工作能力
- 使用测试数据库或容器,而非模拟对象
- 测试间重置状态
E2E Tests
E2E测试
- Critical user paths only
- Keep the suite small and focused
- Accept some flakiness, build in retries
- 仅覆盖关键用户路径
- 保持测试套件精简且聚焦
- 允许一定程度的不稳定,内置重试机制
Human Review
人工评审
- Does it work correctly?
- Does it look right?
- Does it feel good?
- Is it accessible?
- 功能是否正常?
- 视觉呈现是否正确?
- 使用体验是否流畅?
- 是否具备可访问性?
Code Structure
代码结构
Early Returns Over Nesting
提前返回替代嵌套
Guard clauses first. Flatten control flow.
Bad — nested, hard to follow:
python
def process(order):
if order:
if order.items:
if order.is_valid:
return calculate_total(order)
return NoneGood — flat, clear:
python
def process(order):
if not order:
return None
if not order.items:
return None
if not order.is_valid:
return None
return calculate_total(order)Max nesting depth: 3 levels. If deeper, extract to a function.
先使用守卫语句,扁平化控制流。
不良示例——嵌套过深,难以阅读:
python
def process(order):
if order:
if order.items:
if order.is_valid:
return calculate_total(order)
return None优质示例——扁平化,逻辑清晰:
python
def process(order):
if not order:
return None
if not order.items:
return None
if not order.is_valid:
return None
return calculate_total(order)最大嵌套深度:3层。如果超过,需提取为独立函数。
Function Size
函数规模
A function should do one thing. If you need a comment to separate "sections" inside a function, those sections should be separate functions.
Guidelines:
- If a function exceeds ~30 lines, look for extraction opportunities
- If a function takes more than 3-4 parameters, it's probably doing too much
- If you can't name the function clearly, it has too many responsibilities
一个函数应只做一件事。如果需要用注释分隔函数内的"段落",则这些段落应拆分为独立函数。
指导原则:
- 如果函数超过约30行,需考虑拆分
- 如果函数参数超过3-4个,可能承担了过多职责
- 如果无法清晰命名函数,说明其职责过于繁杂
Single Responsibility
单一职责原则
Every function, class, and module should have one reason to change.
Smell: "This function handles validation AND formatting AND saving."
Fix: Three functions — , , .
validateformatsave每个函数、类和模块都应只有一个变更理由。
坏味道: "这个函数同时处理验证、格式化和存储。"
修复方案: 拆分为三个函数——、、。
validateformatsaveExplicit Over Clever
显式优于巧妙
Readability beats brevity. Separate operations into clear steps.
Bad — clever but hard to debug:
python
names = [u.name for u in users if u.is_active and u.role in allowed]Good — clear intent, debuggable:
python
active_users = filter_active(users)
authorized_users = filter_by_role(active_users, allowed)
names = extract_names(authorized_users)When a one-liner requires mental parsing, break it apart. Optimize for the reader, not the writer.
可读性优先于简洁性。将操作拆分为清晰的步骤。
不良示例——看似巧妙但难以调试:
python
names = [u.name for u in users if u.is_active and u.role in allowed]优质示例——意图清晰,易于调试:
python
active_users = filter_active(users)
authorized_users = filter_by_role(active_users, allowed)
names = extract_names(authorized_users)当单行代码需要脑力解析时,应将其拆分。为读者优化,而非为编写者优化。
Error Handling
错误处理
Fail Fast
快速失败
Validate inputs at the boundary. Don't let bad data travel deep into the system.
python
def create_user(email, name):
if not email:
raise ValidationError("Email is required")
if not is_valid_email(email):
raise ValidationError("Invalid email format")
return save_user(email, name)在系统边界处验证输入。不要让无效数据深入系统内部。
python
def create_user(email, name):
if not email:
raise ValidationError("Email is required")
if not is_valid_email(email):
raise ValidationError("Invalid email format")
return save_user(email, name)Specific Errors Over Generic
特定错误优于通用错误
Catch what you expect. Re-raise what you don't.
Bad — swallows everything:
python
try:
do_risky_thing()
except Exception:
passGood — handles what it understands:
python
try:
do_risky_thing()
except NetworkError:
return retry()
except ValidationError as e:
return error_response(e.message)捕获预期的错误,重新抛出未预期的错误。
不良示例——吞噬所有错误:
python
try:
do_risky_thing()
except Exception:
pass优质示例——仅处理已知错误:
python
try:
do_risky_thing()
except NetworkError:
return retry()
except ValidationError as e:
return error_response(e.message)Unexpected errors propagate up
未预期的错误向上传播
undefinedundefinedNever Swallow Errors
绝不要吞噬错误
If you catch an error, you must either:
- Handle it — take a meaningful recovery action
- Log and re-raise it — make the failure visible
- Transform it — wrap in a more specific error for the caller
Empty / blocks are bugs.
catchexcept如果捕获错误,必须执行以下操作之一:
- 处理错误 —— 采取有意义的恢复动作
- 记录并重新抛出 —— 让失败可见
- 转换错误 —— 包装为调用者更易理解的特定错误
空的/块属于bug。
catchexceptNaming Conventions
命名规范
Names must clearly communicate:
- Who is acting — The subject performing the action
- What action is occurring — The verb describing the behavior
- Direction of data or ownership flow — Where things are going to/from
命名必须清晰传达:
- 执行者 —— 执行动作的主体
- 动作 —— 描述行为的动词
- 数据流向或所有权 —— 数据的传递方向或归属
Directional Clarity
流向清晰性
Use prepositions (, , , ) or named parameters.
tofromintoontoBad — Ambiguous:
python
shop.buy_item(item_id, buyer) # Who is buying?
transfer(amount, account) # Transfer to or from?Good — Clear:
python
shop.sell_item_to(item_id, buyer) # Shop sells TO buyer
shop.sell(item_id, to=buyer) # Named parameter clarifies
transfer_from(account, amount) # Direction explicit
account.transfer_to(other, amount) # Direction in method name使用介词(、、、)或命名参数。
tofromintoonto不良示例——歧义:
python
shop.buy_item(item_id, buyer) # 谁在购买?
transfer(amount, account) # 转入还是转出?优质示例——清晰:
python
shop.sell_item_to(item_id, buyer) # 商店售卖给买家
shop.sell(item_id, to=buyer) # 命名参数明确流向
transfer_from(account, amount) # 流向明确
account.transfer_to(other, amount) # 方法名包含流向The Read-Aloud Test
朗读测试
If a method call doesn't read naturally when spoken aloud, the name is wrong.
python
undefined如果方法调用朗读起来不自然,说明命名有误。
python
undefined"shop buy item buyer" — confusing
"shop buy item buyer" —— 混乱
shop.buy_item(item_id, buyer)
shop.buy_item(item_id, buyer)
"shop sell item to buyer" — clear
"shop sell item to buyer" —— 清晰
shop.sell_item_to(item_id, buyer)
undefinedshop.sell_item_to(item_id, buyer)
undefinedBoolean Naming
布尔值命名
Always prefix booleans with , , , , , or :
ishasshouldcanwilldidpython
undefined布尔值必须以、、、、或开头:
ishasshouldcanwilldidpython
undefinedBad — ambiguous (is it a noun? a verb? a state?)
不良示例——歧义(是名词?动词?状态?)
active = True
permission = True
refresh = True
active = True
permission = True
refresh = True
Good — clearly a yes/no question
优质示例——明确是是非判断
is_active = True
has_permission = True
should_refresh = True
undefinedis_active = True
has_permission = True
should_refresh = True
undefinedNaming Patterns
命名模式
| Pattern | Use When | Example |
|---|---|---|
| Action flows to target | |
| Action flows from source | |
| Object performs action toward target | |
| Named parameter clarifies | |
| 模式 | 使用场景 | 示例 |
|---|---|---|
| 动作流向目标 | |
| 动作来自源 | |
| 对象执行朝向目标的动作 | |
| 命名参数明确流向 | |
Avoid
避坑指南
| Don't | Instead |
|---|---|
Single letters (except loop | Full descriptive name |
Abbreviations ( | |
Generic names ( | |
Negated booleans ( | |
| 不要做 | 替代方案 |
|---|---|
使用单个字母(循环变量 | 使用完整描述性名称 |
使用缩写( | |
使用通用名称( | |
使用否定式布尔值( | |
Constants & Clarity
常量与清晰性
No Magic Values
禁止魔法值
Every number and string literal should have a name.
Bad:
python
if retry_count > 3:
sleep(60)Good:
python
MAX_RETRIES = 3
RETRY_DELAY_SECONDS = 60
if retry_count > MAX_RETRIES:
sleep(RETRY_DELAY_SECONDS)所有数字和字符串字面量都应定义为命名常量。
不良示例:
python
if retry_count > 3:
sleep(60)优质示例:
python
MAX_RETRIES = 3
RETRY_DELAY_SECONDS = 60
if retry_count > MAX_RETRIES:
sleep(RETRY_DELAY_SECONDS)Boolean Parameters
布尔参数
Boolean arguments hide meaning at the call site.
Bad — what does mean?
Truepython
create_user(data, True, False)Good — named parameters or options:
python
create_user(data, send_welcome=True, require_verification=False)If the language doesn't support named parameters, use an options object/struct.
布尔参数会隐藏调用处的含义。
不良示例——的含义是什么?
Truepython
create_user(data, True, False)优质示例——使用命名参数或选项对象:
python
create_user(data, send_welcome=True, require_verification=False)如果语言不支持命名参数,使用选项对象/结构体。
Documentation
文档
Docstrings
文档字符串(Docstrings)
Docstrings are living documentation. Public APIs must be self-explanatory without reading implementation.
文档字符串是活文档。公共API必须无需阅读实现代码即可理解其用法。
Required Elements
必填元素
Every public function, method, and class must include:
- Purpose — What it does (one line)
- Parameters — Each parameter with type and meaning
- Returns — What is returned and when
- Side effects — Any state changes, I/O, or mutations
- Errors — What exceptions/errors can occur
- Examples — Realistic usage showing common cases
每个公共函数、方法和类必须包含:
- 用途 —— 功能概述(一行)
- 参数 —— 每个参数的类型与含义
- 返回值 —— 返回内容及场景
- 副作用 —— 任何状态变更、I/O操作或数据修改
- 错误 —— 可能抛出的异常/错误类型
- 示例 —— 展示常见用法的真实场景
Example Docstring
文档字符串示例
python
def sell_item_to(self, item_id: str, buyer: Customer) -> Receipt:
"""Sell an item from shop inventory to a customer.
Transfers ownership of the item from the shop to the buyer,
processes payment, and updates inventory.
Args:
item_id: Unique identifier of the item to sell.
buyer: Customer purchasing the item. Must have sufficient balance.
Returns:
Receipt containing transaction details and timestamp.
Raises:
ItemNotFoundError: If item_id doesn't exist in inventory.
InsufficientBalanceError: If buyer can't afford the item.
ItemAlreadySoldError: If item was sold between check and purchase.
Examples:
Basic sale:
>>> shop = Shop(inventory=[item])
>>> buyer = Customer(balance=100)
>>> receipt = shop.sell_item_to(item.id, buyer)
>>> assert receipt.amount == item.price
>>> assert item.id not in shop.inventory
Handling insufficient balance:
>>> poor_buyer = Customer(balance=0)
>>> shop.sell_item_to(item.id, poor_buyer)
Raises InsufficientBalanceError
"""python
def sell_item_to(self, item_id: str, buyer: Customer) -> Receipt:
"""Sell an item from shop inventory to a customer.
Transfers ownership of the item from the shop to the buyer,
processes payment, and updates inventory.
Args:
item_id: Unique identifier of the item to sell.
buyer: Customer purchasing the item. Must have sufficient balance.
Returns:
Receipt containing transaction details and timestamp.
Raises:
ItemNotFoundError: If item_id doesn't exist in inventory.
InsufficientBalanceError: If buyer can't afford the item.
ItemAlreadySoldError: If item was sold between check and purchase.
Examples:
Basic sale:
>>> shop = Shop(inventory=[item])
>>> buyer = Customer(balance=100)
>>> receipt = shop.sell_item_to(item.id, buyer)
>>> assert receipt.amount == item.price
>>> assert item.id not in shop.inventory
Handling insufficient balance:
>>> poor_buyer = Customer(balance=0)
>>> shop.sell_item_to(item.id, poor_buyer)
Raises InsufficientBalanceError
"""Docstring Rules
文档字符串规则
- Examples should mirror actual test scenarios
- Update docstrings when behavior changes
- Treat docstrings as first-class code, not decoration
- 示例应与实际测试场景一致
- 当行为变更时更新文档字符串
- 将文档字符串视为一等公民代码,而非装饰
Comments
注释
| Do Comment | Don't Comment |
|---|---|
| Why — intent, business reason, non-obvious context | What — the code already says this |
| Non-obvious gotchas or edge cases | Obvious operations |
| Complex algorithm summaries | Bad code to explain it (fix the code instead) |
| TODO with ticket/issue reference | TODO without context |
If you need a comment to explain what code does, the code should be clearer. Rename variables, extract functions, simplify logic — then the comment becomes unnecessary.
| 应注释内容 | 不应注释内容 |
|---|---|
| 原因 —— 意图、业务背景、非显而易见的上下文 | 内容 —— 代码本身已说明 |
| 非显而易见的陷阱或边缘情况 | 明显的操作 |
| 复杂算法的摘要 | 用注释解释坏代码(应直接修复代码) |
| 包含工单/问题引用的TODO | 无上下文的TODO |
如果需要注释解释代码的功能,说明代码应更清晰。重命名变量、提取函数、简化逻辑——之后注释就不再必要了。
Quick Reference
快速检查清单
- Tests written BEFORE implementation
- Red -> Green -> Refactor followed
- Each test has one concept, Arrange-Act-Assert structure
- Tests are isolated, deterministic, fast
- All tests pass, edge cases covered
- Functions are short, single-responsibility
- Max 3 levels of nesting, early returns used
- Errors fail fast at boundaries with specific types
- No empty catch/except blocks
- Names pass the read-aloud test
- Directional clarity in method names (to/from)
- Booleans prefixed with is/has/should/can
- No abbreviations, no generic names
- No magic numbers or strings — constants extracted
- Boolean parameters use named args or options
- All public APIs have complete docstrings
- Comments explain why, not what
- 先写测试,再实现代码
- 遵循红→绿→重构流程
- 每个测试仅验证一个概念,采用Arrange-Act-Assert结构
- 测试具备隔离性、确定性、高速性
- 所有测试通过,覆盖边缘场景
- 函数简短,符合单一职责
- 最大嵌套深度3层,使用提前返回
- 错误在边界处快速失败,使用特定错误类型
- 无空的catch/except块
- 命名通过朗读测试
- 方法名具备流向清晰性(to/from)
- 布尔值以is/has/should/can开头
- 无缩写、无通用名称
- 无魔法数字或字符串——已提取为常量
- 布尔参数使用命名参数或选项对象
- 所有公共API具备完整文档字符串
- 注释解释原因,而非内容
References
参考资料
- — Testing pyramid deep-dive, mocking guidelines, anti-patterns
references/testing-reference.md - — Complete naming conventions, abbreviation rules, domain naming
references/naming-reference.md - — Error hierarchies, retry/fallback patterns, error boundaries
references/error-handling-reference.md
- —— 测试金字塔深度解析、模拟对象指南、反模式
references/testing-reference.md - —— 完整命名规范、缩写规则、领域命名
references/naming-reference.md - —— 错误层级、重试/降级模式、错误边界
references/error-handling-reference.md
Assets
资源文件
- — Step-by-step TDD workflow checklist
assets/tdd-checklist.md - — Copy-paste docstring templates (Python, JS/TS, C#, Rust, Go)
assets/docstring-templates.md - — Comprehensive code review checklist
assets/code-review-checklist.md
- —— 分步TDD工作流程检查清单
assets/tdd-checklist.md - —— 可直接复制的文档字符串模板(Python、JS/TS、C#、Rust、Go)
assets/docstring-templates.md - —— 全面的代码评审检查清单
assets/code-review-checklist.md
Scripts
脚本工具
- — Validate naming conventions across any codebase
scripts/check_naming.py - — Check function length, nesting depth, parameter count
scripts/check_complexity.py
- —— 验证任意代码库的命名规范
scripts/check_naming.py - —— 检查函数长度、嵌套深度、参数数量
scripts/check_complexity.py