问题标签 [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 投票
3 回答
2562 浏览

java - 带有数据模型对象的得墨忒耳定律

我昨天放假回来工作,在我们的每日站会中,我的队友提到他们正在重构我们的 java 代码中的所有模型对象,以删除所有 getter 和 setter,并将模型字段改为公共对象,调用法则Demeter 作为这样做的原因是因为

为了便于我们遵守得墨忒耳定律:一个模块不应该知道它所操纵的“对象”的内部。由于数据结构不包含任何行为,它们自然会暴露其内部结构。所以在那种情况下,得墨忒耳不适用。

我承认我不得不重新了解我对 LoD 的了解,但对于我的一生,我找不到任何表明这在法律精神范围内的东西。我们模型中的 getter/setter 都不包含任何业务逻辑,这是他这样做的理由,因此这些对象的客户不必了解 get/set 方法中是否正在执行某些业务逻辑。

我认为这是对需要“对象结构的内部知识”意味着什么的误解,或者至少是过于字面理解并在此过程中打破了相当标准的惯例。

所以我的问题是,直接公开模型对象内部结构而不是通过 LoD 名称中的 getter/setter 公开是否真的有意义?

0 投票
0 回答
367 浏览

ruby-on-rails - 如何在 Rails 4 join 操作中正确使用合并?

我确实有以下代码结构:

我希望能够像这样调用资产模型:

我正在尝试遵循德米特法则,因此资产模型不应该了解 FinancialYear (其中包含年份信息)。我正在尝试使用合并来完成此操作。

这会给出错误消息,因为第 3 行和第 4 行的顺序错误。知道 Rails 以这种方式创建查询的原因吗?知道如何更改此结构以使其正常工作吗?任何帮助将不胜感激。

0 投票
0 回答
42 浏览

ruby-on-rails - 如何改进表/模型的这种结构?

我有以下一组模型/关联:

在此处输入图像描述

虽然这从面向对象的角度来看是有道理的,但它引入了巨大的距离,例如;一个 NewsItem 和在 UI 中表示它的 Photo.image。

一个明显的改进是放弃MediaItem并制作VideoPhoto多态,但是我需要互换地对待它们,对它们进行排序、排序以搜索它们,而多态关联使这变得更加复杂/尴尬。它还将涉及许多重复的属性(当前在 上MediaItem)。

我对这个设置的主要问题是我有NewsItem视觉表示 a 的情况。除了它的标题,我还展示了一张图片,它是它的封面图片NewsItem——实际上是画廊中的第一张照片。

在这种情况下,我有效地这样做:

鉴于一次屏幕上最多有 20 个这样的项目(可能更多),我肯定需要确保通过笨拙的includes.

当然,我可以在很大程度上隐藏委托背后的一些访问权限,例如:

但这仍然给我留下了试图包含表链的尴尬查询。

有没有更明智的结构方式?

0 投票
1 回答
329 浏览

angularjs - 得墨忒耳定律和角度控制器 DI

我正在阅读http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf(尤其是第 8 页)并观看 Misko 关于编写可测试代码的 Youtube 视频,我想到 Angular 的方式DI 是否强迫你违反得墨忒耳法则。

从 PDF 中简化,一个违反得墨忒耳定律的 Java 构造函数示例:

因为该类只需要用户是否是管理员,而不需要 AccountService。

似乎 Angular 用它的 DI 强迫你打破得墨忒耳定律。我看不到以下内容的替代方案:

如果这是一个控制器,我们可以注入一个用户,它是一个控制器,一个具有解析参数的路由器,但不适用于一般情况。有什么想法吗?请注意,我假设只有 AccountService 是一个单例,并且每个后续对象都是一个实例(并且不能是 DI)。

0 投票
0 回答
5664 浏览

java - PMD 警告“可能违反得墨忒耳定律:对象不是在本地创建的”,即使在调用本地对象上的方法时也是如此。

我对得墨忒耳定律的理解是:

您的方法可以直接调用其类中的其他方法
您的方法可以直接调用其自身字段的方法(但不能直接调用字段的字段)
当您的方法接受参数时,您的方法可以直接调用这些参数的方法。
当您的方法创建本地对象时,该方法可以调用本地对象的方法。

但是
一个人不应该调用全局对象上的方法(但它可以作为参数传递?)
一个人不应该在除a类之外的某个类中拥有一串消息a.getB().getC().doSomething()。

我在我的一种方法中正在做的是:
final ServiceStatusBean serviceStatusBean = new ServiceStatusBean(); serviceStatusBean.setName("someName"); serviceStatusBean.setApiVersion("someVersion");

我的 serviceStatusBean 实例是在方法中本地创建的,我正在调用它的 setter。根据我的理解,它符合德米特法则。但根据 PMD 的说法,它在调用二传手的线路上违反了德米特法则。
警告-“可能违反得墨忒耳法则(非本地创建的对象)”

我无法理解这些 PMD 警告背后的原因。有什么解释吗??
PMD 详细信息:
插件版本 - 4.0.5.v20141105-1906
PMD 版本 - 5.2.1

0 投票
2 回答
97 浏览

php - Php,为什么违反得墨忒耳定律如此糟糕?

我知道它被认为是不好的:

或者

它被解释为“我们不想要大量的 -> -> -> ->” - 但我想让这个结构物理化,我的意思是它不能解耦。我知道如果架构师发生变化,它必须在任何地方完成,但它不会发生。再说一次,如何解决这个问题?

0 投票
1 回答
259 浏览

php - PHP MVC DI 得墨忒耳定律的实用例子,带路由器、控制器和模型

在 PHP 中使用 MVC 苦苦挣扎。看完后我的担忧变得更大: https ://www.youtube.com/watch?v=RlfLCWKxHJ0

根据 LoD,我的路由器类应该只知道请求 Uri 以加载正确的控制器类。但是,我的 Conroller 应该知道它应该使用哪个 Model 类以及一个 View 类来呈现数据。或者更好的是,Controller 应该知道 ModelFactory 将使用选定的数据存储来处理对象创建。

这一切都打破了我的 LoD。

所以我的问题是:

  1. 路由器应该如何初始化控制器类而不知道它需要哪些参数?即使是 DI 容器,我们也不知道要传递给 Router 内部构造函数的对象参数。如果我们将 DI 容器传递给 Router 构造函数(或任何其他类),我们将返回到 Service Locator。这应该怎么做?

也许这都是错误的,但我的出发点是:

路由器.php

从这里开始,我在 Controller 类中什么都做不了,因为我需要调用new Modelnew View并且必须在构造函数或方法中显式地执行它,这很糟糕。

更多问题:

  1. 我应该如何在 Controller 中获取 Model 类的实例?我应该使用静态方法加载视图吗?
0 投票
7 回答
714 浏览

java - Java:访问资源和得墨忒耳法则

概述

在我的(Android)Java 游戏中,我有一个名为resources的类。顾名思义,这个类拥有游戏的资源。我所有的 OpenGL 对象(精灵)都是在这里创建的

它看起来像下面这样(显然,与实际项目中出现的版本相比,这是一个简化版本):

所以,在我的mainMenu场景中,我需要访问我的对象,所以我们可能会看到如下内容:

现在,上述方法只是访问资源中的对象 及其方法的一种方法。但这真的违反了得墨忒耳法则吗? 如果不是,为什么不呢?如果是这样,以不违反 LOD 的方式访问这些对象的最佳方法是什么?

访问者?

一种选择(我已经排除了 TBH - 见下文)是将访问器方法放入我的资源类中。这样我就可以做类似的事情:

我有很多对象,并且每个对象的每个方法/变量都需要一个访问器。不太实用,似乎我正在编写大量额外的代码,最重要的是,只要资源类充满了这些访问器,它就会变得荒谬。因此,我不会走这条路。

将对象传入场景的构造函数

当然,我也可以这样做:

所以我可以简单地这样做:

这对于简单场景(例如不需要大量对象的菜单系统)是可行的,但对于主游戏,它可能很快就会变得一团糟,因为我必须将对大约 30 多个对象的引用传递给构造函数确实听起来不太对......

因此,如果有人能指出最好的方法以及原因,我将不胜感激。

0 投票
1 回答
217 浏览

java - IntelliJ 重构以使用 LoD

说我有一些类 Foo

我有一个使用 Foo 并违反 LoD 的程序

重构以使用 LoD 如下所示:

IntelliJ-IDEA 有很多重构方法(例如提取到方法、提取到变量、内联)。

IntelliJ-IDEA 中是否有一种方法可以重构代码bar.getFoo().getX(),看起来像这样bar.getFooX()

0 投票
1 回答
1649 浏览

java - IntelliJ 中的简单自定义重构

这个问题是对此的跟进。

假设我有一些类 Foo。

我有一个使用 Foo 并违反 LoD(得墨忒耳法则)的程序。

我可以重构此代码以分两步使用 LoD。

  1. ⌥</kbd>⌘</kbd>m bar.getFoo().getX() -> getFooX(bar) (extract to method, also find and replace occurrences)
  2. F6 getFooX(bar)-> bar.getFooX()(移动到实例方法,也查找和替换出现)

使用的程序Bar不再违反 LoD。

我想知道是否有一种方法可以在 IntelliJ 中制作自定义重构方法,将这两个步骤合并为一个。

编辑 我收到了 JetBrains 的回复,其中包含指向预先存在的功能请求的链接。如果您觉得这很有用,请投票!

你好迈克尔,

似乎我们在 YouTrack 中有类似的要求: https ://youtrack.jetbrains.com/issue/IDEA-122400 。随意投票并发表评论。

最好的问候, 雅罗斯拉夫贝德罗夫 JetBrains

编辑 至少有一种方法可以检查得墨忒耳定律的问题。 截屏

这是一个包含仅查找 LoD 违规的检查配置文件的要点。您可以将其导入 IntelliJ