mcpField
I
improve-code-quality

improve-code-quality

github.com/wondelai开发2.5k2.3k 次安装7 周前更新
代码仓库

关于 improve-code-quality

这项可交互、可续行的技能通过九个阶段,引导开发者改进可运行的原型,涵盖测试、可读性、生产可靠性和数据设计。它会将决策与产物记录在项目的 `docs/` 目录中。

主要功能

  1. 01按顺序推进九个改进阶段
  2. 02每项决策均需用户确认
  3. 03支持续行的计划与阶段跟踪
  4. 04在项目 `docs/` 中记录文档
  5. 05以测试安全网作为阶段门槛
  6. 06分开结构调整与行为变更

适用场景

  1. 01修改旧代码前添加特征测试
  2. 02规划重构与架构改进
  3. 03为原型投入生产做准备
  4. 04跨会话继续代码质量改进计划

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wondelai/skills --skill improve-code-quality

安装后在 Claude Code 中输入/improve-code-quality确认已加载。

附带文件references/artifact-templates.md

详细介绍

提升代码质量

将一个能运行但未经测试的 vibe coding 原型,打磨成可交付、可运维的产品。这是一段包含九个阶段、可交互且可随时恢复的旅程:每次做出决定前,Agent 都会先询问,并将结果记录到项目的 docs/ 文件夹中,因此你可以在任何阶段结束后暂停,稍后再继续。即使是一个仅有一周历史的原型,也已经是遗留代码——因此,第一步是建立安全网;有了这张安全网,之后的每个阶段都可以验证。

核心原则

一个未经测试、仅有一周历史的原型,已经是遗留代码:从战术转向战略——先建立安全网,再依次提升可读性、理顺结构并加固生产环境。 此技能会安排各个阶段、提出决策问题,并将每项选择记录到 docs/ 中。各组成技能负责提供方法——调用它们,而不是临时编造框架。跳过前面的阶段(先重构再测试,先扩容再评估规模),正是这种顺序旨在防止的典型问题。

流程图

阶段技能回答的问题产物
1working-with-legacy-code我能否在不知不觉中破坏代码的情况下修改它?创建 docs/TESTING.md + docs/TECH-DEBT.md — GATE
2clean-code下一个人(和 Agent)能看懂这段代码吗?扩展 docs/TECH-DEBT.md
3refactoring-patterns我能否在不改变行为的情况下调整结构?扩展 docs/TECH-DEBT.md
4software-design-philosophy复杂性是否隐藏在深模块之后?扩展 docs/TECH-DEBT.md
5clean-architecture业务规则依赖于框架,还是框架依赖于业务规则?扩展 docs/ARCHITECTURE.md
6pragmatic-programmer我们停止维护后,哪些习惯能让代码保持整洁?扩展 docs/TECH-DEBT.md
7release-it它能否在严苛的生产环境中稳定运行?创建 docs/RELIABILITY.md
8system-design它的规模是否适合我们实际的负载?扩展 docs/ARCHITECTURE.md + docs/RELIABILITY.md
9ddia-systems数据层在并发场景下是否正确且持久可靠?扩展 docs/ARCHITECTURE.md

