告别特性依恋:Ruby Science教你用Move Method为方法找到真正的家
【免费下载链接】ruby-scienceThe reference for writing fantastic Rails applications项目地址: https://gitcode.com/gh_mirrors/ru/ruby-science
Ruby Science是一本教写 Rails 应用的实战参考书,其中 Move Method(移动方法)重构手法正是解决特性依恋(Feature Envy)这个经典代码坏味道的首选方案。读完本文,你将学会判断一个方法是否“放错了地方”,并用 5 个简单步骤把它安全地移到正确的类里。
什么是特性依恋:方法“住错地方”的信号
特性依恋(Feature Envy)指的是:一个方法里的大部分逻辑,其实在频繁访问别的对象,而不是自己所在类的状态。就像一个人整天跑别人家串门,说明他住错了房。
🔍 常见症状清单:
- 方法里反复引用同一个参数或局部变量
- 参数、局部变量比本类的实例变量用得更勤
- 方法名里带着别的类名,例如
invite_user - 同一个类里有一堆接收相同参数的私有方法
- 违背了 Law of Demeter(得墨忒尔法则) 与 Tell, don't ask 原则
特性依恋的代价是双重的:逻辑被困在错误的类里难以复用,而且往往藏在private方法中,其他类根本用不到。
Move Method:为什么它是特性依恋的最佳解药
Ruby Science 把 Move Method 定义为:把方法整体搬到拥有它所依赖状态的类中。这样做能同时收获三件事:
| 收益 | 说明 |
|---|---|
| 消除特性依恋 | 方法搬到了它“羡慕”的对象身边 |
| 提升可复用性 | 私有、带参数的方法变成公有、无参数的方法 |
| 提高可读性 | 方法与它依赖的其他方法住得更近了 |
完整的操作规范见书籍的 Move Method 章节,配套的坏味道分析在 Feature Envy 章节。
移动方法的 5 步操作流程
- 把方法定义和方法体完整搬入新类
- 新类本来就拥有的状态,不再作为参数传入,直接引用
- 原来属于旧类的状态,补充为必要参数
- 方法名在新语境下不合理就重命名(如
invite_user搬进User类后改叫invite) - 把对旧方法的调用全部替换为对新方法的调用
实战:把评分逻辑从 Completion 搬进 Answer
书里的示例应用是一个问卷调查应用(源码位于example_app/)。改造前的 completion.rb 中,score方法里有个“越界”的块:它反复访问answer的question和text,典型的特性依恋:
def score answers.inject(0) do |result, answer| question = answer.question result + question.score(answer.text) end end作者用了两步走(可对照提交记录d5b4871与fe3ef38):
第一步:Extract Method(提取方法),先把依恋的部分隔离成score_for_answer私有方法,此时代码依然能正常工作。
第二步:Move Method(移动方法),把这个方法搬到 answer.rb 并改名score,逻辑从此回到数据的真正主人身边:
class Answer < ActiveRecord::Base def score question.score(text) end end搬完之后:Completion#score只剩干净的answers.sum { |a| a.score }式调用;评分逻辑从私有小方法变成可被其他类复用的公有接口,坏味道清零。
⚠️ 常见误区:别想一步到位
新手最容易犯的错误是“边提取边移动”——一次性在新类里建方法、搬代码、改调用。书里专门警告了这一点:拆成两个小步骤,每一步跑完测试都绿,代码“损坏”的窗口期更短,出问题时排查范围也更小。练熟之后,两步小重构的速度和一步大重构其实一样快。
移动完成后的自检清单:
- ✅ 新方法在新家没有继续犯特性依恋(若有,继续拆分回迁)
- ✅ 新类没有因为收留方法而变成大类(Large Class)
如何获取 Ruby Science 完整资源
仓库里既有书籍的 Markdown 源文件,也有一步步展示重构过程的示例 Rails 应用,是练习 Move Method 的绝佳素材:
git clone https://gitcode.com/gh_mirrors/ru/ruby-science推荐阅读路径:
- 书籍目录总览:
book/book.md - 坏味道篇(先学会识别):
book/code_smells/,重点看feature_envy.md - 重构方案篇(再动手开药):
book/solutions/,重点看move_method.md、extract_method.md - 示例应用:
example_app/,可用git log -- example_app/app/models/completion.rb查看真实的重构提交历史
掌握 Move Method 之后,你会发现 Rails 模型层的职责划分清晰了许多——每个方法都住在了它真正该待的家。
【免费下载链接】ruby-scienceThe reference for writing fantastic Rails applications项目地址: https://gitcode.com/gh_mirrors/ru/ruby-science
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考