mcpField
M
maintainable-code

maintainable-code

github.com/jpcaparas开发5686 次安装1 天前更新
代码仓库

关于 maintainable-code

maintainable-code 是供编码 Agent 处理源代码任务的 Skill,涵盖可维护性、生产环境韧性与可测试性。它提供按任务情境选择的设计指导,强调小幅修改、明确边界和适当验证。

主要功能

  1. 01指导清晰的代码结构与命名
  2. 02为后台任务和分布式流程提供韧性指导
  3. 03建议可替换依赖边界与测试替身
  4. 04按实现、重构、评审等任务提供决策路径
  5. 05强调适当的验证与可恢复性

适用场景

  1. 01实现功能或修复缺陷时遵循本地架构
  2. 02重构时分步保留现有行为
  3. 03为任务队列或外部 API 设计故障处理
  4. 04评审代码中的可测试性与维护风险

安装

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

$npx skills add https://github.com/jpcaparas/skills --skill maintainable-code

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

AGENTS.md
metadata.json
README.md
skill-card.prompt.md
agents/
.gitkeep
assets/
.gitkeep
evals/
evals.json
evals/files/
runtime-defaults.ts
references/
commenting.md
decomposition.md
dependency-boundaries.md
distributed-systems.md
gotchas.md
guardrails-and-quality-gates.md
implementation-plans.md
jobs-and-queues.md
observability.md
principles.md
resilience.md
review-rubric.md
source-notes.md
test-doubles.md
scripts/
analyze_app_resilience.py
analyze_maintainability.py
analyze_mockability.py
test_skill.py
validate.py
templates/
maintainability-review.md
mockability-review.md
resilience-review.md

详细介绍

maintainable-code

编写、编辑和审查代码,让人类维护者无需破解晦涩技巧,就能理解、测试并在日后修改代码;无需连接调试器,就能排查生产故障;并能在测试中替换依赖,而不扭曲生产环境的设计。

这项技能整合了过去彼此独立的三项关注点:通用可维护性、生产应用韧性(作业、队列、重试、可观测性)以及可模拟性(依赖边界和测试替身)。

被动触发

只要任务涉及源代码,就在后台加载此技能,即使用户没有提及可维护性也一样。这包括面向生产环境的运行时行为,例如后台工作器、定时任务、Webhook、支付流程、导入/导出、通知、API 集成、数据库状态转换、缓存、文件上传、队列、cron、身份验证/会话流程、日志记录、跟踪、告警或可靠性行为。也包括任何依赖协作者、I/O、时间、随机性、持久化、配置、网络调用、SDK、进程状态或框架上下文的行为。

小型编辑要保持轻量:默默应用核心规则,只提及会影响最终实现的决策。如果要添加或修改测试,且 {{ skill:maintainable-tests }} 可用,也加载它。

决策树

