Reek 入门:Ruby 代码异味(Code Smell)检测实战
Reek 是 Ruby 代码异味检测工具,能发现过长方法、特性依恋、重复代码等结构性问题。本文讲解 Reek 的安装配置、常见异味解读与 CI 集成,帮你在问题恶化前拦截。
Reek 扫描 Ruby 代码中的"设计层面坏味道"——过长方法、过多参数、特性依恋(Feature Envy)、重复逻辑等,输出逐条报告。与 RuboCop(管风格)互补:一个管代码"长得好不好看",一个管代码"设计得健不健康",CI 里两个都该跑。
代码异味是什么
异味不是 bug——代码能跑,但结构上埋着维护地雷:方法长到读不完、一个类总去翻另一个类的内部、参数列表越来越长。这些问题单看无害,积累三年就是"没人敢改"的祖传代码。Reek 把 Martin Fowler《重构》里的异味目录变成了自动检测规则。
安装与基本用法
gem install reek
reek lib/ # 扫描目录
reek lib/user.rb # 扫描单文件
报告示例:
lib/report.rb -- 3 warnings:
[12]:Report#generate has approx 6 statements [TooManyStatements]
[18]:Report#generate refers to 'user' more than self [FeatureEnvy]
每条警告包含位置、异味类型和简要说明,.reek.yml 配置文件可按目录、规则、具体方法精细豁免。
高频异味解读与对策
- TooManyStatements(语句过多):方法过长。对策:提炼私有方法,让每个方法只做一件事;
- FeatureEnvy(特性依恋):方法操作别的对象的数据多过自己。对策:把逻辑移到那个对象上(Tell, Don't Ask);
- LongParameterList(参数过长):参数超过三四个。对策:引入参数对象(dry-struct 正合适);
- DuplicateMethodCall(重复调用):同一方法反复调用。对策:局部变量缓存或 memoize;
- NilCheck / ControlParameter:用 nil 判断和开关参数控制流程。对策:多态或空对象模式。
原则:异味是提示不是判决——合理的地方用配置豁免,不合理的排进重构清单。
项目配置实践
.reek.yml 示例:
detectors:
TooManyStatements:
max_statements: 8
IrresponsibleModule:
enabled: false # 老项目先关掉"缺少注释"类规则
directories:
"app/legacy":
UtilityFunction:
enabled: false # 目录级豁免,逐步收紧
接入 CI 时用 reek --failure-exit-code 让超标即失败;老项目先用 --todo 生成现状快照豁免全部存量,只拦新增异味——渐进收紧比一步到位可持续得多。
常见问题(FAQ)
Q:Reek 和 RuboCop 会不会重复?
职责不同:RuboCop 管代码风格(缩进、命名、惯用法)和部分复杂度指标;Reek 专注设计异味(耦合、职责、数据结构)。两者 CI 并用是 Ruby 社区标配。
Q:Rails 项目用 Reek 有什么注意?
Rails 的惯例写法会触发部分误报(如 controller 的 UtilityFunction)。社区有 reek-rails 适配配置;对 controller 目录适当放宽规则,把严格标准留给模型与 Service 层。
Q:警告太多不知从哪下手?
按异味类型排序,先修 FeatureEnvy 和 TooManyStatements——这两类的重构收益最大、风险最小。每次 PR 顺手清一两条,比专项"重构冲刺"更容易落地。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。