7

得墨忒耳法则似乎是一个非常强大的概念。我可以理解它如何帮助编写良好且可维护的面向对象代码。

有人建议每次需要访问视图中关联对象的属性时编写一个委托方法。而不是在视图中写这样的东西

@order.customer.name

你会写这个代码:

# model
class Order < ActiveRecord::Base
  belongs_to :customer
  delegate :name, :to => :customer, :prefix => true
end

#view
@order.customer_name

另一方面,人们认为您的视图不应该指定模型,并且您不应该仅为了在视图中用点换下划线而向模型添加诸如委托之类的方法

当在视图中违反得墨忒耳法则时,在模型中编写委托方法是否被认为是最佳实践?

4

1 回答 1

7

我认为您customer_name自动生成的委托方法是目前最简单的方法。由于它是一个方法调用(而不是一系列方法链),因此以后很容易重构(或者,比某些链式方法更容易重构)

想象一下,无论出于何种原因,将许多客户添加到订单中,其中一个是主要客户。现在您的订单类可能看起来像

class Order < ActiveRecord::Base

  has_many :customers

  def customer_name
    if customers.first.primary?
      customers.first.name
    else
      customers.last.name
    end
end

很容易用我们自己的一种方法替换方便委托生成的方法。

(第一次编写也非常容易,因为delegate它会处理所有样板。很有可能你会customer_name在你的应用程序中永远使用这种形式。很难知道。但是第一次编写很容易/自动编写的代码扔掉很便宜:))

当然,您必须避免编写方法名称的情况,例如customer_streetaddress_is_united_states?(是的,不是将对象图编码为点,而是将其编码为下划线。)

如果您的视图确实需要知道用户是否位于美国,那么这样的方法可能会起作用:

class Order < ActiveRecord::Base

    belongs_to :customer

    def shipping_to_us?
      customer.shipping_country == "USA"
      # Law of Demeter violation would be:
      # customer.addresses.first.country == "USA"
    end
  end

  class Customer < ActiveRecord::Base
    has_many :addresses

    def shipping_country
      addresses.first.country
    end
  end

请注意这里是如何向对象Order 询问Customer送货地址,而不是告诉客户获取其客户的第一个地址所在的国家/地区。就像一个告诉你做某事并让你独自一人的老板与一个对你的日常工作进行微观管理的老板。(要获得额外的启发,请阅读问题,不要告诉 Ruby 开发的方法 :))

关于使用演示者、装饰器方法或助手来避免这些可能只是显示逻辑代码乱扔模型,有一些话要说。我将把它作为练习留给读者:)

于 2013-06-01T05:25:45.380 回答