问题标签 [law-of-demeter]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
20 回答
728 浏览

design-patterns - Is there anything inherently wrong with long object invocation chains?

I've organized my code hierarchically and I find myself crawling up the tree using code like the following.

I'm not drilling down into the task object; I'm drilling up to its parents, so I don't think I'm losing anything in terms of encapsulation; but a flag is going off in the back of my mind telling me there's something dirty about doing it this way.

Is this wrong?

0 投票
6 回答
8318 浏览

oop - 耦合、内聚和得墨忒耳定律

墨忒耳法则表明你应该只与你直接知道的物体交谈。也就是说,不要执行方法链接来与其他对象对话。当您这样做时,您正在与中间对象建立不正确的链接,将您的代码不恰当地耦合到其他代码。

那很糟。

解决方案是让您知道的类本质上公开简单的包装器,将责任委托给与之有关系的对象。

那挺好的。

但是,这似乎导致班级凝聚力低。它不再只是简单地负责它所做的事情,而且它还具有某种意义上的委托,通过复制其相关对象的接口部分来降低代码的内聚性。

那很糟。

真的会降低凝聚力吗?是两害相权取其轻吗?

这是发展的灰色地带之一,您可以在其中讨论界限在哪里,或者是否有强有力的、有原则的方法来决定在哪里划定界限以及您可以使用什么标准来做出决定?

0 投票
4 回答
2028 浏览

oop - 封装原理

有一些面向对象的工程原则表明“一个类应该只知道它作为参数的类的契约,或者它使用的任何内部契约”。

在 C++ 中,反例是:

这个原则有名字吗?此外,很高兴看到实际原理而不是我上面的解释。

0 投票
1 回答
211 浏览

dependency-injection - DI 和复合组件 - 设计

我正在为系统设计一个新组件,尝试遵循有关 DI 的各种准则,以便我们在隔离、模拟等方面获得回报。

所以我有以下组件(说明为抽象):

  • Fetcher - 支持 IFetcher,它从特定数据源获取数据。返回 IDataSource。
  • Builder - 支持 IBuilder,它从 IDataSource 构建结构。

我想将它们包装在一个“Performer”(因为想要一个更好的名字)组件中,它会执行以下操作:

为了遵守 Dependency Injection 和 LoD 指南(据我所知),我同时传入了 IFetcher 和 IBuilder 组件。

我的问题 - 这听起来像一个可以接受的设计吗?与工作同事的对话是“是的,听起来不错”,但不是 100% 相信 Performer 类的封装。

在我看来,Performer 是一个复合控件,它将几个不同的组件粘合在一起,这应该是可以接受的。唯一的问号是我是否应该有一个“Performer Factory”,但考虑到可以模拟实际组件(Ifetcher 和 IBuilder),这似乎有点过分了。

任何想法将不胜感激,谢谢。

0 投票
4 回答
609 浏览

c++ - 如何重构此代码层次结构(与得墨忒耳法则有关)

我有一个游戏引擎,我将物理模拟与游戏对象功能分开。所以我有一个物理身体的纯虚拟课程

我将从中推导出物理模拟的各种实现。我的游戏对象类看起来像

我可以插入该特定游戏所需的任何实现。但是Body当我只有一个GameObject. 所以我发现自己写了很多东西,比如

我很想把所有这些都抓起来,然后做类似的事情

但这似乎是错误的(即违反了得墨忒耳法则)。另外,它只是将详细程度从实现推到了使用。所以我正在寻找一种不同的方式来做到这一点。

0 投票
10 回答
25698 浏览

language-agnostic - 如何解决违反得墨忒耳法则的问题?

我和一位同事为我们的客户设计了一个系统,我们认为我们创造了一个很好的干净设计。但是我在我们引入的一些耦合方面遇到了问题。我可以尝试创建一个示例设计,其中包含与我们的设计相同的问题,但如果您原谅我,我将创建我们设计的摘录来支持这个问题。

