带有数据模型对象的得墨忒耳定律 [英] Law of Demeter with data model objects

查看:11
本文介绍了带有数据模型对象的得墨忒耳定律的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

为了便于我们遵守 Demeter 定律:一个模块不应该知道它所操纵的对象"的内部结构.由于数据结构不包含任何行为,它们自然地暴露了它们的内部结构.所以在这种情况下,德米特不适用.

我承认我不得不复习我对 LoD 的了解,但在我的一生中,我找不到任何迹象表明这符合法律精神.我们模型中的 getter/setter 都不包含任何业务逻辑,这是他这样做的理由,因此这些对象的客户端不必了解 get/set 方法中是否正在执行某些业务逻辑.

我认为这是对需要对象结构的内部知识"的含义的误解,或者至少是过于字面化并在此过程中打破了非常标准的约定.

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

解决方案

Robert Martin 写的名为 Clean Code 的书涵盖了这一点.

在第 6 章(对象和数据结构)中,他谈到了对象和数据结构之间的根本区别.对象受益于封装,而数据结构则不然.

有一节是关于迪米特法则的:

<块引用>

有一个著名的启发式方法,称为德米特法则,它说模块不应该了解它操纵的对象的内部结构.正如我们在上一节中看到的,对象隐藏其数据并公开操作.这意味着对象不应通过访问器暴露其内部结构,因为这样做是暴露而不是隐藏其内部结构.

更准确地说,得墨忒耳定律说 C 类的方法 f 应该只调用这些方法:

  • C
  • f 创建的对象
  • 作为参数传递给 f 的对象
  • 保存在 C 实例变量中的对象

该方法不应调用由任何允许的函数返回的对象的方法.换句话说,与朋友交谈,而不是与陌生人交谈.

Bob 大叔举了一个 LoD 违规的例子:

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

<块引用>

这是否违反了 Demeter 取决于 ctxt、Options 和 ScratchDir 是对象还是数据结构.如果它们是物体,那么它们的内部结构应该隐藏而不是暴露,因此了解它们的内部结构显然违反了得墨忒耳法则.另一方面,如果 ctxt、Options、ScratchDir 只是没有行为的数据结构,那么它们自然暴露了它们的内部结构,所以 Demeter 不适用.

访问器函数的使用混淆了这个问题.如果代码是这样写的,那么我们可能就不会问 Demeter 违规了.

final String outputDir = ctxt.options.scratchDir.absolutePath;

所以这可能是您的同事来自哪里.我认为我们必须这样做是因为 LoD"的论点充其量是不精确的.核心问题不是 LoD,而是 API 是由对象还是数据结构组成.当有更紧迫的事情要做时,它似乎是一种不必要且容易出错的改变.

I came back to work from vacation yesterday, and in our daily standup, my teammates mentioned they were refactoring all of the model objects in our java code to remove all getters and setters and make the model fields all public objects instead, invoking the Law of Demeter as the reason for doing so because

to facilitate the our adherence to Demeter's law: a module should not know about the innards of the 'objects' it manipulates. Since data structures contain no behavior, they naturally exposes their internal structure. So in that case, Demeter does not apply.

I admit I had to brush up on my knowledge of the LoD, but for the life of me I can't find anything to indicate that this is within the spirit of the law. None of the getters/setters in our models contain any business logic, which is his justification for doing this so clients of these objects don't have to understand whether or not there is some business logic being executed within the get/set methods.

I think this is a misunderstanding of what it means to need 'internal knowledge of an objects structure', or at the very least is taking it too literally and breaking a pretty standard convention in the process.

So my question is, does it actually make any sense to expose model objects internal structure directly instead of via getters/setters in the name of the LoD?

解决方案

There is a book called Clean Code by Robert Martin that covers this.

In Chapter 6 (Objects and Data Structures) he talks about fundamental differences between objects and data structures. Objects benefit from encapsulation, data structures don't.

There is a section about the Law of Demeter:

There is a well-known heuristic called the Law of Demeter that says a module should not know about the innards of the objects it manipulates. As we saw in the last section, objects hide their data and expose operations. This means that an object should not expose its internal structure through accessors because to do so is to expose, rather than to hide, its internal structure.

More precisely, the Law of Demeter says that a method f of a class C should only call the methods of these:

  • C
  • An object created by f
  • An object passed as an argument to f
  • An object held in an instance variable of C

The method should not invoke methods on objects that are returned by any of the allowed functions. In other words, talk to friends, not to strangers.

Uncle Bob gives an example of a LoD violation:

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

Whether this is a violation of Demeter depends on whether or not ctxt, Options, and ScratchDir are objects or data structures. If they are objects, then their internal structure should be hidden rather than exposed, and so knowledge of their innards is a clear violation of the Law of Demeter. On the other hand, if ctxt, Options, and ScratchDir are just data structures with no behavior, then they naturally expose their internal structure, and so Demeter does not apply.

The use of accessor functions confuses the issue. If the code had been written as follows, then we probably wouldn’t be asking about Demeter violations.

final String outputDir = ctxt.options.scratchDir.absolutePath;

So this is probably where your co-workers are coming from. I think the argument "we have to do this because LoD" is imprecise at best. The central issue isn't LoD so much as whether the API consists of objects or data structures. It does seem like an unnecessary and error-prone change to push through when there are more pressing things to do.

这篇关于带有数据模型对象的得墨忒耳定律的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