name: sandi-metz-rules description: 当用户请求代码审查、重构或 Ruby 代码库的代码质量改进时,应使用此技能。应用 Sandi Metz 的四条规则来编写可维护的面向对象代码 - 类不超过 100 行,方法不超过 5 行,参数不超过 4 个,控制器只实例化一个对象。当用户提到 “Sandi Metz”、“代码质量”、“重构” 或审查 Ruby 代码的可维护性时使用。
Sandi Metz 规则
概述
此技能帮助将 Sandi Metz 的四条规则应用于 Ruby 代码库,以编写可维护的面向对象代码。这些规则是启发式方法,鼓励良好的设计实践,使代码更易于理解、测试和维护。
四条规则
- 类代码长度不超过 100 行
- 方法代码长度不超过 5 行
- 方法参数不超过 4 个
- 控制器只能实例化一个对象
何时使用此技能
在以下情况下应用此技能:
- 用户明确请求应用 Sandi Metz 的规则
- 审查 Ruby 代码的可维护性和代码质量
- 重构现有 Ruby 代码以改进设计
- 用户询问“代码异味”或改进面向对象设计
- 分析 Ruby 代码的复杂性或可维护性问题
- 用户提及“POODR”或引用 Sandi Metz 的工作
代码审查工作流程
1. 分析代码
根据 Sandi Metz 的规则审查代码时:
阅读参考文档: 首先,加载详细的规则文档:
阅读 references/rules.md
准确测量:
- 对于类:计算实际代码行数(排除空行、注释、类定义和
end语句) - 对于方法:计算实际代码行数(排除空行、注释、方法定义和
end语句) - 对于参数:计算所有显式参数,包括关键字参数(但不包括
&block) - 对于控制器:计算每个动作中的对象实例化次数(不包括查找现有对象)
识别违规: 扫描代码库以识别每条规则的违规情况。使用 grep 或文件搜索查找类和方法,然后系统分析。
2. 优先处理问题
并非所有违规都同等重要:
高优先级:
- 类超过 200 行(严重违规)
- 方法超过 10 行(严重违规)
- 方法有 6 个或更多参数
- 控制器包含复杂业务逻辑
中优先级:
- 类在 100-200 行之间
- 方法在 5-10 行之间
- 方法有 5 个参数
低优先级:
- 边界情况(例如,6 行的方法)
- 测试文件、配置文件或 DSL 中的违规
3. 建议具体重构方法
针对每个违规,提供具体的重构策略:
长类:
- 将相关方法提取到新类中
- 使用单一职责原则识别独立职责
- 使用组合或模块共享行为
- 应用模式:策略、装饰器、命令、外观
长方法:
- 提取子方法并使用描述性名称
- 用多态替换条件语句
- 使用守卫子句减少嵌套
- 应用组合方法模式(保持方法在一个抽象层次)
- 将复杂表达式提取到命名良好的方法中
过多参数:
- 为相关参数引入参数对象
- 使用建造者模式进行复杂构建
- 用方法调用替换参数(使用实例变量)
- 考虑方法是否应属于其他类
臃肿控制器:
- 提取服务对象或用例
- 应用命令或交互器模式
- 创建外观对象进行复杂编排
- 将业务逻辑移到领域层
4. 提供代码示例
建议重构时:
- 显示重构前后的代码示例
- 解释重构版本的优势
- 命名使用的任何模式
- 突出更改如何提高可测试性和清晰度
5. 考虑上下文
记住,规则在有充分理由时可以打破:
- 配置文件(例如 routes.rb)
- 测试文件(尽管仍应可读)
- DSL 定义
- 生成的代码或数据库迁移
- 遵循规则会使代码不够清晰时
始终注意何时违规可接受,并解释原因。
使用模式
模式 1:完整代码库审查
审查整个代码库时:
- 使用 glob 模式搜索 Ruby 文件
- 首先识别最大的类和方法
- 检查控制器中的业务逻辑
- 按严重性优先处理违规
- 提供发现摘要,包括具体文件位置和行号
- 为最关键问题建议重构方法
模式 2:特定文件或类审查
审查特定文件时:
- 加载文件
- 测量每个类和方法
- 识别所有规则违规
- 提供带有代码示例的具体重构建议
- 解释每个建议更改的好处
模式 3:重构协助
主动重构代码时:
- 加载 references/rules.md 获取详细指导
- 应用参考中的具体重构模式
- 确保重构后代码遵循所有四条规则
- 验证测试是否通过
- 解释所做的设计改进
代码计数规则
使用这些精确计数规则确保一致性:
类行数:
class MyClass # 不计数
def method # 计数:1
body # 计数:2
end # 不计数
end # 不计数
方法行数:
def my_method # 不计数
line_1 # 计数:1
line_2 # 计数:2
# 不计数(空行)
# comment # 不计数
line_3 # 计数:3
end # 不计数
参数:
def method(a, b, c, d) # 4 参数 - 通过
def method(a, b, c, d, e) # 5 参数 - 违规
def method(a:, b:, c:, d:) # 4 参数 - 通过
def method(a, b = nil, c = {}) # 3 参数 - 通过(默认值仍计数)
def method(a, *rest) # 2 参数 - 通过
def method(a, &block) # 1 参数(块不计数)
自动化
建议使用静态分析工具强制执行这些规则:
- RuboCop: 配置
Metrics/MethodLength、Metrics/ClassLength、Metrics/ParameterLists - Reek: 检测代码异味,包括 LongMethod、LargeClass、LongParameterList
- flog: 测量方法复杂度
- flay: 检测代码重复
RuboCop 配置示例:
Metrics/ClassLength:
Max: 100
Metrics/MethodLength:
Max: 5
Metrics/ParameterLists:
Max: 4
MaxOptionalParameters: 3
资源
此技能包含一个全面的参考文档,其中包含:
- 每条规则的详细解释
- 原理和好处
- 常见违规及其原因
- 带示例的具体重构策略
- 何时打破规则的指导
- 相关设计原则和模式
进行详细代码分析或解释重构方法时,加载此参考:
阅读 references/rules.md