德米特定律似乎是一个非常强大的概念。我可以理解它如何帮助编写良好且可维护的面向对象的代码。
Some people suggest每次需要访问视图中关联对象的属性时编写委托方法。而不是在视图中写这样的东西
@order.customer.name
你会写这段代码:
# model
class Order < ActiveRecord::Base
belongs_to :customer
delegate :name, :to => :customer, :prefix => true
end
#view
@order.customer_name
在视图中违反Demeter法则,在模型中编写委托方法是否被认为是最佳做法?
答案 0 :(得分: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
如何 {/ 1}}对象的送货地址,而告诉客户获取客户的第一个地址的国家/地区。就像一个告诉你做某事的老板,让你独自与老板一样,微观管理你日常工作的方式。 (有关额外的启发,请阅读问题,不要告诉Ruby开发方法:))
有一些关于使用演示者,装饰器方法或帮助器的内容,以避免让这个可能只显示逻辑代码乱丢你的模型。我将把它作为练习留给读者:)