操作规则

  1. 优先恢复进度。 在做任何事之前,先阅读 docs/IMPROVE-CODE-QUALITY-PLAN.md 和 Journey Map 中的所有产物。如果跟踪文档存在,用 3-5 行概述 Journey 状态,并询问要进入哪个阶段。用户确认入口后即为完成。存在跟踪文档的 Journey 应恢复,而不是重新开始。
  2. 仅首次运行时进行初始信息收集。 如果没有跟踪文档:先执行下方的初始信息收集,然后创建 docs/IMPROVE-CODE-QUALITY-PLAN.md,将每个阶段的状态设为 pending | in-progress | awaiting-evidence | done | deferred: reason | skipped: reason。跟踪文档创建完成且用户确认阶段计划后即为完成。
  3. 进入阶段。 说明该阶段的作用、需要做出的决策、产出的文档,以及大致工作量。提供继续/跳过/推迟选项——标记为 GATE 的阶段可以推迟,但不能跳过。用户选择继续后,将阶段标记为 in-progress。用户做出选择后即为完成。
  4. 调用技能与备用方案。 加载并使用该阶段的技能:每个阶段的 Invoke 行都会通过 slug 指定技能——使用该技能执行阶段任务。如果技能不可用,提供:npx skills add wondelai/skills/<slug> --global。如果用户拒绝,则根据 Brief 执行该阶段——采用最低可行方法。说明当前使用的模式。
  5. 阶段内决策。 提出「与用户共同决定」下的每个问题——给出具体选项和你的建议。将选择记录在跟踪文档的 Key Decisions 中。默默作出的决策属于缺陷。
  6. 阶段退出。 写入前先展示产物草稿内容供用户确认。获批后:编写或扩展 docs/ 文件,更新跟踪文档(状态、Key Decisions、Next Actions)。文件写入完成且阶段行显示 done 后即为完成。
  7. 产物规范。 写入前先阅读;仅在文件不存在时创建,否则应扩展文件——添加或更新自己的章节,并保留其他人的内容。docs/ 中的文件名均为大写。首次创建 docs/ 文件时,请参阅 references/artifact-templates.md;使用完整模板创建文件(包含所有章节标题),然后填写该阶段指定的章节。每项建议都必须作为复选框或表格行记录,并注明负责人和优先级。
  8. 阶段 1 是关卡;提交必须单一用途。 Safety Net Map 未列出的代码不得由任何阶段触及——先将其列入固定范围(未列出即表示不在 Pinned behaviors 下;Gaps 列中的条目也不得触及)。结构变更和行为变更绝不能放在同一提交中:先在仅含结构变更的提交中重构,并确保测试通过,然后再通过独立提交修改行为。重构期间测试变红时,应回退并拆成更小步骤重试,而不是调试。安全网测试新增内容和 docs/ 更新都必须各自使用单一用途的独立提交。

摸底

创建跟踪表前,先询问以下问题:

  1. 应用的作用是什么?如果它出问题,最糟糕的后果是什么?(评估风险并确定阶段优先级)
  2. 接下来要修改哪个模块?哪个模块的变更最频繁(git log),或者属于核心领域?(根据三轴启发式选择 Phase 1 的起始模块)
  3. 目前是否存在自动化测试?测试命令能否成功通过?(确定 Phase 1 安全网的范围)
  4. 技术栈是什么——框架、ORM、数据库?(决定是否进入 Phase 5 和 Phase 9——边界和数据决策)
  5. 这是否已在生产环境中运行并处理真实用户数据?活跃用户或请求大约有多少?(决定是否进入 Phase 7-9——弹性设计应由需求驱动)
  6. 它会调用哪些外部依赖——第三方 API、支付、电子邮件、队列?(决定是否进入 Phase 7——审查集成点)
  7. 现在希望推进到哪个阶段?(真实用户出现前推进 Phase 1-3;发布前推进 Phase 7;Phase 8-9 根据实际增长跟进)

跳过阶段的启发式规则:如果实际负载远低于任何扩展阈值,就跳过 Phase 8-9(从需求出发,而不是从解决方案出发——用户只有 50 个时,不要为 50k 个用户构建系统)。有真实用户后,Phase 7 不是可选项——即使流量很低,超时和熔断器也是基本要求(可标记为 deferred: reason,但绝不能标记为 skipped)。绝不要跳过 Phase 1;它是门槛。然后根据模板创建跟踪表,并确认计划。

当 docs/IMPROVE-CODE-QUALITY-PLAN.md 存在、每个阶段都已标明状态,且用户已确认计划时,即视为完成。

阶段

各阶段按列出的顺序推进——每个阶段都假定前一阶段的产物已存在。根据操作规则,可以进入、跳过或推迟任何阶段,但 Phase 1 是所有阶段的门槛:下游阶段不得触及未固定的代码。

Phase 1 — 构建安全网(working-with-legacy-code)— 门槛

目的: 固定变更点的当前行为,以便验证后续每个阶段。安全网映射中未涵盖的代码,任何阶段都不得触及。