当核心规则或本地证据不足以指导不明显的设计决策时,使用以下路径。仅仅主题匹配,并不意味着必须阅读一组参考资料。

  • 实现新功能或修复错误: 优先匹配本地架构。让改动保持小巧、类型明确、命名直白,并通过范围最窄且有意义的验证。面向具备扎实基础知识、但对本系统背景了解不完整的未来维护者编写代码。

  • 重构现有代码: 借助充分的现有覆盖测试,分小步保留行为。边界不清时参考 references/decomposition.md;纠缠的副作用妨碍安全验证时,参考 references/dependency-boundaries.md。仅在必要时添加特征化测试或替换点。

  • 审查代码: 审查发现必须引用具体代码,并说明对维护者的影响。严重程度或范围难以判断时,参考 references/review-rubric.md;需要解释不明显的运维背景时,参考 references/commenting.md。

  • 为其他 Agent 或团队成员编写计划: 清楚说明目标、范围和验证方式,不依赖会话上下文。交接复杂度较高时参考 references/implementation-plans.md;需要保留不明显的理由时参考 references/commenting.md。说明会影响工作的失败处理和依赖决策,但不必固定章节数量。

  • 编写运维代码、CI 工作流、迁移、生成的胶水代码或密集命令流水线: 对不明显的意图、不变量和外部约束添加注释。注释放置位置或说明方式不明确时,参考 references/commenting.md;不要赘述显而易见的代码。

  • 添加后台作业、队列、cron、Webhook、导入/导出、电子邮件、支付捕获或通知: 针对适用的故障模式,确保安全处理重复请求、限制工作量并具备恢复能力。复用已验证的框架机制或现有保障。仍有未解决风险时,参考 references/resilience.md 或 references/jobs-and-queues.md,不要默认添加额外机制。

  • 涉及多个服务、外部 API、事件发布、分布式数据变更或异步工作流: 限制等待和重试,防止有害的重复操作,并考虑部分完成的情况。所有权或保障机制不明确时,参考 references/distributed-systems.md;outbox/inbox、对账和补偿都是可选方案,并非通用必备方案。

  • 添加日志记录、指标、追踪、告警、仪表板或事件诊断: 使用能够说明用户影响和恢复情况的现有信号。当诊断缺口确实需要埋点时,查阅 references/observability.md,不要为每次编辑都添加遥测。

  • 选择严格的运行时默认值、按环境划分的安全护栏、兼容性策略或仓库质量门禁: 区分已配置、适用、已选定和成功应用的状态;将危险操作设为选择加入;分阶段引入会改变行为的默认值;并验证所声明的兼容范围。需要进一步设计策略时,查阅 references/guardrails-and-quality-gates.md。

  • 添加调用依赖项的代码,或使难以测试的代码变得可替换: 将外部集成置于精简的端口/适配器或等效的本地边界之后;将领域策略与构造、配置和传输分开。在边界处控制时间、随机性和环境读取。现有接缝不够用时,查阅 references/dependency-boundaries.md。

  • 选择如何在测试中替换依赖项: 优先选择能够证明行为且能力最弱的替身:固定答案用桩,逼真的内存行为用伪实现,交互契约用模拟对象或间谍对象。替换方案或适配器漂移存在不明显的风险时,查阅 references/test-doubles.md。

  • 不确定某种设计是否易于维护: 选择能减少后续读者负担、又不会隐藏重要领域行为的方案。查阅 references/principles.md,或针对具体未解决风险的参考文档。

  • 用户要求巧妙、精简或广泛抽象: 按照用户要求的取舍处理,无需让他们重新说明。保持正确性、类型和安全性;在可行时限制巧妙实现的范围,并且只说明影响重大的维护成本。

快速参考

情况默认操作
新代码遵循现有的本地模式,使用精确名称、强类型和直接控制流
重复逻辑只有当重复内容有相同的变更原因时才提取
复杂分支尽早规范化输入,防范无效情况,然后让正常路径一目了然
运维脚本或 CI YAML为每个阶段命名,并注释不明显的命令组、外部 API 特性、制品契约和故障处理
大型函数按稳定职责拆分,而不是按任意行数拆分
新抽象至少要求两个真实调用点,或一个需要保护的明确边界
隐式框架行为如果兼容性证据支持,优先采用失败时明确报错或不可变的默认值;将开关视为行为迁移
危险或会覆盖数据的操作默认关闭;交互式工具使用确认机制,程序化契约则明确意图、范围、前置条件、幂等性和恢复方式
质量策略提供一个检查模式命令,组合已配置的各层:格式化/代码检查、分析、行为测试;只有存在相应工具时才运行安全的重构试运行
版本兼容性使用技术栈支持的接缝——运行时能力检查、版本化适配器、构建标志或条件编译——并测试最低支持组合和当前版本
注释在最小的有效范围内解释不明显的理由或约束;仅在有助于说明流程时使用 ASCII 图示
计划提供足够的范围、本地上下文和验证证据,以达成所请求的结果

弹性:

仅在存在相应风险时应用这些做法。只要现有数据库、提供商、框架和平台的保证覆盖了该操作的范围和配置,就应将其视为有效保障;仅针对缺口添加机制。

