得墨忒尔定律——你能走多远?
我想遵循德墨忒尔法则。当我在代码中搜索“两个点”时,我发现自己问自己是否真的值得在这种类型的上下文中设置委托职责:
从
class Activity
def increment_user_points!
self.user.increment_points!(points, true)
end
end
到
module UserDelegator
def user_increment_points!(points, increment_credits=false)
self.user.increment_points!(points, increment_credits)
end
end
class Activity
include UserDelegator
def increment_user_points!
user_increment_points!(points, true)
end
end
您的想法是什么?
I want to follow the Law of Demeter. As I am going through my code searching for the "two dots", I find myself asking if it's really worth setting up the delegation responsibilities in this type of context:
FROM
class Activity
def increment_user_points!
self.user.increment_points!(points, true)
end
end
TO
module UserDelegator
def user_increment_points!(points, increment_credits=false)
self.user.increment_points!(points, increment_credits)
end
end
class Activity
include UserDelegator
def increment_user_points!
user_increment_points!(points, true)
end
end
What are your thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的例子并没有违反德米特法则。用户是 Activity 的一个属性,并且您正在访问用户的公共 API 方法,因此原始实现不会出现错误。
德米特定律的目标是避免破坏对象封装。你的“两点”方法有点过于简单化了这个想法。实际上,您应该检查对象是如何交互的,并确保您没有过多地了解其他对象的属性或关系。例如,如果以下情况违反规则:
这将是因为该地址是用户的业务,并且应该通过用户的 API 适当封装对其的访问。作为用户的客户端,我们永远不应该直接访问用户属性的 API。
同样,在您的示例中,您直接使用用户 API,这很好并且没有违反德米特法则。综上所述,我发现一般规则是一个很好遵循的规则。如果您避免破坏对象封装(如图所示),您的代码通常会更容易更改和维护,并且类将更容易重构。
Your example is not breaking the Law of Demeter. The user is an attribute of the activity and you are accessing a public API method on the user, so you are not in error with the original implementation.
The goal of the Law of Demeter is to avoid breaking object encapsulation. Your "two dots" approach is somewhat of an oversimplification of the idea. In reality, you should examine how your objects are interacting and ensure that you are not reading too far into the attributes or relationships of other objects. For instance, if the following would be a violation of the rule:
This would be due to the fact that the address is the business of the user, and it should encapsulate access to it appropriately through the user's API. As a client of the user, we should never directly have access to the API's of the users attributes.
Again, in your example, you are using the users API directly, which is fine and is not violating Demeters Law. All that said, I have found the general rule to be a good one to follow. Your code will generally be easier to change and maintain and classes will be easier to refactor if you avoid breaking object encapsulation as shown.
我实际上希望看起来更像这样:
创建一个包含
include
的模块似乎会产生更多复杂性。德墨忒尔法则的全部要点(我更喜欢将其视为指南......)是,您应该能够对用户
的内部进行任何您喜欢的操作,而不必在类外重写大量代码。您的UserDelegator
模块没有多大帮助——当您摆弄User
的内部结构时,您仍然需要重写该代码。但如果是我,我认为我不会为此烦恼,除非您发现自己重写了很多代码来对
User
进行简单的更改。也许这只是因为我习惯了 Linux 内核编码风格,它经常违反 Demeter 定律:三个对象远离:)并且我不确定如果这样写代码会更清晰:
所以我所有人都赞成适度遵循准则——问问自己,您的修改是否实际上会导致更干净、更易于维护的代码,或者是否只是为了遵循规则而遵循规则。
I'd actually expect TO to look more like this:
Creating a module to
include
would seem to create more complexity. And the whole point of the Law of Demeter (I like to think of it more as a guideline..) is that you ought to be able to do whatever you like toUser
's internals without having to rewrite much code outside the class. YourUserDelegator
module doesn't help much -- you still get to re-write that code when you fiddle withUser
's internals.But if it were me, I don't think I'd even bother with this, unless you're finding yourself rewriting a lot of code to make simple changes to
User
. Maybe that's just because I'm used to the Linux kernel coding style, which breaks the law of Demeter on a regular basis:Three objects away :) and I'm not sure the code would be more legible if written:
So I'm all in favor of following guidelines in moderation -- ask yourself if your modifications actually lead to cleaner, more maintainable code, or if it is just following a rule for the sake of following rules.