审查工具
用工具(linter、类型检查器、测试覆盖)自动化机械检查使审查者聚焦逻辑。
为什么
代码审查时间稀缺,花在机械检查(风格、格式、类型错误、缺测试)是浪费——这些正是工具比人强的事。linter 0.1s 抓风格违规;人花 30 秒找和写评论、作者花 5 分钟修和回、循环重复下违规。CI 自动这些检查使 PR 不通过 linter、类型检查器和测试覆盖阈值不能开——审查者永不见风格违规、类型错误或未测代码,时间花仅人能做的 事: 逻辑、架构、安全、命名。这使审查更快(15 分钟非一小时)、更有价值(反馈关于设计非格式)、更不挫(无人喜评论缺分号)。
何时使用
项目开始时设工具 CI 强制。团队识别重复检查时增量加工具。
如何做
1. linter(ESLint、Biome、Ruff、golangci-lint) - 强风格、抓常见 bug、禁不安全模式 - CI 每 PR 跑、违规坏 - 配规则匹配团队约定 - 自动修可自动修的(格式、导入顺序) 2. 格式化器(Prettier、gofmt、rustfmt、black) - 消格式讨论——工具决定 - 保存时跑(编辑器)和 CI 中(强制) - 审查中永无格式评论 3. 类型检查器(TypeScript、mypy、pyright) - 运行前抓类型错误 - 类型错误坏构建 - 用严格模式(无隐 any、无 null 无显检查) 4. 测试覆盖(jest --coverage、pytest --cov、go test -cover) - 新代码要求覆盖(如新行 80%) - 覆盖降阈值下坏构建 - 覆盖是地板非目标——100% 覆盖不意味好测试 5. 预提交钩子(husky、lefthook、pre-commit) - 提交时跑 linter、格式化器和类型检查器 - 检查坏提交坏——开发者推前修 - 这在到 CI 前更不用说审查前抓问题
示例
// .eslintrc.json——强风格和抓 bug
{
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"no-unused-vars": "error",
"no-implicit-coercion": "error",
"eqeqeq": "error", // 无 ==、用 ===
"no-var": "error", // 用 let/const
"prefer-const": "error"
}
}
// .prettierrc——消格式讨论
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80
}
// tsconfig.json——严格类型检查
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}
}
// package.json——覆盖阈值
{
"scripts": {
"test": "jest --coverage --coverageThreshold='{"global":{"lines":80}}'"
}
}
// .husky/pre-commit——提交前跑检查
#!/bin/sh
npx lint-staged
// lint-staged 配置:
{
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write", "tsc --noEmit"]
}
}
// .github/workflows/ci.yml——CI 强制
name: CI
on: [pull_request]
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint // eslint
- run: npm run format:check // prettier --check
- run: npm run typecheck // tsc --noEmit
- run: npm test // 带覆盖 jest
// 现审查者可聚焦逻辑非风格:
// 审查者评论: "这函数有竞条件——
// 两请求可更新同记录。考虑用带版本字段的乐观锁。"
// (非: "42 行用了 == 而非 ===。")常见问题
- ⚠审查中评论 linter 能抓的风格——"用单引号"是 linter 规则非审查评论,审查者时间浪费于机械检查。
- ⚠设 linter 但 CI 不强制——linter 本地过但开发者禁(eslint-disable)或不跑,违规发。
- ⚠要求 100% 测试覆盖——团队写琐碎测试(expect(true).toBe(true))达阈值,覆盖 100% 但测试无价值,指标变游戏。
- ⚠CI 跑所有检查但本地不跑——开发者推、等 CI 10 分钟、发现 lint 错、修、再推、循环重复 5 次才绿。
最佳实践
- ✓CI 和预提交钩子自动化所有机械检查(lint、格式、类型检查、覆盖)使审查者永不见——审查时间花逻辑、架构和安全非风格。
- ✓保存时(编辑器集成) 和提交时(预提交钩子)本地跑检查非仅 CI——开发者即时反馈不等 10 分钟 CI 找 lint 错。
- ✓为新代码设覆盖阈值(新行 80%)而非所有代码 100%——这鼓励测新代码不激旧代码琐碎测试。
- ✓用严格 TypeScript(strict: true、noImplicitAny、strictNullChecks)——类型检查器抓整类 bug(空解引用、类型困惑)否则审查者须手动查。