情况默认操作
浏览器重复提交、Webhook 重放、重试或工作进程重启通过天然幂等性、唯一性约束或持久化意图键,防止有害的重复影响
十位用户触发同一个高开销任务原子地合并相同且已授权的意图,并限制并发执行;复用现有任务状态
任务在 pending 或 running 状态停留过久确保能够检测到过期工作,并安全恢复或将其置为终态;现有队列恢复机制足够时优先使用
远程 API 调用确保连接等待和请求等待时间受限;如需重试,应对错误分类,并采用有界且安全的退避策略
队列负载激增使用现有容量控制或反压机制限制资源使用并保护共享依赖项
数据库写入后的副作用确保不会丢失必要的交接;使用事务机制、发件箱或其他经过验证的恢复路径
多步骤分布式工作流明确状态和部分完成结果;必要时进行协调或补偿
部分服务中断优先降低低价值功能的服务能力,并保障用户的核心任务
记录请求/任务进度包含识别工作、结果和恢复决策所需的安全上下文
指标衡量相关的用户健康状况和容量风险;添加计数器前先复用现有指标
跟踪对无法解释的跨边界延迟或故障添加跨度,而非对微小的本地辅助函数添加跨度
告警仅在影响用户或自动化处理已耗尽时触发页面通知;只有在有助于诊断或采取行动时才使用非页面通知信号

可测试性:

情况默认操作
直接访问网络、数据库、文件、时钟、随机数、环境变量或队列将其保留在外层边界,或通过小型契约传入
业务规则与 SDK 调用混杂将规则提取为确定性函数,并注入面向 SDK 的适配器
构造函数在内部创建客户端除非本地惯例另有规定,否则从调用方接收客户端、工厂或配置
静态/全局单例依赖项优先在边界使用显式协作者、上下文对象或精简封装
框架处理程序在处理程序中保留解析和响应格式化;将策略移至可调用服务/函数
测试需要真实的外部服务在连接共享基础设施前,使用伪对象、存根、契约测试或本地测试容器
接口看起来有用仅在确有替换需求、需要保护边界或语言惯例要求时添加
评审中发现不可模拟的代码指出隐藏依赖,并展示最小修复路径,不要一概要求重写
测试复用足够的覆盖;在进行高风险变更前,补足行为或回归测试缺口
评审优先关注缺陷、令人困惑的边界、缺失的测试以及未来变更风险

核心规则

清晰性与结构:

  1. 优先考虑下一位胜任的维护者,而不是展示高深技巧。假设他们具备扎实的基础,但不了解你脑海中的系统历史。
  2. 在命名、提取或引入模式之前,先阅读周边代码。
  3. 让行为贴近能够解释它的数据和策略。
  4. 优先使用朴素、类型明确的数据结构,而不是字符串、杂乱的选项集合或隐藏约定。
  5. 让函数保持在单一且稳定的抽象层级:编排、策略、转换或 I/O。
  6. 在语言和代码库支持的情况下,让无效状态难以表示。
  7. 只对名称和结构无法表达的非显而易见的理由、不变量或约束添加注释。将说明放在相关的类、方法、属性、分支或代码块旁;不要添加需要用户删除的评论。
  8. 对不确定、与版本相关或影响重大的语言/框架声明,依据项目实际技术栈的官方资料进行核实。在有助于核实声明或用户提出要求时,附上来源链接;默认不要研究已知基础知识,也不要夸大文档所述行为。
  9. 当紧凑的 ASCII 图示有助于说明非显而易见的数据流、状态转换、队列、重试、所有权或边界跨越时,将其放在注释或文档块中。确保图示与说明一致;如果代码变更导致其中任一内容过时,立即更新两者。
  10. 对非平凡行为进行重构时,做好充分验证;复用现有测试,仅针对覆盖缺口添加特征测试。
  11. 如果你有意保留复杂性,请在最终答复中说明其中影响重大的权衡。
  12. 在本地兼容性允许的范围内,从类型、分析、框架行为和边界验证等层面逐步提高严格性。启用会改变行为的严格模式之前,先添加迁移覆盖。
  13. 在入口处分开处理取消、可选能力缺失、操作失败和意外缺陷。保留可采取行动的原因,不要把所有结果都折叠成 false、null 或一个通用错误。
  14. 默认关闭危险能力。强制标志可以跳过交互,但不得绕过授权、验证、不变量或恢复检查。

