条件语句地狱如何逃?Ruby Science详解Replace Conditional With Polymorphism完整指南 条件语句地狱如何逃Ruby Science详解Replace Conditional With Polymorphism完整指南【免费下载链接】ruby-scienceThe reference for writing fantastic Rails applications项目地址: https://gitcode.com/gh_mirrors/ru/ruby-scienceRuby Science是专为 Rails 开发者打造的《编写优秀 Rails 应用的参考手册》。本文将带你用 Ruby on Rails 中的多态Polymorphism手法一次性告别case/if-elsif堆砌的条件语句地狱让代码可维护性直线上升 什么是条件语句地狱想象一下你的模型里有个字段叫question_type取值是Open、Scale、MultipleChoice。于是每个方法里都长这样case question_type when Open then summarize_open when Scale then summarize_scale when MultipleChoice then summarize_multiple_choice end这就是 Ruby Science 书中定义的Case Statement条件语句代码异味方法检查类型码或对象类名为每种情况硬编码一条分支路径。它的危害远不止难看发散变更Divergent Change加一种新题型就得改这个方法散弹式修改Shotgun Surgery同样的case逻辑散落在模型、控制器、视图里加一种题型要改 N 个文件大类堆积Large Class所有题型的细节全挤在一个类里越来越臃肿。书中的示例应用一个问卷调查 Rails 应用的 question 模型 就是一个典型现场。 想系统了解这个异味的症状与识别方法可以阅读本书源码目录中的book/code_smells/case_statement.md。核心思路让每个类自己说话Ruby 是面向对象语言它有一个比if/else更优雅的机制——动态分派dynamic dispatch同一个方法名summary在不同类中可以有不同的实现。调用者只需要喊一声请你总结一下具体谁来做、怎么做由对象自己决定 。这正是Replace Conditional With Polymorphism用多态替换条件语句方案的核心条件语句写法多态写法case type手动分发子类覆写方法Ruby 自动分发加类型 改老代码加类型 加新类老代码零改动逻辑挤在一个类里每种类型的逻辑住在自己家书中将其与Tell, Dont Ask告知而非询问原则并列你不再询问对象是什么类型而是直接告知它做什么。相关原则讲解见book/principles/tell_dont_ask.md。逃逸路线图4步把case语句变成多态第1步把类型码换成子类启用STI示例应用里的问题类型存在数据库type列中。Ruby on Rails 对这个机制有个专门的名字单表继承Single Table InheritanceSTI——不同子类实例共存于同一张表Rails 根据type列自动实例化正确的类。迁移步骤在db/migrate/目录中可见真实案例先把Open改名为OpenQuestion更好的类名再声明继承列最后把question_type重命名为 Rails 约定的type。每一步都独立跑测试避免同时调试两件事。第2步提取方法拆散条件分支把case的每条路径抽成独立方法书中称为Extract Method例如summarize_multiple_choice_answers、summarize_open_answers……第3步移动方法到对应的子类用Move Method重构手法把每条路径的方法搬进它的子类并重命名为summaryclass MultipleChoiceQuestion Question def summary total answers.count counts answers.group(:text).order(Arel.sql(COUNT(*) DESC)).count percents counts.map do |text, count| percent (100.0 * count / total).round #{percent}% #{text} end percents.join(, ) end endMultipleChoiceQuestion#summary覆写了父类方法Ruby 会自动为选择题挑对实现。所有路径搬完后父类里的老summary整个删掉Question类瞬间瘦身 ✂️。第4步用多态局部视图搞定视图层模型改完了视图层通常还藏着第二座case 地狱——根据类型决定渲染哪个 partial。Rails 的render question会询问对象的to_partial_path子类会自动返回基于类名的视图路径于是开放题渲染app/views/open_submittables/_open_submittable.html.erb量表题渲染scale_submittables/_scale_submittable.html.erb选择题渲染multiple_choice_submittables/_multiple_choice_submittable.html.erb一行渲染代码零if判断。示例应用中这些视图文件都在example_app/app/views/下可以对照感受。这套方案值不值优缺点一文看懂✅ 好处新增题型只需新增一个子类并实现相应方法现有类一行不改开闭原则的胜利每种类型的逻辑与数据住在一起再也不会出现巨型类重复的条件逻辑被自然消除代码复用更干净。⚠️ 代价书中诚实列出加行为变难了新增一种行为要去每个子类里都加一遍方法实现散落在各处如果你加行为的频率远高于加类型应该考虑策略模式或访问者模式被迫使用继承书中提醒读者权衡组合优于继承book/principles/composition_over_inheritance.mdSTI 自身有坑类型互相转换困难、查询过滤有陷阱详见book/code_smells/sti.md。一句话决策指南类型变化频繁 → 多态子类是首选行为变化频繁 → 转向策略/组合方案。延伸阅读在Ruby Science中继续探索完整章节含全部重构细节与提交记录book/solutions/replace_conditional_with_polymorphism.md相关异味book/code_smells/divergent_change.md、book/code_smells/shotgun_surgery.md、book/code_smells/case_statement.md配套重构手法book/solutions/extract_method.md、book/solutions/move_method.md、book/solutions/extract_class.md可运行的示例应用问卷 Rails 应用自带测试example_app/告别条件语句地狱不是换个写法而是把决策权交给正确的对象。下次在 Rails 项目里看到第三个when时不妨停下来让多态替你分忧 【免费下载链接】ruby-scienceThe reference for writing fantastic Rails applications项目地址: https://gitcode.com/gh_mirrors/ru/ruby-science创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考