4

我目前正在学习delegate德墨忒耳法则,我似乎找不到一个很好的例子来说明使用delegate实际上是有用的。

我想找一个与我的项目相关的例子,因为我必须做一个演示。我发现可能违反得墨忒耳法则的唯一代码行如下:

@game.promotions.find_by_promo_type("cross")

该模型Game has_many Promotions和它正在跨越另一个模型以执行find基于促销属性的调用promo_type。据我了解,这违反了得墨忒耳法则,我应该通过使用委托来解决这个问题:

class Game < ActiveRecord::Base
   has_many :promotions

   delegate :find_by_promo_type, :to => :promotion
end

你能给我一个例子,除了“得墨忒耳的法则是这样说的”之外,这实际上是有用的。

我唯一能想到的是,出于某种原因,我想将名称更改为promotionsto promos,那么该解决方案将很有用,因为我只需要进行以下更改并且:find_by_promo_type仍然适用于Game

class Game < ActiveRecord::Base
   has_many :promos

   delegate :find_by_promo_type, :to => :promos
end

唯一的问题是,我认为这个论点是有缺陷的。如果我要更改模型名称,我还必须在许多其他地方重构代码,甚至不违反得墨忒耳定律。很难相信这就是得墨忒耳法则在这个例子中所能完成的全部。

有人可以帮我理解这一点。

4

1 回答 1

6

使用delegate可以具有抽象某事如何完成的实现的优势。在您的示例中,与其说是允许您将名称更改为promotionsto promos。这是关于您向“外部世界”或对象的 API 公开的内容非常有目的性。与之交谈的对象Game不需要知道您正在使用另一个 ActiveRecord 模型来检索关联Promotions的 . 它可以添加不必要的耦合。

所有的 LoD 违规都不一定是坏事,但它们可以作为代码异味,当你看到它们时应该暂停一下。您需要平衡消除 LoD 违规的成本与更改对象 API 的潜在成本和可能性。

我强烈推荐阅读 Sandi Metz 的 Practical Object-Oriented Design in Ruby: An Agile Primer 的第 4 章。它很好地涵盖了这个主题并指出:“使用委托来隐藏紧密耦合与解耦代码不同。”

在您的情况下,您可能希望从调用者的角度更多地考虑它以及它应该发送什么消息Game。也许它应该只是调用Game.cross_promotions而不是Game调用另一个对象的方法,无论它是否被委托。

于 2013-10-17T04:41:52.257 回答