生产行为与恢复:

  1. 将重试、重复投递、并发、延迟、部分故障、部署重启和过期状态视为正常输入,而非罕见意外。
  2. 当重复操作可能损害正确性或浪费资源时,应区分新的意图与重放。天然幂等性或现有身份标识可能已经足够;没有必要时,不要持久化新的工作记录。
  3. 对非平凡的持久化工作,明确允许的状态转换、所有权、终止结果,以及脱离卡死状态的有界路径。只使用工作流所需的状态和字段。
  4. 确保相关故障都有安全的恢复方式或明确的终止结果。优先使用现有的自动恢复机制;仅在现有机制未覆盖风险时,才添加重试、清理器、协调机制或死信处理。
  5. 限制资源使用,避免单个工作流耗尽共享容量。现有并发限制、租约、速率限制或背压可能已经足够;队列和隔离舱并非必须添加。
  6. 在能够实施保障的边界处,防止有害的重复副作用。添加去重机制之前,先核实天然幂等性、数据库约束、提供方密钥或其他现有保障的适用范围。
  7. 确保跨进程、网络、队列、数据库或提供方边界的等待都有时限。遵守现有的有效截止时间,而不是添加相互竞争的超时层;确保不确定的结果能够安全恢复。
  8. 使用足够的可观测性来诊断相关的用户健康和容量故障;延迟、流量、错误和饱和度是有用的排查起点,而非遥测配额。绝不记录机密、令牌、原始支付详情、完整个人身份信息(PII)、会话 Cookie 或提供方凭据。

可测试性: 23. 将决策与副作用分离。领域策略应能够在不依赖真实网络、时钟、文件、数据库、队列或随机性的情况下进行测试。 24. 在模块、构造函数、函数、处理程序或上下文边界处明确协作者,并优先采用范围精简的契约,描述调用方需要什么,而非依赖项能做的一切。 25. 对有状态行为使用伪对象,对固定响应使用存根,对重要交互使用 mock/spy,并为适配器编写契约测试。代码可被 mock,不等于测试中要大量使用 mock。 26. 不要添加只有想象中的替代实现的抽象,也不要仅仅为了让测试能够访问私有内部实现而将其暴露出来。只有一个清晰替换点的简单代码,胜过层层叠加却无人使用的接口。

可维护性门槛

完成代码更改前,先在心中检查此门槛,并在条件允许时使用本地工具检查:

门槛通过条件
意图读者无需逐行阅读,就能从名称和结构看出代码的作用
范围更改仅涉及责任范围最小的部分,并避免无关的清理工作
边界I/O、编排、领域策略和呈现没有在无充分理由的情况下纠缠在一起
类型数据契约足够明确,能让编辑器、编译器或测试发现误用
注释密集或令人意外的代码在合适层级(类/模块、方法/函数、属性/字段,以及适用时的本地代码块)配有易于理解的注释/文档块;任何 ASCII 图示都与文字说明和代码一致
测试最可能出现的回归有针对性测试,或明确说明了验证缺口
错误在能够补充有用上下文的边界处处理失败情况
默认值严格性、不可变性和环境门控均有明确说明;适当情况下可配置,并有兼容性证据支持采用
自动化本地和 CI 检查模式执行相同的版本化质量策略,并覆盖受支持的依赖范围
交接最终回复列出关键文件、已运行的验证,以及任何剩余风险

自愈门槛

对于生产运行时更改,请检查下方适用的保障措施。现有机制足够时应予以接受;此表并不要求添加每种状态、信号或恢复组件。