简介(备用方案): 没有测试的代码就是遗留代码,所以即使是一周前写的原型也符合条件。先覆盖再修改,绝不要盲目编辑:找出变更点,用侵入性最小的接缝打破内联依赖(为生产环境提供默认值的参数化构造函数;对一个深埋的调用使用提取并重写),然后编写特征测试来记录实际行为——断言某个错误值,查看失败结果,再固定实际值。如果时间不允许全面覆盖,就对新代码采用 Sprout/Wrap,并将未经测试的宿主代码记为技术债。

调用: 使用 working-with-legacy-code 技能,并采用摸底时选定的起始模块。要求从入口方法开始绘制效果示意图,找出接缝,并确定最小特征测试集,以固定当前的注册/计费/核心行为。

与用户共同决策: (1) 根据三轴启发式确认起始模块——接下来要修改的模块、变更频繁的模块、核心领域模块。(2) 特征测试过程中发现的错误:固定错误行为并将其登记到债务账本中,绝不要悄悄修复——调用方可能依赖这种特殊行为。确认用户接受这一点。

产物: 创建 docs/TESTING.md,其中包含 ## Test Strategy、## Safety Net Map(模块 | 已固定行为 | 测试文件 | 缺口)和 ## Characterization Backlog;创建 docs/TECH-DEBT.md,其中包含 ## Debt Ledger(项目 | 位置 | 类型 | 风险 | 工作量 | 优先级 | 状态)和 ## Sprout / Wrap Register。更新跟踪表。

完成条件: 目标模块的行为已固定,测试套件成功通过,两个文件均已创建,且 Phase 1 状态为 done——只有这样才能解锁后续阶段。

阶段 2 — 提高代码可读性(clean-code)

目的: 现在变更已可验证,接下来优化读者体验——包括命名、小型单一用途函数和安全的错误处理。

简述(备用): 代码被阅读的次数远多于编写的次数。名称应体现意图(elapsedTimeInDays,而不是 d);布尔值应读起来像谓词;函数应在同一抽象层级上只做一件事,参数数量为 0–2 个(标志参数相当于两个函数)。命令查询分离:要么更改状态,要么返回值,绝不可两者兼做。错误处理:优先使用异常而非返回码,捕获具体类型,绝不返回或传递 null(改用空集合、Optional 或 Null Object),并在每个抛出的错误中提供操作和状态上下文。

调用: 针对目标模块使用 clean-code 技能。请它对六项规范分别给出 0–10 分,并按优先级列出前十项修复,还要审计错误处理(裸捕获、返回 null、缺少上下文的错误)。

与用户共同决定: 哪些修复现在应用,哪些记录为技术债务;团队今后采用哪些命名和错误处理规范;以及是否将 clean-code 评分设为 CI 门禁。

产出物: 扩展 docs/TECH-DEBT.md:在 ## Smell Inventory 中为每个命名/函数/错误问题添加行(问题 | 位置 | 重构 | 状态),并在 ## Adopted Conventions 下记录商定的规则。更新跟踪表。

完成条件: 模块评分达到 8 分以上,或所有低于 8 分的差距都在 Smell Inventory 中有对应修复;规范已记录,且 Phase 1 测试仍然通过。

阶段 3 — 应用命名重构(refactoring-patterns)

目的: 将“整理一下”转化为有名称、保持行为不变、分小步执行的变换。

简述(备用): 每种代码异味都对应一种命名重构。提取函数是最常用的方法——如果你想写注释来解释一个代码块,就提取该代码块,并用注释的内容为它命名。此外还包括用符号常量替换魔法数字、用卫语句替换嵌套条件、用多态替换条件语句、引入参数对象。工作流:测试通过、执行一次变换、测试通过、提交;测试失败就回退,而不是调试。准备性重构(先让变更变得容易,再进行容易的变更)和三次法则有助于避免过早抽象。

调用: 针对有异味的函数并结合 Phase 1 测试使用 refactoring-patterns 技能。请它为每种异味命名、指出对应变换,并在每次测试后一次只应用一种变换。

与用户共同决定: 范围——本轮要处理哪些异味;即将推出的功能是否需要先在插入点进行准备性重构;以及重构后的模块是否加入 TESTING.md 中的 CI 门禁列表。

