这是德米特法则的一个很好的例子吗?

问题描述

我正在准备口试,我想知道我是否正确理解了得墨忒耳定律。从本质上讲,我已经理解迪米特法则旨在通过减少类之间的相互依赖来放松耦合,并且不明确地透露类是如何获取某些信息的。这在引用“只与您的直接朋友交谈”中得出结论。我想出了这个简化的例子:

如果我们有一个班级棋盘,并且我们的比赛场地上有游戏棋子,例如想找出哪些棋子移动了,那么一种直观的方法来找出这一点,如下所示:

Board.getGamePiece(p).getMovement();

但这违反了得墨忒耳定律。因此,我们只需编写以下代码即可将该任务委托给 getMovement 方法

Board.getMovement(p);

我的理解是否正确?我的解释中是否有任何错误我有点不确定如何在此处使用术语“委托”,在我的示例中是否正确使用?

解决方法

我认为你理解这个想法,但我不确定你的例子是否真的有意义。在棋盘游戏的背景下,棋盘很难不关心可能的动作! (所以在这里应用 Demeter 是没有意义的,因为董事会已经可以访问 Movement 类了)。

,

我已经正确理解了迪米特法则

这是一个模糊、不科学的原理。它不像万有引力定律,也不像语言规范。您将其提升为二进制概念(代码要么违反它,要么不违反)。这是双重错误:

  • 这是一个见仁见智的问题,它是灰色的。没有“此代码违反它,而此代码不违反它”这样的事情。
  • 这是一个指南,而不是规则。有时编写许多人都同意的代码完全违反了这一原则,但这是正确的编写方式(从某种意义上说,它会导致最有效、最容易理解、最容易测试和最容易修改)未来的变更请求)。

Board.getGamePiece(p).getMovement();

对比

Board.getMovement(p);

这是我的观点,但是,任何从 LoD 的角度对这些行发表的评论都是观点,如果有人试图告诉你它不是,那他们就错了: )

在 LoD 的意义上,这些是完全相同的,并且此代码(任一版本)都完全没问题。

重点是:两者都意味着您了解游戏棋子这样的概念,并且棋子可以移动。两行代码也以某种方式或形式返回 Movement,因此在任何一种情况下,此代码不仅知道“游戏件存在”和“它们可以移动”,而且“这就是move 的样子以及如何与之交互'。

你写board.getMovement(p)一无所获。

去掉这些模糊的概念,你就会开始有所收获。如果您已将 board.advance() 编写为一种方法,它通过询问每个棋子想要进行的运动来应用 1 回合的事件,然后移动所有棋子并进行处理,例如某些部分现在已经损坏,那么您现在涉及的概念要少得多:运行 board.advance() 的代码知道有一个棋盘,并且有诸如转弯之类的东西,并且您可以前进一个转。

代码不需要知道碎片存在,或者它们可以移动。

将 'LoD' 翻译成 Java 的任何代码如下:a.method1().method2() 必然是 LoD 的中断,好吧,随意这样做。但是,如果您将其混为一谈并最终得到:

  1. a.method1().method2() 打破了 LoD。
  2. 打破 LoD 是一种糟糕的代码风格,会导致代码难以维护。
  3. 因此,a.method1().method2() 是糟糕的代码。

然后你在某个地方搞砸了。它不是;严格应用此原则将导致您复制大量代码并从程序员级别添加更多依赖项(现在 board 中的代码需要了解更多关于哪些部分可以做什么,而不是如果您不这样做)不要这样做)。

这让我们学到了关于这种模糊的风格指南的另一课:它们几乎总是直接竞争。如果您尝试针对 LoD 进行“优化”,则很可能会导致大量其他规则(例如 DRY)失败。

最终的目标是编写可维护的代码。这比尝试应用一些死记硬背的概念(例如“避免a.x().y()”)要困难得多。编程很难。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...