问题标签 [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.
java - 带有数据模型对象的得墨忒耳定律
我昨天放假回来工作,在我们的每日站会中,我的队友提到他们正在重构我们的 java 代码中的所有模型对象,以删除所有 getter 和 setter,并将模型字段改为公共对象,调用法则Demeter 作为这样做的原因是因为
为了便于我们遵守得墨忒耳定律:一个模块不应该知道它所操纵的“对象”的内部。由于数据结构不包含任何行为,它们自然会暴露其内部结构。所以在那种情况下,得墨忒耳不适用。
我承认我不得不重新了解我对 LoD 的了解,但对于我的一生,我找不到任何表明这在法律精神范围内的东西。我们模型中的 getter/setter 都不包含任何业务逻辑,这是他这样做的理由,因此这些对象的客户不必了解 get/set 方法中是否正在执行某些业务逻辑。
我认为这是对需要“对象结构的内部知识”意味着什么的误解,或者至少是过于字面理解并在此过程中打破了相当标准的惯例。
所以我的问题是,直接公开模型对象内部结构而不是通过 LoD 名称中的 getter/setter 公开是否真的有意义?
ruby-on-rails - 如何在 Rails 4 join 操作中正确使用合并?
我确实有以下代码结构:
我希望能够像这样调用资产模型:
我正在尝试遵循德米特法则,因此资产模型不应该了解 FinancialYear (其中包含年份信息)。我正在尝试使用合并来完成此操作。
这会给出错误消息,因为第 3 行和第 4 行的顺序错误。知道 Rails 以这种方式创建查询的原因吗?知道如何更改此结构以使其正常工作吗?任何帮助将不胜感激。
ruby-on-rails - 如何改进表/模型的这种结构?
我有以下一组模型/关联:
虽然这从面向对象的角度来看是有道理的,但它引入了巨大的距离,例如;一个 NewsItem 和在 UI 中表示它的 Photo.image。
一个明显的改进是放弃MediaItem
并制作Video
和Photo
多态,但是我需要互换地对待它们,对它们进行排序、排序以搜索它们,而多态关联使这变得更加复杂/尴尬。它还将涉及许多重复的属性(当前在 上MediaItem
)。
我对这个设置的主要问题是我有NewsItem
视觉表示 a 的情况。除了它的标题,我还展示了一张图片,它是它的封面图片NewsItem
——实际上是画廊中的第一张照片。
在这种情况下,我有效地这样做:
鉴于一次屏幕上最多有 20 个这样的项目(可能更多),我肯定需要确保通过笨拙的includes
.
当然,我可以在很大程度上隐藏委托背后的一些访问权限,例如:
但这仍然给我留下了试图包含表链的尴尬查询。
有没有更明智的结构方式?
angularjs - 得墨忒耳定律和角度控制器 DI
我正在阅读http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf(尤其是第 8 页)并观看 Misko 关于编写可测试代码的 Youtube 视频,我想到 Angular 的方式DI 是否强迫你违反得墨忒耳法则。
从 PDF 中简化,一个违反得墨忒耳定律的 Java 构造函数示例:
因为该类只需要用户是否是管理员,而不需要 AccountService。
似乎 Angular 用它的 DI 强迫你打破得墨忒耳定律。我看不到以下内容的替代方案:
如果这是一个控制器,我们可以注入一个用户,它是一个控制器,一个具有解析参数的路由器,但不适用于一般情况。有什么想法吗?请注意,我假设只有 AccountService 是一个单例,并且每个后续对象都是一个实例(并且不能是 DI)。
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
php - Php,为什么违反得墨忒耳定律如此糟糕?
我知道它被认为是不好的:
或者
它被解释为“我们不想要大量的 -> -> -> ->” - 但我想让这个结构物理化,我的意思是它不能解耦。我知道如果架构师发生变化,它必须在任何地方完成,但它不会发生。再说一次,如何解决这个问题?
php - PHP MVC DI 得墨忒耳定律的实用例子,带路由器、控制器和模型
在 PHP 中使用 MVC 苦苦挣扎。看完后我的担忧变得更大: https ://www.youtube.com/watch?v=RlfLCWKxHJ0
根据 LoD,我的路由器类应该只知道请求 Uri 以加载正确的控制器类。但是,我的 Conroller 应该知道它应该使用哪个 Model 类以及一个 View 类来呈现数据。或者更好的是,Controller 应该知道 ModelFactory 将使用选定的数据存储来处理对象创建。
这一切都打破了我的 LoD。
所以我的问题是:
- 路由器应该如何初始化控制器类而不知道它需要哪些参数?即使是 DI 容器,我们也不知道要传递给 Router 内部构造函数的对象参数。如果我们将 DI 容器传递给 Router 构造函数(或任何其他类),我们将返回到 Service Locator。这应该怎么做?
也许这都是错误的,但我的出发点是:
路由器.php
从这里开始,我在 Controller 类中什么都做不了,因为我需要调用new Model,new View并且必须在构造函数或方法中显式地执行它,这很糟糕。
更多问题:
- 我应该如何在 Controller 中获取 Model 类的实例?我应该使用静态方法加载视图吗?
java - Java:访问资源和得墨忒耳法则
概述
在我的(Android)Java 游戏中,我有一个名为resources的类。顾名思义,这个类拥有游戏的资源。我所有的 OpenGL 对象(精灵)都是在这里创建的
它看起来像下面这样(显然,与实际项目中出现的版本相比,这是一个简化版本):
所以,在我的mainMenu场景中,我需要访问我的对象,所以我们可能会看到如下内容:
现在,上述方法只是访问资源中的对象 及其方法的一种方法。但这真的违反了得墨忒耳法则吗? 如果不是,为什么不呢?如果是这样,以不违反 LOD 的方式访问这些对象的最佳方法是什么?
访问者?
一种选择(我已经排除了 TBH - 见下文)是将访问器方法放入我的资源类中。这样我就可以做类似的事情:
我有很多对象,并且每个对象的每个方法/变量都需要一个访问器。不太实用,似乎我正在编写大量额外的代码,最重要的是,只要资源类充满了这些访问器,它就会变得荒谬。因此,我不会走这条路。
将对象传入场景的构造函数
当然,我也可以这样做:
所以我可以简单地这样做:
这对于简单场景(例如不需要大量对象的菜单系统)是可行的,但对于主游戏,它可能很快就会变得一团糟,因为我必须将对大约 30 多个对象的引用传递给构造函数确实听起来不太对......
因此,如果有人能指出最好的方法以及原因,我将不胜感激。
java - IntelliJ 重构以使用 LoD
说我有一些类 Foo
我有一个使用 Foo 并违反 LoD 的程序
重构以使用 LoD 如下所示:
IntelliJ-IDEA 有很多重构方法(例如提取到方法、提取到变量、内联)。
IntelliJ-IDEA 中是否有一种方法可以重构代码bar.getFoo().getX()
,看起来像这样bar.getFooX()
?
java - IntelliJ 中的简单自定义重构
这个问题是对此的跟进。
假设我有一些类 Foo。
我有一个使用 Foo 并违反 LoD(得墨忒耳法则)的程序。
我可以重构此代码以分两步使用 LoD。
- ⌥</kbd>⌘</kbd>m
bar.getFoo().getX()
->getFooX(bar)
(extract to method, also find and replace occurrences) - F6
getFooX(bar)
->bar.getFooX()
(移动到实例方法,也查找和替换出现)
使用的程序Bar
不再违反 LoD。
我想知道是否有一种方法可以在 IntelliJ 中制作自定义重构方法,将这两个步骤合并为一个。
编辑 我收到了 JetBrains 的回复,其中包含指向预先存在的功能请求的链接。如果您觉得这很有用,请投票!
你好迈克尔,
似乎我们在 YouTrack 中有类似的要求: https ://youtrack.jetbrains.com/issue/IDEA-122400 。随意投票并发表评论。
最好的问候, 雅罗斯拉夫贝德罗夫 JetBrains
这是一个包含仅查找 LoD 违规的检查配置文件的要点。您可以将其导入 IntelliJ。