产出物: 扩展 docs/TECH-DEBT.md 的 ## Smell Inventory:为每种异味记录已应用的命名重构及其状态。更新跟踪表。

完成条件: 目标异味均标明命名重构,状态为 done/ticketed;测试通过;结构变更已通过仅包含结构变更的提交合并。

阶段 4 — 通过深层模块降低复杂性(software-design-philosophy)

目的: 对抗无人监督的 Agent 造成的类泛滥——用简单接口隐藏真正的机制,而不是不断增加浅层类。

简述(备用): 复杂性是敌人;尽量减少模块给系统其余部分带来的负担。模块深度 = 功能 ÷ 接口复杂度;深层模块用小型接口隐藏机制,浅层模块则不会(类泛滥)。合并那些总是一起出现且共享状态的浅层类。留意信息泄漏(一个决策反映在多个模块中)和时间分解(按执行顺序而非知识组织)。这是从战术转向战略:投入 10-20% 的精力来保持设计整洁。

调用: 使用 software-design-philosophy 技能,检查迄今涉及的模块集合。询问哪些类是浅层类、信息在哪里跨边界泄漏,以及如何通过合并构建接口更简单的深层模块。

与用户一起决定: 哪些合并现在执行、哪些推迟,同时谨防合并无关的关注点。

产物: 在 docs/TECH-DEBT.md 的 ## Smell Inventory 下补充类泛滥/浅层模块/信息泄漏条目及已实施的合并。更新跟踪器。

完成条件: 每个浅层模块集群都已合并或记录了修复方案;没有为了追求“模块化”而增加接口数量;测试通过。

阶段 5 — 划定架构边界(clean-architecture)

目的: 让框架和数据库依赖业务规则,而不是反过来。

简述(备用): 依赖规则:源代码依赖指向内层——实体,然后是用例,再然后是接口适配器,最后是框架/驱动;内层不能命名任何外层内容。数据库和 Web 都只是细节,是规则的插件。通过依赖倒置强制执行:用例拥有仓库接口;Postgres/Stripe 实现位于外层适配器中。SOLID 是中层工具。共享同一数据模型的微服务就是分布式单体——先在服务内部应用此规则。

调用: 使用 clean-architecture 技能,结合当前模块图和初步调研中确定的技术栈。请其绘制依赖图,列出每一处业务逻辑导入 ORM 或框架的违规,并展示如何提取出不依赖框架、通过自有接口提供服务的用例。

与用户一起决定: 此轮要将边界推进到什么程度、先将哪些供应商(支付、存储)封装在自有接口后,以及是否等到服务内边界稳固后再进行计划中的服务拆分(避免形成分布式单体)。

产物: 更新 docs/ARCHITECTURE.md:在 ## Layer Map & Dependency Rule 下记录各层和当前违规项(违规 | 位置 | 修复 | 状态),并在 ## Decision Log 下记录边界决策。更新跟踪器。

完成条件: 每项依赖规则违规都已作为跟踪条目记录并配有修复方案;至少封装风险最高的供应商;业务规则测试无需框架即可运行;测试通过。

阶段 6 — 固化习惯(pragmatic-programmer)

**目的:**确立元原则,确保这段旅程结束后,代码库仍易于修改。

**简要说明(备用):**DRY 关注的是知识,而不是文本——对同一条规则在两个地方的重复实现进行去重(客户端和服务器端的验证),不要处理巧合相似的内容。正交性:更改一个组件不应影响另一个组件。破窗理论:立即修复权宜之计,或用已跟踪的工单将其封存——绝不要留下未跟踪的 // TODO。可逆性:通过自有接口封装第三方供应商。示踪弹:将下一个功能构建为一个精简但真实的端到端切片,而不是逐层构建。

**调用:**在整个代码库中使用 pragmatic-programmer 技能。请它标出重复的知识(忽略巧合重复),以及需要封存的破窗或未跟踪的 TODO。

**与用户共同决定:**每次迭代的技术债预算,以及破窗策略——哪些立即修复,哪些登记为工单。

