关于 code-overhaul-review
面向开发者的代码库审查技能,用于维护、现代化或全面改造规划。它按阶段检查并依影响与工作量排列问题,同时要求先征求用户意见再确定方向。
主要功能
- 01初步评估仓库健康与范围
- 02按技术栈应用专项审查项
- 03影响与工作量优先级矩阵
- 04分阶段审查架构、质量、测试与性能
- 05为每项问题列出权衡与决策点
适用场景
- 01规划维护前评估代码库
- 02选择有限范围或全面改造模式
- 03重构前检查潜在风险
- 04制定兼顾测试顺序的执行计划
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ehmo/ code-overhaul-skill --skill code-overhaul-review安装后在 Claude Code 中输入/code-overhaul-review确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CHANGELOG.mdeval/GRADER.mdRUBRIC.mdSCENARIOS.md详细介绍
代码全面检修评审
对代码库进行审查,检查维护、现代化和全面检修方面的问题。对于每个问题,说明具体的权衡,先给出明确的建议,并在假设方向之前征求意见。
这是健康检查,不是功能评审。目标是找出对可靠性、性能、可维护性和开发效率影响最大的改进,然后按严谨的顺序执行。
**技术栈检测:**在步骤 0 开始时,扫描仓库中的语言标记(*.swift/Xcode 项目、go.mod、package.json/tsconfig)。对于检测到的每种技术栈,除通用部分外,还要应用下方“语言专属附录”中对应的附录。对于单体仓库,应用多个附录,并说明各项发现适用于哪个模块或软件包。
优先级层级
上下文不足?步骤 0 > 影响/工作量矩阵 > 测试图示 > 建议 > 其余内容。绝不要跳过步骤 0 或矩阵。
工程偏好
- DRY——积极指出重复代码。
- 测试充分是不可妥协的要求;测试过多胜过测试不足。
- “工程化到位”——既不脆弱,也不过度抽象。
- 多考虑边缘情况,不要减少;深思熟虑胜过速度。
- 明确胜过巧妙。
- 最小差异:新增的抽象和修改的文件越少越好。
- 性能是功能。前后都要进行性能分析。
- 可行时优先使用平台/API 或标准库,而非第三方依赖。
- 弃用警告就是 bug。主动修复。
- 构建时间很重要。任何会拖慢构建的改动都必须说明理由。
图示
在计划和行内代码注释中,使用 ASCII 图表示数据流、状态机、依赖关系图、流水线和决策树。在行为不明显的地方嵌入图示:模型、服务、视图/控制器、测试。
**图示维护也是改动的一部分。**过时的图示比没有图示更糟。即使超出范围,也要指出。
开始之前
步骤 0:范围评估
- **仓库健康状况:**编译器/代码检查器警告、弃用警告、TODO/FIXME/HACK 密度、死代码、未使用的导入、测试通过率、构建时间。(按附录补充技术栈专属工具。)
- **依赖情况:**所有第三方依赖及其当前版本与最新版本。标记:落后超过 1 个主版本、未维护(12 个月以上)、可由平台 API 替代的依赖。
- **平台/语言版本下限:**决定哪些现代 API 可用,以及哪些变通方案可以移除。
- **技术债务集中点:**按规模、改动频率、耦合度和 bug 历史,列出排名前 3–5 的文件/模块。
- **复杂度检查:**超过 15 个文件或新增超过 3 个抽象时,质疑范围是否合理。
提供三种模式:
- **SURGICAL:**一个主题,最小影响范围,一次会话。
- **SYSTEMATIC:**按章节逐项交互,每章不超过 4 个问题。
- **FULL AUDIT:**所有章节、所有问题。分阶段路线图。
**选择模式后,就要全面投入。**不得悄悄缩小范围。
评审章节
1. 架构
评估:模块结构和边界(绘制依赖关系图)、分层违规、数据流和事实来源、并发/线程安全、路由/导航一致性、扩展瓶颈、安全边界。针对每个主要边界,描述一个现实的生产环境故障,并判断现有代码能否处理。指出适合添加 ASCII 图示的位置。应用技术栈附录。
**停下。**提出 AskUserQuestion。用户回复前不要继续。
2. 代码质量
评估:文件/文件夹组织、DRY 违规、错误处理缺口(注明文件和行号)、命名一致性、技术债务热点、过度工程化和工程化不足、死代码、过时图示、代码检查器/编译器警告。应用技术栈附录。
**停下。**提出 AskUserQuestion。用户回复前不要继续。
3. 测试
为所有关键流程、流水线、状态转换和分支绘制图示。针对每一项,评估:是否有测试?测试是否有效?是否覆盖边缘情况?是否快速且可靠?此外,还要评估测试分布、执行时间(标记耗时测试)、隔离性、缺失的测试类别和模拟策略。应用技术栈附录。
**停下。**提出 AskUserQuestion。用户回复前不要继续。
4. 性能
评估:启动时间、内存占用和泄漏、关键路径上的响应延迟、I/O 模式、网络效率、构建时间、二进制文件/捆绑包大小。应用技术栈补充项。
停止。 使用 AskUserQuestion。在用户回复前,不要继续。
5. 依赖项与现代化
评估:过时的依赖项、可替换的依赖项、无人维护的依赖项、语言现代化机会、工具链卫生状况、CI/CD 健康状况。应用技术栈补充项。
停止。 使用 AskUserQuestion。在用户回复前,不要继续。
每个问题都要包含
- 文件/行号引用。
- 2–3 个选项,包括“暂缓”。
- 每个选项单独一行:工作量、风险、影响范围、维护负担。
- 以指令开头:“执行 B。原因如下:”
- 用一句话对应工程偏好。
- AskUserQuestion:“我们建议 [字母]:[原因]”,然后列出
A) ... B) ... C) ...。标签:数字 + 字母(例如,“3B”)。
必需的输出
影响/工作量矩阵
LOW EFFORT HIGH EFFORT
┌─────────────────┬─────────────────┐
HIGH │ DO FIRST │ PLAN CAREFULLY │
IMPACT │ (quick wins) │ (core overhaul) │
├─────────────────┼─────────────────┤
LOW │ IF TIME │ SKIP / DEFER │
IMPACT │ (polish) │ (not worth it) │
└─────────────────┴─────────────────┘
不在范围内
逐项列出已暂缓的工作,并附上一句话说明理由。
已有内容
代码库中已有但使用不足的实用工具、辅助函数或模式。
已暂缓工作 → Beads
bd create "<title>" -t <type> -p <priority> -d "<what, why, current state, where to start, prereqs>" -l "tech-debt,overhaul"
提交前先询问。使用 bd dep add 添加链接。
图表
改动前后的依赖关系图、重构后的数据流、状态机。指出需要内联图表的文件。
故障模式
针对每条修改后的代码路径:列出一个真实的故障情况 → 测试是否覆盖?是否有错误处理?对用户可见还是静默发生?没有测试、没有处理且静默发生 → 严重缺口。
迁移/回滚
采用渐进式还是一次性迁移?回滚计划是什么?新旧方案是否并存?如何验证?
执行顺序
使用编号,并遵循以下要求:(1) 满足改动间的依赖关系;(2) 按影响/工作量优先级排序;(3) 先编写测试,再重构;(4) 每一步都可单独交付。
完成摘要
╔════════════════════════════════════════════════╗
║ CODE OVERHAUL SUMMARY ║
╠════════════════════════════════════════════════╣
║ Mode: ___ ║
║ Stacks detected: ___ ║
║ Warnings: ___ compiler, ___ deprec ║
║ Dead code: ___ ║
║────────────────────────────────────────────────║
║ Architecture: ___ issues ║
║ Code quality: ___ issues ║
║ Tests: ___ gaps ║
║ Performance: ___ issues ║
║ Dependencies: ___ outdated, ___ replace║
║────────────────────────────────────────────────║
║ Quick wins: ___ ║
║ Core overhaul: ___ ║
║ Beads filed: ___ ║
║ Critical gaps: ___ ║
║ Execution steps: ___ ║
╚════════════════════════════════════════════════╝
添加技术栈补充项中特有的行(例如,强制解包数量、any 数量、race-clean 状态)。
回顾与改进
检查 Git 日志:高频变更的文件、已回滚的提交、大型“修复”提交、反复出现的模式(“修复……中的崩溃”“变通处理……”)。对历史问题频发的区域采取更积极的处理方式。
格式
问题使用数字编号,选项使用字母编号。优先列出建议选项。每个选项用一句话说明。每个部分结束后暂停。
未解决的决策
在末尾列出:“可能在日后带来问题的未解决决策。”绝不默默采用默认方案。
反模式
- 一次性大改写 → 渐进式改进。
- 未编写测试就重构 → 先编写特征测试。
- 过度打磨 → 关注健康状况,而非完美。
- 盲目追逐新技术 → 只解决具体问题。
- 破坏构建 → 每次提交都必须能够编译并通过测试。
特定语言的补充项
检测到相应技术栈时应用以下补充项。对于单体仓库,应用所有匹配的补充项,并为每条发现标注其模块。
补充项:iOS / Swift
触发条件: .swift 文件、.xcodeproj、*.xcworkspace、包含 Apple 平台目标的 Package.swift。
步骤 0 的附加项
- 运行:统计 Xcode 警告数量、SwiftLint 违规数量、部署目标(最低 iOS 版本)。
- 部署目标决定:SwiftUI API 范围、结构化并发的可用性,以及哪些 UIKit 变通方案可以移除。
- 依赖项审计细则:SPM/CocoaPods/Carthage。可替换项:Kingfisher→AsyncImage、Alamofire→URLSession async/await、SnapKit→现代 AutoLayout、RxSwift→Combine/async-await、KeychainAccess→原生 keychain、SwiftyJSON→Codable、IQKeyboardManager→原生键盘避让。
架构附加项
- 状态管理的一致性:@Observable、ObservableObject 与 @State——每种关注点选一种,不要混用。
- 导航:NavigationStack、协调器模式还是混用——是否保持一致?
- 并发模型:结构化并发的采用边界与旧版 GCD/completion handler。迁移分界在哪里?
- Core Data/SwiftData 技术栈的健康状况。扩展目标是否正确共享代码?
代码质量补充
- 强制解包和隐式解包可选值——逐一列出,这些都可能导致崩溃。
try?静默吞掉错误。空的 catch 块。- 保留循环风险:闭包中缺少
[weak self]、非弱引用的代理属性。 - 未使用的 @objc 暴露、过时的 Storyboard/XIB 连接、无用的 IBOutlets/IBActions。
- 过于庞大的 ViewControllers/Views(超过 300 行)。
- 面向协议的过度设计:只有一个实现者的协议、不必要的关联类型。
测试补充
- XCTest 与 Swift Testing 的采用情况。UI 测试的可靠性(单项 UI 测试超过 10s 时标记)。
- 测试主机应用依赖——单元测试能否在不启动应用的情况下运行?
- Core Data 测试是否使用内存存储?网络测试是否使用 URLProtocol 模拟?
- 测试数量较多时,整个测试套件的耗时很重要——超过 60s 时标记。
- 缺少的测试:复杂布局的快照测试、无障碍审计测试。
性能补充
- **启动:**main 前阶段(dylib 加载、+load、静态初始化器)和 main 后阶段。
didFinishLaunching中是否有在主线程上同步执行的工作? - **主线程:**主线程上的文件 I/O、JSON 解析、图像解码、Core Data 查询。
- **滚动:**单元格复用、异步图像加载、Auto Layout 歧义、屏幕外渲染(cornerRadius + clipsToBounds)。
- **媒体:**显示前是否对图像进行降采样?PhotoKit 获取效率如何?是否有不必要的格式转换?
- **构建:**使用
-Xfrontend -debug-time-function-bodies找出最慢的文件。复杂的类型推断。SPM 解析耗时。 - **二进制文件:**未使用的资源目录条目、可以按需加载的嵌入资源。
现代化补充
- 结构化并发:async/await、actors、任务组。
- @Observable 宏(iOS 17+)、#Preview 宏、用于 EnvironmentValues 的 @Entry。
- 类型化 throws(Swift 6)、严格并发检查的就绪情况。
- Xcode 整洁度:未使用的构建阶段、过时的 schemes、代码签名配置偏差、层级错误的构建设置。
摘要补充
添加以下行:最低 iOS 目标版本、Swift 版本、强制解包数量、SwiftLint 违规数。
其他反模式
- 从 UIKit 迁移到 SwiftUI 时缺少边界策略 → 定义一次桥接模式,并在各处统一使用。
附录:Go
**触发条件:**go.mod、*.go 文件。
步骤 0 补充
- 运行:
go vet、staticcheck、golangci-lint、govulncheck ./...、检查go mod tidy的变更。 - go.mod 中的 Go 版本决定:range-over-func(1.23+)、log/slog(1.21+)、errors.Join(1.20+)、泛型深度、循环变量修复(1.22+)。
- 依赖审计细则:
go list -m -u all。可替换的依赖:gorilla/mux→stdlib 1.22+ 路由、logrus→log/slog、pkg/errors→fmt.Errorf %w、testify→stdlib testing、go-playground/validator→自定义实现、gorm→sqlc/sqlx、对于简单 CLI,cobra→stdlib flag。
架构补充
- 包边界:
internal/的使用是否正确?是否存在循环依赖风险? - 接口泛滥:由实现方而非使用方定义的接口是否过多。接受接口,返回结构体。
- 依赖注入:使用 wire、手动注入,还是到处散布
init()? - 优雅关闭链:信号 → context 取消 → 资源清理。
- 错误传播:sentinel、类型化错误还是包装错误——是否保持一致?
- Context:值与取消——是否滥用?
代码质量补充
- 未检查的错误:
_ = foo()——除非有注释说明,否则逐一列出。 - 复杂函数中的裸返回。
- 包级全局变量和对
init()的滥用。 - 命名:遵循 Go 约定(MixedCaps、1-2 个字符的接收者、小写单词包名)。名称重复冗长(
user.UserService)。 - 过度设计:只有一个实现的接口、不必要的泛型、仅用于 2 个配置值的 Options 模式。
- 设计不足:超过 2000 行的文件、超过 5 个参数、在泛型更清晰时仍使用
any/interface{}。
测试补充
- 表驱动测试是否一致?是否使用
t.Helper()?是否使用t.Run()编写子测试? - 集成测试是否标记为
//go:build integration? - 竞态检测器:
go test -race是否通过?这是门槛,不是可选项。 - 为热点路径添加基准测试(
BenchmarkX)。为解析器添加模糊测试(FuzzX)。 - 复杂输出使用黄金文件。
testdata/是否组织有序? - 模拟:仅在边界处使用接口,不要把所有内容都模拟掉。处理程序使用
httptest。
性能补充
- CPU: 紧密路径中不必要的内存分配、热点代码中的反射、循环内编译正则表达式(编译一次并作为包级变量)、循环中拼接字符串(使用 strings.Builder)。
- 内存: Goroutine 泄漏(无界启动且不取消 context)、sync.Pool 的使用机会、预分配 slice(
make([]T, 0, cap))、热点路径中的 string↔[]byte 转换。 - 并发: Mutex 争用(RWMutex?atomic?)、channel 缓冲区大小、无上限的 goroutine 扇出(errgroup)、context 传递缺口。
- I/O: 连接池大小、预处理语句复用、N+1 查询、复用 HTTP 客户端(而非每个请求都创建)、未关闭响应体、文件使用 bufio。
- 构建: CGO(拖慢构建、增加交叉编译复杂度)、不必要的
go generate。 - 二进制文件:
-ldflags "-s -w"、-trimpath、未使用依赖造成的膨胀。
现代化补充
- 在能提升清晰度时,用泛型替代
interface{}/代码生成(仅限具体类型超过 2 种的情况)。 - range-over-func(1.23+)、log/slog、errors.Join、循环变量修复(1.22+)——移除变通方案。
- iter 包(1.23+)、any/comparable 约束。
- 工具链:保持 Makefile/Taskfile 整洁、golangci-lint 配置及时更新、CI(test、vet、lint、race、vulncheck)。
摘要补充
添加以下行:Go 版本(mod)、go vet 问题、staticcheck 问题、govulncheck 发现项、未检查的错误、竞态检测是否干净(Y/N)。
额外反模式
- 过度使用接口 → 单方法接口是 Go 的理想做法,而不是起点。
- 过早使用泛型 → 仅当具体类型超过 2 种且模式已得到验证时才使用。
补充:Web / JavaScript / CSS
触发条件: package.json、tsconfig.json、.js、.ts、.jsx、.tsx、.css、.scss、*.html 文件。
第 0 步补充
- 运行:检查
tsc --noEmit错误、ESLint/Prettier 违规、npm audit、包体积(总计 + 按路由统计)。 - 是否启用了 TypeScript 严格模式?如果没有,迁移路径属于高优先级事项。
- 浏览器基线版本(browserslist)决定:CSS 嵌套、:has()、容器查询、structuredClone、AbortSignal.any、Promise.withResolvers。
- 依赖审计:
npm outdated。可替换项:moment→Temporal/date-fns、lodash→原生方法(Array.at、Object.groupBy、structuredClone)、axios→fetch、classnames→clsx/模板字面量、uuid→crypto.randomUUID、node-fetch→原生 fetch(Node 18+)。
架构补充
- 组件层级(绘制树状图)。状态管理:本地还是全局、props 层层传递还是使用 context 或 store——是否一致?
- 数据获取:按组件、按路由还是集中处理?是否缓存/去重?是否有加载/错误状态?
- API 层:fetch 调用是分散还是集中处理?
- 如适用,明确 SSR/SSG/CSR 边界。错误边界的放置位置。
- 构建配置复杂度。环境处理方式。
代码质量补充
JS/TS:
any类型——逐一列出,它们会削弱 TypeScript 的作用。- 绕过安全检查的
as断言。松散相等(==)。 - 未捕获的 Promise 拒绝。缺少错误边界。
- 臃肿的 barrel 文件影响 tree-shaking。未使用的导出(
ts-prune)。 - 超过 300 行的组件文件。
CSS:
- 优先级冲突,
!important泛滥。 - 未使用自定义属性的魔法数字。需要设计令牌统一的重复值。
- 未使用的 CSS。命名不一致(BEM、工具类或随意命名)。
- z-index:有文档记录的层级规范,还是一团乱?媒体查询:分散还是集中?
- CSS-in-JS、样式表或工具类——是否采用一致的方案?
HTML/无障碍:
- 语义化 HTML(是否满是 div?)。ARIA:缺失或错误。键盘导航、焦点管理、颜色对比度、替代文本、表单标签、标题层级。
测试补充
- 逻辑使用单元测试(Jest/Vitest)。行为使用组件测试(Testing Library)——标记过度使用
getByTestId的情况,优先使用getByRole/getByText。 - 关键路径使用 E2E 测试(Playwright/Cypress)。复杂布局使用视觉回归测试。
- 使用 MSW 模拟网络——是否一致?快照测试:有用还是噪声?
- 可访问性测试(axe-core)。测试套件速度:标记总耗时超过 30s、单项测试超过 5s 的情况。
性能补充
- Core Web Vitals: LCP(关键渲染路径)、CLS(图片未设置尺寸、字体闪烁、动态注入)、INP(长任务、繁重的处理器)。
- 包体积: 按路由拆分,有效执行 tree-shaking?为首屏以下内容使用动态导入,重复依赖,使用
source-map-explorer分析。 - 加载: 是否内联关键 CSS?是否存在阻塞渲染的资源?字体策略(font-display、预加载)?图片(WebP/AVIF、srcset、懒加载、显式尺寸)?
- 运行时: 不必要的重新渲染(在有测量依据时补充缺失的 memo)、DOM 抖动、事件监听器清理、Web Worker 使用机会、使用 requestAnimationFrame 更新视觉效果。
- 缓存: Service Worker 策略、HTTP 标头、CDN、stale-while-revalidate、资源指纹。
- 网络: API 瀑布流(串行→并行)、过度获取、缺少分页。
现代化补充
- CSS:原生嵌套(移除预处理器嵌套)、容器查询、
:has()、View Transitions、Popover API、<dialog>(移除模态框库)、color-mix()、@property。 - TS:严格模式路线、
satisfies、模板字面量类型、可辨识联合、using(5.2+)。 - 平台:structuredClone、Object.groupBy、Set 方法、导入属性。
- 工具链:打包工具是否跟上潮流(Webpack→Vite?)、Node 版本、包管理器一致性、monorepo 工具、预览部署。
摘要补充
添加以下行:Framework、TS 严格模式 Y/N、any 数量、ESLint 违规数、包体积(gzip)、npm audit 漏洞数、LCP。
其他反模式
- 过早抽象 → 不要为 3 个按钮构建组件系统。
- CSS 重置打地鼠 → 修复优先级模型,而不是处理表面症状。
- 将
any当作逃生舱 → 每个any都是延期偿还且会复利增长的债务。 - 框架频繁更换 → 应在解决具体问题时迁移,而不是为了追新。