门槛通过条件
身份通过天然幂等性、持久化意图标识、唯一性或其他经过验证的边界保障,防止产生有害的重复副作用
状态非简单工作对实际使用的状态有明确的转换、终止和恢复行为
并发共享资源设有唯一性约束、锁、租约、速率限制或工作进程上限
时间远程调用、任务、锁和待处理状态均设有超时或过期时间
重试对可重试错误进行分类,限制重试次数,加入抖动,并确保重复副作用不会造成问题
恢复对卡住、部分完成和失败的状态,可以重试、协调、重新触发或终止,无需开发者手动编辑数据
降级可选依赖失败时,应用仍能保障用户最重要的任务
可观测性可用信号能够说明相关的用户影响、工作标识、失败情况和恢复结果
告警自动化耗尽或用户受到影响时触发告警,而非每次出现预期的瞬时故障时都触发
测试对最可能发生的生产故障有针对性测试、模拟,或明确说明验证缺口

可模拟性检查

完成涉及依赖或副作用的更改前,也请检查:

检查项通过条件
依赖归属读者能看出由谁创建每个外部依赖,以及由谁使用它
替换能力测试可以替换缓慢、不稳定、昂贵或不可逆的协作者,而无需更改生产代码
确定性时间、随机性以及进程/环境读取都在边界处受到控制
契约规模接口或协议只包含调用方实际需要的操作
生产环境接线正常运行路径仍然简单直接且易于追踪
测试意图测试断言行为和重要契约,而非偶然的调用顺序
失败模式无需引发真实副作用,即可模拟依赖的错误路径
范围此更改提升了可测试性,且没有无关重写或框架变动

工作流程

根据更改规模调整此流程。小型编辑只需聚焦上下文并进行验证,无需撰写背景说明、失败图谱或多章节报告。

  1. 先进行侦察。 阅读本地指南、受影响的代码、相关契约以及正确执行所需的测试。只有在更改依赖于更广泛的接线或配置时,才检查这些内容。

  2. 明确维护者的需求。 理解新增或变更的职责。只有在有助于消除范围或交接歧义时,才将其写下来。

  3. 绘制失败图谱。 对于实质性的运行时风险,考虑相关的重复输入、并发、超时、崩溃、过期状态和部分完成情况。确定现有责任方或缺失的保障;只记录实现或评审所需的决策。

  4. 识别硬依赖。 检查受影响的 I/O、时间、随机性、配置、SDK 和全局状态边界。重用安全的替换点;不要盘点无关依赖。

  5. 选择适合代码库的最简单边界。 优先使用现有模块和辅助工具。只有在新抽象能够保护一个真实的变更维度时才添加它。优先采用局部约束和现有框架原语;只有在失败模式足够真实、确有必要时,才添加队列、锁、发件箱表、断路器或看门狗。

  6. 分小步实现。 让差异易于评审。避免顺手格式化、无关迁移、风格变动,以及仅为测试而扭曲代码的做法,例如添加公共 setter 或宽泛的服务定位器。

  7. 验证行为、失败行为和可读性。 运行相关测试和仓库要求的检查。复用足够的覆盖,并补足影响重大的缺口。像评审陌生人的代码那样重新阅读差异;仅在缺少说明会导致非显而易见的理由遗失时才添加注释。

  8. 清楚报告。 报告结果、验证情况和剩余风险。只有在设计决策影响重大时才说明;省略空章节和常规流程叙述。

可选辅助工具

将这些辅助工具用作快速代码异味扫描器,而非最终结论:

python3 scripts/analyze_maintainability.py /path/to/project
python3 scripts/analyze_maintainability.py /path/to/project --json
python3 scripts/analyze_app_resilience.py /path/to/project
python3 scripts/analyze_app_resilience.py /path/to/project --json
python3 scripts/analyze_mockability.py /path/to/project
python3 scripts/analyze_mockability.py /path/to/project --json
  • analyze_maintainability.py 会标记大型函数、含糊的名称、薄弱的类型、注释债务和 TODO 漂移。函数范围和函数名称检查仅使用 Python 的 AST;对于其他所有宣称支持的语言,都会有意省略函数调用和函数形式的检查,而不是猜测;薄弱类型信号仍仅限于 Python 注解和保守的 TypeScript 类型位置。
  • analyze_app_resilience.py 会标记可能缺少幂等性、重试/退避不足、外部调用没有明显超时、日志上下文不足、吞掉错误,以及没有恢复机制的待处理状态。
  • analyze_mockability.py 会标记可能硬编码的副作用和全局变量,供人工或 Agent 检查。