**产物:**扩展 docs/TECH-DEBT.md:在 ## Debt Ledger 中记录重复知识和破窗事项,并在 ## Debt Budget & Broken-Windows Policy 和 ## Adopted Conventions 下记录商定的策略。更新跟踪表。

**完成条件:**重复知识问题已登记到账本或修复,不再有未跟踪的权宜之计,并且已写明技术债预算策略。

阶段 7 — 确保生产环境稳定运行(release-it)

**目的:**强化每个集成点,让缓慢或故障的依赖能够优雅降级,而不是拖垮整个应用。

**简要说明(备用):**通过 QA 的软件未必能在生产环境中存活。集成点是头号故障源——响应缓慢比没有响应更糟。不可妥协的要求:每个出站调用都必须设置连接和读取超时;对故障依赖启用断路器(跳闸后断开、快速失败、半开恢复);通过舱壁隔离资源池;使用带指数退避和抖动的重试;清理稳态运行期间累积的杂物。通过功能标志和扩展-收缩迁移,将部署与发布解耦。添加深度健康检查、RED 指标和基于症状的告警。

**调用:**根据接入阶段收集的出站依赖,使用 release-it 技能。请它审计没有超时的调用、断路器和舱壁的设置位置,以及深度健康检查、RED 指标和告警设计。

**与用户共同决定:**断路器阈值、哪些依赖需要专用资源池,以及告警症状和阈值(错误率、延迟)。

**产物:**创建 docs/RELIABILITY.md,包含 ## Integration-Point Audit(dependency | timeout | circuit breaker | bulkhead | retry policy | status)、## Health Checks & Metrics 和 ## Deploy vs Release。更新跟踪表。

**完成条件:**每个出站调用都有超时,关键依赖配有断路器和舱壁,已设置深度健康检查、RED 指标和基于症状的告警,已为累积杂物安排稳态清理,可在不重新部署的情况下回滚发布,并且审计表中关键路径没有未解决项。

阶段 8 — 按实际负载规划规模(system-design)

目的: 根据需求和数据,有计划地扩展,而不是被动响应——只有在估算结果证明有必要时才增加基础设施。

简要说明(后备方案): 从需求出发,而不是从解决方案出发。粗略估算:QPS = 日活跃用户数 × 每日操作次数 ÷ 86,400,峰值为平均值的 2–5 倍;存储量 = 每日记录数 × 单条大小 × 保留期限。按顺序扩展:先纵向扩展,然后针对读密集型路径使用缓存(旁路缓存模式,设置 TTL 并明确失效策略),再添加只读副本,最后才考虑分片。使用消息队列,将耗时工作与请求路径解耦。优先采用成熟设计(限流器 → 令牌桶,返回 429 Retry-After)。

调用: 根据接收信息中的负载实际情况,使用 system-design 技能。询问平均和峰值 QPS、年度存储量、哪个组件会最先成为瓶颈,以及按优先级排列的缓存/队列/副本方案,避免过度设计。

与用户共同决定: 哪些扩展措施现在实施,哪些推迟;决定应结合实际数据(用户数为 50 时,不要按 50k 用户的规模建设),并指出要迁移到消息队列后的第一个慢速工作负载(如果有)。

产物: 在 docs/ARCHITECTURE.md 的 ## System Context 中补充实际负载情况和粗略估算数据;在 docs/RELIABILITY.md 的 ## Query & Resource Findings 中补充无界查询和瓶颈。更新跟踪表。

完成条件: 记录 QPS 和存储量数据,指出第一个瓶颈,并且每项扩展措施都已实施或推迟,同时记录触发条件对应的数据。

阶段 9 — 正确设计数据层(ddia-systems)

目的: 保护那些比代码存在更久的数据——确保并发情况下的正确性,并根据需求而非习惯选择数据存储。

简要说明(后备方案): 数据比代码存在得更久。大多数数据库默认采用读已提交或快照隔离,而非可串行化隔离——简单的先读后写会引发写偏斜(两个请求同时出售最后一件商品)。应通过 SELECT ... FOR UPDATE 或可串行化事务显式解决,并了解实际采用的默认隔离级别。一旦存在副本,复制延迟意味着必须认真处理读己之写和单调读。数据模型应匹配访问模式;多模型持久化通常是正确选择;应将权威数据与派生数据分开(CDC/事件溯源),而不是采用双写。

