我正在阅读一本名为《 Rails反模式》的书,他们谈论使用委派来避免违反Demeter法则。这是他们的主要例子:
他们认为在控制器中调用这样的命令是不好的(我同意)
@street = @invoice.customer.address.street
他们提出的解决方案是执行以下操作:
class Customer
has_one :address
belongs_to :invoice
def street
address.street
end
end
class Invoice
has_one :customer
def customer_street
customer.street
end
end
@street = @invoice.customer_street
他们说,由于您仅使用一个点,因此您没有违反Demeter定律。我认为这是不正确的,因为您仍在通过客户通过地址来获取发票的街道。我主要是从我读过的博客文章中得到这个想法的:
http://www.dan-manges.com/blog/37
在博客文章中,主要的例子是
class Wallet
attr_accessor :cash
end
class Customer
has_one :wallet
# attribute delegation
def cash
@wallet.cash
end
end
class Paperboy
def collect_money(customer, due_amount)
if customer.cash < due_ammount
raise InsufficientFundsError
else
customer.cash -= due_amount
@collected_amount += due_amount
end
end
end
博客文章指出,尽管只有一个点customer.cash
而不是customer.wallet.cash
,但此代码仍违反Demeter法则。
现在在Paperboy collect_money方法中,我们没有两个点,而在“ customer.cash”中只有一个点。这个代表团解决了我们的问题吗?一点也不。如果我们看一下这种行为,一个报税员仍在直接伸入客户的钱包以提取现金。
编辑
我完全理解并同意,这仍然是一种违规行为,我需要在Wallet
withdraw中创建一个方法来为我处理付款,我应该在Customer
类中调用该方法。我没有得到的是,按照这个过程,我的第一个例子仍然违反了Demeter法则,因为Invoice
仍然直接进入Customer
街道。
有人可以帮我消除困惑。我一直在搜索过去两天,试图让这个话题陷入,但仍然令人困惑。