将它们的输出视为供人工审查的提示。扫描结果安静并不能证明代码优质、健壮或易于模拟;扫描结果嘈杂也不能证明代码有问题。如需更深入的审查,可选择改用 templates/maintainability-review.md、templates/resilience-review.md 或 templates/mockability-review.md;不要求采用其格式和章节。

指导不再适用时

相比打包提供的模式,应优先遵循已验证的本地不变量和符合习惯用法的框架行为。当它们与建议冲突或建议不起作用时,应检查已安装版本以及相关官方文档或可信的一手资料。说明尚未解决的限制。提出修正或删除规范技能的建议,并附上冲突规则、来源/版本,以及具体的回归问题或反例;不要悄悄编辑已安装的副本,也不要将发现的问题转变为无关的重构。

阅读指南

需求阅读
默认做法背后的原则references/principles.md
拆分函数、模块和职责references/decomposition.md
有用的开发者注释和语言特定示例references/commenting.md
可维护性、健壮性和可测试性的审查发现及严重程度排序references/review-rubric.md
为其他 Agent 或团队成员制定计划references/implementation-plans.md
严格默认设置、危险副作用、兼容性和可执行质量门禁references/guardrails-and-quality-gates.md
自愈应用原则、故障映射、工作身份和状态机references/resilience.md
作业、队列、webhook、cron、卡住的工作和重复工作references/jobs-and-queues.md
重试、超时、幂等 API、outbox/inbox、saga 和协调references/distributed-systems.md
日志、指标、追踪、告警和仪表板references/observability.md
隔离依赖项、副作用、时间、随机性和配置references/dependency-boundaries.md
选择 mock、stub、fake、spy 和契约测试references/test-doubles.md
三类关注点中常见的陷阱和反模式references/gotchas.md
来源影响和改编说明references/source-notes.md

注意事项

  1. 小函数并不一定更易维护。过度拆分可能和冗长函数一样,让整体逻辑难以理解。
  2. DRY 不是合并碰巧相似代码的命令。共享代码应有共同的变更原因。
  3. “整洁”的代码仍可能有误。先保留行为并验证,再润色结构。
  4. 通用抽象往往比明确的重复代码更难长期维护。等出现真实差异后再抽象。
  5. 注释无法补救误导性的名称或混乱的边界。应先重命名或重构。
  6. Agent 生成的代码常常能通过测试,却不符合项目本地惯例。应用通用建议前,先遵循代码仓库的规范。
  7. 更严格的默认设置即使看起来只是配置,也可能改变行为并造成破坏性影响。先盘点受影响的路径,再分阶段推出。
  8. 单元测试全部通过,也不能代替代码仓库配置的格式化程序/代码检查器检查、分析、兼容性测试,或可用时安全的代码自动修改试运行;这些检查各自能发现不同的维护问题。
  9. 重试不安全的操作,可能造成你原本想修复的故障。添加重试前,先确保操作具备幂等性。
  10. 如果锁在工作进程完成前就过期,仅保证任务唯一还不够。应协调锁 TTL、任务超时、可见性超时和重试窗口。
  11. pending 不是恢复策略。每个非终止状态都需要明确的负责人和过期状态处理路径。
  12. 死信队列不是垃圾桶。它们需要告警、检查字段、重新投递规则,以及有害消息处理策略。
  13. 可观测性并非越多越好。高基数、包含机密信息或无人查询的遥测数据会增加成本和风险,却无法改善故障恢复。
  14. 为每个类都定义接口会让代码更难浏览。只在替换或所有权边界确实存在时添加契约。
  15. 对时钟、随机数生成器、环境变量和全局上下文的隐式读取,造成的测试故障往往不亚于网络调用。
  16. Monkeypatching 有时很有用,但不应成为替换核心生产代码中协作者的唯一方式。

评论

支持 Markdown