2

我对如何通过一对多关联避免违反 Demeter 法则感到困惑。假设我有一个这样的模型:

class Organization < ActiveRecord::Base
  has_one :address
  has_many :employees
end

我相信这样做会违反得墨忒耳定律:

organization.address.street_name

这可以通过使用 *address_street_name* 方法来避免。这是一个足够简单的解决方案。但是假设我们现在这样做:

organization.employees.each { |employee| puts employee.first_name }

这似乎违反了得墨忒耳法则,尽管看起来并不那么明显。您仍然展示了对 Employee 内部结构的了解。避免此类违规行为的最佳方法是什么?

4

3 回答 3

2

得墨忒耳法则的目标是避免暴露内部状态,并鼓励使用“告诉,不要问”原则,而不是a.something.do_something使用a.do_something(然后可以委托给其内部成员something)。

话虽如此,这并不是您永远不能违反的硬性规定。在这种情况下,没有真正的解决方法,因为您不是要求员工使用其名字做某事,而只是查询其名字。

于 2012-07-31T23:55:03.017 回答
1

嗯。这是我的看法:

  • 如果您在视图中使用两个示例,我会说上面的两个示例都可以,因为如果您正在创建一个显示来自多个模型的信息的视图,我想这很常见,那为什么不呢?很明显,rails 中的视图对数据结构/模型了解很多。

  • 在第二个示例中,如果您对一个元素进行迭代(即执行一些逻辑),我会考虑将其放入另一个类,在这种情况下是员工。但同样,如果它在视图中,我宁愿不这样做,特别是如果这意味着从模型方法生成 html 代码。在我看来,Rails 模型更像是一种数据结构,而不是 Rob Martin 在“数据/对象反对称”一节中的 Clean Code 中描述的对象(第 95 页,就在 demeter 定律之前 ;-))

于 2012-07-31T23:54:05.187 回答
0

得墨忒耳法则的动机是封装,而不是“减少点数”。

隐藏域对象中的行为是最有意义的,但对于在视图中显示数据来说意义不大——这不是你永远不能打破的规则。

这篇文章对这个主题给出了很好的解释:得墨忒耳定律和点计数

于 2012-08-01T00:05:18.640 回答