这是重构ActiveRecord胖模型的正确方法吗?

时间:2013-08-13 08:48:11

标签: ruby-on-rails refactoring separation-of-concerns

例如,如果我有这个ActiveRecord模型:

应用程序/模型/ order.rb

class Order < ActiveRecord::Base
  # model logic
end
require "lib/someclass.rb"

LIB / somelass.rb

class Order
  before_save :something
  # more logic here
end

这是从模型重构/提取逻辑的好方法吗? 或者可以使用关注类,服务类或其他东西?

2 个答案:

答案 0 :(得分:14)

就像很久以前有人告诉我的那样:

  

代码重构不是随机移动代码的问题。

在您的示例中,这正是您正在做的事情:将代码移动到另一个文件

为什么不好?

通过这样移动代码,您将使原始类更复杂,因为逻辑被随机分成几个其他类。当然它看起来更好,一个文件中的代码在视觉上更好,但就是这样。

首选组合继承。使用像这样的mixins要求通过将杂乱的东西倾倒在六个独立的垃圾抽屉中并将它们关上来“清理”一个凌乱的房间。当然,它在表面看起来更干净,但垃圾抽屉实际上更难以识别和实现澄清域模型所必需的分解和提取。

我该怎么办?

你应该问问自己:

  • 哪个代码组合在一起,可以成为新类/模块的一部分?
  • 将代码提取到其他地方有意义吗?
  • 我是否有一些代码在我的应用程序中共享?
  • 我可以在代码库中提取循环模式吗?

提取服务对象

当某个操作符合以下一个或多个条件时,我会访问服务对象:

  • 行动很复杂
  • 该动作涉及多个模型
  • 该操作与外部服务交互
  • 此操作不是基础模型的核心问题
  • 执行操作的方法有多种

提取表单对象

如果可以通过单个表单提交更新多个模型,则可能需要创建表单对象。

这使得所有表单逻辑(名称约定,验证等)都可以放在一个地方。

提取查询对象

您应该将复杂的SQL / NoSQL查询提取到自己的类中。每个查询对象负责根据标准/业务规则返回结果集。

提取演示者/装饰者

将视图逻辑提取到演示者中。您的模型不应该处理特定的视图逻辑。此外,它还可让您在多个视图中使用演示者。

More on decorators

感谢this博文,帮助我将这些内容整合在一起。

答案 1 :(得分:1)

将代码保存在同一个类移动逻辑中,它不会提取它。

外部化回调声明具有误导性且具有潜在危险性。回调被滥用了;强迫读者追捕相关文件是残酷的。

没有一般方式回答问题; “最好的”重构取决于实际重构的内容。但是,生命周期信息应该是明显和精确的。

担忧,服务,装饰,外墙等是支持重构的良好机制。在不知道重构的内容的情况下,不可能就什么是“最佳”提供有意义的建议。