调用: 根据接收信息中的数据库以及阶段 8 制定的副本方案,使用 ddia-systems 技能。要求它找出容易发生写偏斜的先读后写路径,说明实际的默认隔离级别及其异常,并修复存在风险的路径。

与用户共同决定: 哪些路径需要加锁,哪些需要采用可串行化事务;以及新的工作负载(搜索、信息流)是否值得引入第二个由 CDC 保持同步的数据存储。

产物: 在 docs/ARCHITECTURE.md 的 ## Data & Storage Decisions 中补充隔离级别、加锁路径以及多模型/派生数据的选择;在 ## Decision Log 中记录决策理由。更新跟踪表。

完成条件: 已记录默认隔离级别,每条容易发生写偏斜的路径都已加锁或改为可串行化,并且每个新增数据存储都有明确的同步机制。

可选阶段

技能添加时机产物
domain-driven-design代码缺乏领域语言,导致业务逻辑纠缠不清时扩展 docs/ARCHITECTURE.md(## Bounded Contexts & Context Map、## Domain Glossary (Ubiquitous Language))

可选阶段遵循相同的执行规则——加载并使用每项列出的技能,方式与核心阶段完全相同;在「添加时机」条件首次成立时插入——本例中,应在边界建立后立即插入,即阶段 5 之后。

常见错误

错误修正方法
还没写一个测试就开始清理代码先在 Phase 1 (working-with-legacy-code) 中编写特征测试,锁定现有行为;这道安全网是后续每个阶段的前提。
任由 Agent 把代码“模块化”成一大群细小的类应用 software-design-philosophy 的深模块规则——合并那些总是一起使用的浅类;减少接口,而不是增加接口。
调用外部 API 时不设置超时在 Phase 7 (release-it) 中,为每个出站调用添加连接和读取超时,并为关键依赖添加断路器。
还没评估需求就开始扩展规模先进行粗略估算 (system-design);通常,数字会表明缓存和只读副本足以支撑数年的增长。
把微服务误当成架构先在服务内部应用依赖规则 (clean-architecture);共享同一数据模型的服务就是分布式单体。
认为数据库是可串行化的检查实际的默认隔离级别,并锁定先读后写的路径 (ddia-systems)——写偏差能通过所有单用户测试。

完成本次旅程

按顺序推进,不要一次性完成:Phase 1-3(健壮性、可读性、重构)应在真实用户到来之前完成;在代码库规模再次翻倍之前,Phase 5 的边界划分最能发挥作用;上线前加固 Phase 7(即使流量很低,超时和断路器也不可或缺);让 Phase 8-9 跟随实际增长数据推进。

退出检查清单——每一项都对应一份产物:

  • 业务规则都有无需数据库或框架即可运行的测试(已完成变更模块的 TESTING.md Safety Net Map)。
  • 每个出站调用都有超时,关键依赖都有断路器,并已接入深度健康检查和 RED 指标,且配置了基于症状的告警(RELIABILITY.md Integration-Point Audit 无待处理项,Health Checks & Metrics 已填写)。
  • 符合依赖规则——业务逻辑不导入任何框架或 ORM(ARCHITECTURE.md Layer Map 中的违规项均已关闭)。
  • 已知数据库隔离级别,并已锁定先读后写的路径(ARCHITECTURE.md Data & Storage Decisions)。
  • 不再有未跟踪的临时方案;每个延期事项都作为 Debt Ledger 条目记录,并注明优先级(TECH-DEBT.md)。

关闭跟踪器:每个阶段都标记为 done 或 skipped: reason,并将剩余的 Next Actions 记入 TECH-DEBT.md Debt Ledger,确保没有遗漏。然后继续前进:如果代码库已经老旧且庞大,而不是年轻又杂乱,就继续使用 remove-technical-debt 技能;如果下一个系统需要从第一天起就精心规划结构,就继续使用 design-code-architecture 技能。

评论

支持 Markdown