mcpField
S
simplifying-ruby-code

simplifying-ruby-code

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

关于 simplifying-ruby-code

用于 Ruby 代码审查与重构的 Skill,着重简化结构并保留有意义的行为。它提供替换冗余类、分离决策与 I/O,以及删除代码前检查调用方的模式。

主要功能

  1. 01将无状态命令对象改为函数
  2. 02按需选用 Hash、Struct 或 Data
  3. 03以组合替代深层继承
  4. 04分离纯决策与 I/O
  5. 05删除类前检查调用方
  6. 06指导审查和分步重构

适用场景

  1. 01审查 Ruby 代码的简化机会
  2. 02重构 Rails 服务对象和 Concern
  3. 03规划安全删除类
  4. 04分离计算与数据库或文件操作

安装

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

$npx skills add https://github.com/bostonaholic/skills --skill simplifying-ruby-code

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

包含的文件

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

agents/
openai.yaml
references/
review-findings.md
scripts/
find-callers.sh

详细介绍

简化 Ruby 代码

优先使用普通数据(Hash、Array、Struct、Data)和纯函数,而不是添加状态或行为的类。将决策与副作用分开:决策接收数据并返回数据;副作用执行 I/O(数据库、网络、文件、时间)。将它们放在不同的方法或模块中,这样测试决策时就不需要使用模拟对象。

用户要求审查时,只报告发现的问题,除非用户要求,否则不要编辑任何内容。通过编号(“Pattern 1”)或反模式名称引用相关模式。

模式

  1. 将命令对象改为模块函数。 如果某个类唯一的公共方法是 call、perform、run 或 execute,且除了构造函数参数外不持有任何内容,就可以改为直接调用或模块函数(UserCreator.new(params).call 可改为 User.create(params))。如果对象会在多次调用间持有状态、执行值得命名的多步骤算法,或必须序列化(例如后台任务),则保留对象。

  2. 将值对象改为 Data、Struct 或 Hash。 如果某个类只存储属性,包含手写的 initialize、读取器或 ==,且没有行为或验证:

    使用方式适用情况
    Hash临时数据、键不固定、JSON 输入或输出
    Struct属性固定,允许修改
    Data属性固定且不可变(检查 ruby -v >= 3.2)
    自定义类验证、不变量或真正的领域行为
  3. 将仅含类方法的类改为模块。 如果某个类从未被实例化,且只定义 self. 方法,就将其改为带有 module_function 的模块。

  4. 用组合替代深层继承。 继承层级超过 2 层(只计算项目自身的类;ApplicationRecord 或 StandardError 等框架和标准库基类不计入),或存在只有一个子类的抽象基类时,考虑改用组合。

  5. 缺少 Ruby 协议。 如果调用方需要手动拆解类似集合或值的类,而该类没有实现 each 和 Enumerable、to_h、<=> 和 Comparable,或 hash 和 eql?,就应补上相应协议。

  6. 混合决策与副作用。 如果测试需要大量模拟对象,或某个方法在同一段代码中计算并写入数据,就将计算提取为纯函数,并保留一个精简的方法来处理 I/O。

Rails 反模式

  • 服务对象: 单方法、无状态的服务应放在模型方法或模块函数中(模式 1)。复杂的编排可以保留为服务,但要将决策与副作用分开(模式 6)。任务是合理的对象,因为它们需要序列化。
  • 模型: ActiveRecord 模型应保留为类;将业务计算移入纯函数。
  • Concern: Concern 用于在多个模型间共享行为;如果某个 Concern 被用作单个模型的杂物箱,则应指出。
  • Helper: 仅用于视图格式化;业务规则应放在模块中。
  • 重新实现 Rails: 自定义 DSL 或基类若重复实现 scopes、validations、callbacks、enums 或 ActiveModel,就应避免。

纯 Ruby 反模式

  • 模板方法: 基类使用钩子方法,而代码块即可实现。
  • 构建器: 对于可通过关键字参数或 Data.define 直接构建的对象。
  • 包装器: 包装 Array、Hash、Set 或其他标准库类型,并转发大多数调用的类。
  • 元编程: 使用 method_missing、define_method 或 instance_eval 构建 DSL,而普通方法即可实现。
  • 依赖: 为了几行标准库代码而引入 gem。

在 gem 中,每个公共常量都是其他项目可能调用的 API。

移除或内联类之前

  • 对每个类运行 bash <skill-dir>/scripts/find-callers.sh <Constant> <project>。
  • 退出码为 0:处理每个 reference 和 require 命中项,并判断每个 dynamic 命中项构造出的名称是否可能是该类;这需要阅读代码,因此由你负责。
  • 退出码为 1:未找到调用方。退出码为 2:修正参数。退出码为 3:安装指定工具。退出码为 4:报告 grep 错误。
  • 控制器还会通过 config/routes.rb 中的 snake_case 资源名被调用;脚本不会搜索这种情况,因此请阅读该文件。
  • 在评审中,如果无法确认某个发现的调用方情况,请删除或降低该发现的优先级。

评审发现

报告评审结果时,请阅读评审发现,了解分组方式、每条发现包含的字段以及结尾顺序。

重构

先确保测试基线全部通过。一次应用一种模式,并在每次之后运行测试套件;如果失败,请先修复或回退该步骤,再继续。更新那些模拟已移除层的测试,让它们改为调用纯函数或直接 API。

评论

支持 Markdown