mcpField
U
unsmell

unsmell

github.com/dobroslavradosavljevic开发354 次安装6 天前更新
代码仓库

关于 unsmell

unsmell 是面向开发者的代码整理技能,旨在改善可维护性并保持预期行为不变。它依据范围检查和具体证据,指导局部或全仓库重构。

主要功能

  1. 01按范围检查代码库
  2. 02基于证据分析代码异味
  3. 03保持行为的重构流程
  4. 04TypeScript 类型安全审查
  5. 05验证并汇报完成情况

适用场景

  1. 01重构指定模块或功能
  2. 02检查代码库的可维护性问题
  3. 03整理 TypeScript 类型模型

安装

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

$npx skills add https://github.com/dobroslavradosavljevic/skills --skill unsmell

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

附带文件agents/openai.yaml

详细介绍

Unsmell

在不改变预期行为的前提下提升可维护性。除非用户指定目标,否则应检查整个仓库;如果用户指定了目标,只修改该范围以及维持其正常运行所必需的最少依赖边。

核心规则

  • 先阅读仓库指南并了解惯例,再评判代码。
  • 除非用户授权,否则应保留公开行为、API、数据格式和兼容性。
  • 优先编写清晰、内聚的代码,而不是机械地缩减代码。
  • 不要把每一行重复代码、长名称、大文件或抽象缺失都视为缺陷。必须有具体的维护成本。
  • 如果现有的本地模式合理,就沿用它。不要引入相互竞争的架构。
  • 分阶段进行内聚的重构,确保每次改动便于审查。避免无关的格式变更和缺乏依据的重写。
  • 保留无关的用户改动。切勿仅因某段代码的用途不明显就将其删除。
  • 只有当依赖带来的价值明显超过其维护成本,且用户允许安装时,才添加依赖。
  • 在 TypeScript 中,应改进类型模型或缩小值的范围,而不是压制编译器。不要用隐藏的不健全性换取显式的类型错误。

确定范围

编辑前先对请求进行分类:

  • **全面 Unsmell:**检查完整的第一方代码库,但排除生成文件、供应商代码、构建产物、缓存、锁文件、快照和迁移文件,除非它们正是问题的来源。
  • **定向 Unsmell:**仅检查和编辑指定的文件、目录、模块、功能、代码异味类别或依赖路径。可跟踪目标范围外的引用以了解情况,但只有目标重构确有需要时才修改范围外的内容。

如果边界不明确,且会实质性影响改动范围,请提出一个聚焦的范围确认问题。否则,说明推断出的边界并继续处理。

工作流程

1. 梳理仓库结构

检查项目说明、清单、源码根目录、测试、生成代码标记、模块边界和可用的质量检查命令。了解项目主要语言和框架的惯例。

对于全面 Unsmell,应广泛搜索并优先检查热点。对于定向 Unsmell,应跟踪目标的调用方、导入、导出、测试和契约,同时避免不必要地扩大编辑范围。

2. 找出有证据支持的代码异味

检查以下问题:

  • 可能逐渐不一致的重复知识或行为,而非无害的结构相似。
  • 过长的函数、过大的模块、职责混杂和内聚性低。
  • 过深的条件分支、复杂的控制流、布尔标志控制的行为和隐藏的状态转换。
  • 基本类型滥用、牵一发而动全身的修改、功能嫉妒、抽象泄漏和不恰当的耦合。
  • 组合能力薄弱:掩盖行为的继承或包装器、职责过多的组件、属性逐层传递,以及与领域逻辑混杂的编排逻辑。
  • 已通过引用关系和运行时或静态证据确认的无用、不可达、过时或冗余代码。
  • 误导性、不一致、过长或过度缩写的名称。
  • 目录层级过深、路径片段冗余和所有权边界不清晰。
  • 不一致的错误处理、资源清理、异步控制流和重复验证。
  • 有证据表明存在的重复高开销工作、意外的 N+1 行为、不必要的内存分配或可避免的渲染。
  • 存在重复、脆弱、与实现细节过度耦合的测试,或重构行为周围缺少的测试。
  • 下文所述的 TypeScript 逃生通道和类型模型异味。

记录每个候选问题的位置、具体成本、判断把握度、拟议改动、行为风险和受影响的依赖。不要为了凑数而硬找问题。

TypeScript 标准