我们正在开发一个系统,用于为患者注册某些治疗。为了避免到图像的链接断开,我将把 UML 概念类图描述为 ac# 样式类定义。

我将尝试解释一下设计,协议是新治疗的模板。并且协议属于某种类型并且具有需要管理的药物。根据协议,相同药物的剂量可能不同(除其他外),因此存储在 ProtocolMedication 类中。AdministrationRoute 是与协议管理分开管理和创建/更新药物的方式。

我发现以下我们将违反德墨忒耳法则的地方:

违反得墨忒耳法则

BLL 内部

例如,在 ProtocolMedication 的业务逻辑中,有一些规则依赖于药物的 AdministrationRoute.Soluble 属性。代码将变为

存储库内部

列出特定学科中所有协议的方法将被写为:

用户界面内部

我们使用 ASP.NET(无 MVC)作为我们系统的接口,在我看来,这一层目前的违规行为最严重。gridview 的数据绑定(必须显示协议纪律的列必须绑定到 Kind.Discipline.Name),它们是字符串,所以没有编译时错误

所以我认为实际的问题可能是,什么时候可以将其更多地视为德墨忒耳的建议,以及如何解决违反德墨忒耳法则的行为?

我对自己有一些想法,但我会将它们作为答案发布,以便可以单独对其进行评论和投票。(我不确定这是这样做的方式,如果不是,我将删除我的答案并将它们添加到问题中)。

0 投票
5 回答
408 浏览

c++ - 得米特法则或返回整个向量

哪一个更好:

或者:

0 投票
4 回答
627 浏览

rest - 得墨忒耳法则与 REST

得墨忒耳法则(真的应该是得墨忒耳的建议)说你不应该“穿过”一个物体去接触他们的子物体。如果您作为客户需要执行一些重要的操作,那么大多数时候您正在使用的域模型应该支持该操作。

REST 原则上是一个愚蠢的对象层次结构。它就像一个资源/对象的文件系统,其中每个对象都可以有子对象。您几乎总是可以使用 REST。您可以选择使用 REST 技术构建按约定的复合对象类型,只要提供者和客户端就更高级别的操作达成一致,您就可以避免通过。

那么,你如何平衡 REST 和 Demeter?在我看来,它们并不冲突,因为 REST 完全是关于超松散耦合,以至于提供者试图预测客户的所有需求是毫无意义的,而 Demeter 假设逻辑可以迁移到它的通过重构最自然的地方。

但是,您可能会争辩说,在您更好地了解您的客户之前,REST 只是一个权宜之计。REST 只是一个技巧吗?Demeter 在任何服务器/客户端场景中都不现实吗?

0 投票
3 回答
2760 浏览

dependency-injection - 关于工厂模式和依赖注入的得墨忒耳定律

我有一个关于依赖注入的问题。

说我想创建一个类,调用它,WebGetTask

WebGetTask 需要对 HttpService 的依赖

错误代码 1 代码:

行。我知道这很糟糕,因为 httpService 被注入,但它从未使用过,除了在新的 WebGetTask 上创建

好的坏代码2代码:

我认为这更好,因为我们使用工厂但是...但是..

从我站的地方,我可以看到在 WebGetTaskFactory 中我们仍在注入一个 HttpService 并且除了创建一个新的 WebGetTask 的唯一目的之外没有对它做任何事情

所以回顾一下我的问题是我如何设计一个工厂类(WebGetTaskFactory),当新对象在其构造函数上需要依赖项(HttpService)而不简单地注入和传递依赖项(HttpService)时创建新对象(WebGetTask)?或者更确切地说,这是这样做的方法吗?如果是这样,那么一切都很好,如果不是,那么请指导我如何正确使用DI和工厂模式。谢谢。

0 投票
3 回答
656 浏览

law-of-demeter - 这个编程规则的名称是什么?

有一个编程“规则”说,当一个方法需要知道'xyz'时,应该直接询问'z',而不是询问'x'。我只是不记得名字了。