Php,为什么破坏德米特定律如此糟糕?

Joh*_*ith 0 php law-of-demeter

我知道它被认为是坏的:

$this->laptop->getKeyboard()->getTouchpad()->getLbutton();
Run Code Online (Sandbox Code Playgroud)

要么

$this->laptop->getKeyboard()->getCapslock()->isLedOn();
Run Code Online (Sandbox Code Playgroud)

它被解释为"我们不想要大量的 - > - > - > - >" - 但我想让这种结构变得有形,我的意思是它不能脱钩.我理解,如果架构师改变了,它必须在任何地方完成,但它不会发生.再说一次,如何解决这个问题?

wor*_*oru 6

Demeter法是关于依赖性而不是 - >(或其他语言中的点).

例如,如果您有一个流畅的界面(方法返回此),该法律不适用.

您希望您的课程依赖于最少数量的其他课程.

如果你的班级依赖于其他10个班级,那么任何一个班级的改变都可以打破它.理解你班级的作用更难.测试这样的课程也很难.

如果你有$field->getDependency1()->getDependency2()或者没关系$field->dependency1->dependency2- 你的代码仍然依赖于其他两个类并且知道dependency1的内部结构(它内部有dependency2).

您可以通过告诉不要求原则来解决您的问题.在OOD中,您不希望使用仅包含数据的结构.您希望拥有知道如何处理其字段的对象.

例如,你可以重构:

$oldBalance = $bank->getAccount()->getBalance();
$bank->getAccount()->setBalance($oldBalance - $amount);
Run Code Online (Sandbox Code Playgroud)

至:

$bank->withdraw($amount);
Run Code Online (Sandbox Code Playgroud)

在银行类:

function withdraw($amount) {
    $this->account->withdraw($amount);
}
Run Code Online (Sandbox Code Playgroud)

在Account类中:

function withdraw($amount) {
    $this->balance = $this->balance - $amount;
}
Run Code Online (Sandbox Code Playgroud)

你有更多的方法,但现在使用$ bank的代码,对账户及其余额一无所知.您可以轻松地测试该类仅模拟$ bank字段.您还有更多可重用的代码.


Jar*_*zyk 6

想象一下这个对话:

You: Hey Laptop, get me the I/O devices
Laptop: There you go
You: Hey IODevices, get me the keyboard
IODevices: There you go
You: Hey Keyboard, get me the touchpad
Keyboard: There you go
You: Hey Touchpad, I want to press your left button
Touchpad: Consider it done Boss!
Run Code Online (Sandbox Code Playgroud)

男人,你是怪物电子迷,或者你是为了生活 - 你知道你的笔记本电脑的每一小块!;)

与此:

You: Hey Laptop, I want to press left button on the touchpad
// Laptop gets the job done
Laptop: Done Boss!
Run Code Online (Sandbox Code Playgroud)

在第二次谈话中,引擎盖下,

  1. Laptop调用它的依赖IODevices(你不需要知道任何关于它的东西),
  2. IODevices调用它的依赖Keyboard(Latop不需要知道它),
  3. Keyboard得到它的依赖Touchpad(IODevices不需要知道它 - 实际上这是一个不好的例子,但是......你明白了)然后调用pressLeftButton()它.

也就是说,你不关心细节,你想要做的就是pressLeftButton.您不需要知道如何KeyboardTouchpad相关,从每个方法等返回什么.您有必须实现的公共接口.

这使得每个人都高兴,因为当你更换什么可以打破KeyboardXyzKeyboardAbc,只要后者实现了相同的接口.