在 TypeScript 代码库中,重点查找并解决以下问题:

  • 显式或隐式的 any、不安全地处理 unknown、as any、as unknown as T 等双重断言,以及仅用于强制兼容的类型断言。
  • 缺乏依据的非空断言、确定赋值断言、掩盖无效状态的可选链,以及隐藏缺失数据的回退值。
  • @ts-ignore、缺乏依据的 @ts-expect-error、已禁用的类型感知 lint 规则,以及用于掩盖源代码错误的生成声明。
  • 过于宽泛的类型,例如 object、Function、{}、不受约束的 Record<string, unknown>、宽松的字符串标识符,以及扩展到超出有效领域状态的联合类型。
  • 重复或矛盾的接口、可从源架构或 API 推导的手写类型,以及可能发生偏差的平行运行时定义和类型定义。
  • 可选属性过载、布尔状态组合,以及允许不可能状态的可空模型;在适当情况下,优先使用可辨识联合和显式状态转换。
  • 未能带来更强保证,却增加复杂度的泛型参数、条件类型、重载、工具类型和类型级抽象。
  • 不正确的变体、将可变数据暴露为只读或反之、未经检查的索引访问、不安全的键迭代,以及丢失的字面量类型。
  • 在不可信边界缺少运行时验证。静态类型无法验证网络、存储、环境、用户或已解析的数据。
  • 仅类型导入/导出错误、循环类型依赖、过大的 barrel 文件、意外的公共导出,以及泄漏内部实现的模块边界。
  • 隐藏拒绝的 Promise 和回调类型、被丢弃的 Promise、混杂的同步/异步契约,或比实际运行时行为更窄的错误类型。

修复根本的契约、数据模型、控制流收窄或边界验证。优先使用类型推导、satisfies、带有真实运行时检查的类型谓词、可辨识联合、穷尽性 never 检查,以及项目已使用的架构库所派生的类型。仅在不变量已得到证明但无法表达给编译器时使用断言;将断言范围保持在最小,并在不变量不明显时记录说明。

在有针对性的清理中,不要盲目启用更严格的编译器选项,因为这会扩大工作范围。在完整的 TypeScript 代码异味清理中,检查 tsconfig 的严格性;仅当产生的错误能在所请求的工作范围和兼容性约束内解决时,才建议或启用更严格的选项。

3. 排定优先级

按以下顺序安排工作:

  1. 正确性隐患和不安全的生命周期行为。
  2. 高成本的重复内容和边界问题。
  3. 经常变更或处于核心位置的代码中的复杂性。
  4. 组合和内聚性改进。
  5. 命名、文件组织和局部一致性。

优先选择能够消除根本原因并简化后续变更的改动。跳过价值较低的改动。

4. 分轮重构

每轮:

  1. 通过测试、契约、调用点和类型,确认当前行为。
  2. 做出能够解决代码异味的最小连贯结构性改动。
  3. 更新因移动或重命名而受影响的导入、导出、引用、测试、文档和配置。
  4. 运行范围最小且相关的现有验证。
  5. 重新检查结果,确认没有引入意外的间接层、语义变化或新的代码异味。

遵循以下默认原则:

  • 仅在共享代码代表一个稳定概念时才提取。与其使用错误的抽象,不如适当保留重复代码。
  • 按职责和变更频率拆分文件,而非依据任意的行数限制。
  • 围绕明确的输入和输出组合小单元。将编排与领域逻辑分开,并在边界处理副作用。
  • 如果有助于提升可读性,使用卫语句或专用辅助函数简化控制流。
  • 重命名应以清晰为目的,而非一味追求简短。含义准确的长名称可能优于含糊的短名称。
  • 仅当改善导航或归属关系带来的收益足以抵消导入改动时,才移动或重命名文件和文件夹。
  • 删除死代码前,先检查动态加载、反射、框架约定、脚本以及外部或公共消费者。
  • 保留解释原因、不变量或约束的注释;删除仅复述显而易见代码的注释。
  • 在 TypeScript 中,不要通过类型断言、抑制错误、放宽泛型、虚假默认值或扩大返回类型来解决错误。保留或增强有效的类型推断和公共契约。
5. 完成指定范围

对于全面消除代码异味,应重复执行发现和重构,直到第一方代码中不再存在高置信度或中等置信度、可采取行动的代码异味。不要只修复一个典型问题就停止。

对于定向消除代码异味,当指定目标已清理并通过验证时即可停止。不要顺带重构相邻区域。

6. 验证

根据改动范围,使用仓库现有的格式化工具、代码检查工具、类型检查器、测试、构建和架构检查。对于 TypeScript,运行不生成文件的项目类型检查;如果已配置类型感知代码检查,也应使用。先从小范围检查开始;对整个代码库进行重构后,再运行现有检查中范围最广且相关的检查。未经批准,不要安装缺失的工具。

如果无法运行验证,应准确说明未验证的内容及原因。若仍有排除区域、不确定的动态引用或既有检查失败,不要声称代码库已完全清理。

完成报告

总结以下内容:

  • 检查范围及排除项。
  • 已消除的根本代码异味,以及由此带来的结构改进。
  • 重要的重命名、移动、提取、合并和删除。
  • 已运行的验证及结果。
  • 遗留问题及各自原因:超出范围、置信度较低、需要改变行为、缺少前置条件或改动成本过高。

保持报告简洁。先说明已完成的成果,而不是逐项罗列所有改动。

评论

支持 Markdown