'Array#dig'或'Hash#dig'方法是否违反了得墨忒耳法?

时间:2016-01-18 00:36:13

标签: ruby syntax law-of-demeter

dig方法:

  

通过在每一步调用dig来提取由idx对象序列指定的嵌套值,如果任何中间步骤为nil,则返回nil。

这意味着:

[1, {foo: :bar}].dig(1, :foo)

通过依次对:bar对象和Array对象执行查找来返回Hash

dig的第一次调用是在Array对象上进行的,但下一次调用dig是对Hash对象返回的Array对象进行的

使用dig是否违反Law of Demeter

2 个答案:

答案 0 :(得分:1)

dig几乎就是阵列上的语法糖和你在引入方法之前执行的哈希访问,所以它不会比你已经更多或更少违反Demeter法则。考虑一下你的例子:

[1, {foo: :bar}].dig(1, :foo)
[1, {foo: :bar}][1][:foo]

您拥有相同的数据结构,但您获得了相同的价值,但令人愉快的是,现在您不必每一步都检查nil

得墨忒耳定律是一种设计启发式算法。如果你发现自己通过三个对象来完成某些事情,那么进行覆盖的代码必须知道所有这三个对象的事情。这是一个迹象,表明您可能希望重构以减少模块所具有的依赖项数量,但是用于进行覆盖的方法,无论是[]还是dig,都不是完全相关。

答案 1 :(得分:1)

是的,可以说是的。但是,除了通常的方法之外,hash[:foo][:bar][:baz]或(更安全)hash[:foo] && hash[:foo][:bar] && hash[:foo][:bar][:baz]也是如此。 dig是这些的捷径。

我认为你走在正确的轨道上,使用嵌套的哈希来传递复杂的数据类似于违反了得墨忒耳法则,无论是否使用挖掘,它都是在做法律的事情德米特的意思是反对。从某种意义上说,您的代码需要了解哈希的结构,而不是仅使用明确的API调用方法。然后人们可以说dig正在采取一种违反经常做的LoD的方式 - 并且使其更容易做,纯粹主义者可以说这是一个坏主意。

但是在实际编程中,至少在红宝石中,德米特定律更像是一个普遍的好主意,而不是真正遵循的法律。

还有人可能会争辩说,dig在某种程度上可以避免在没有它的情况下发生的LoD违规行为。 技术使用dig时,您不再违反LoD,因为您现在只需要调用一个方法(一个dig调用)您可以直接引用的对象。我不认为技术性问题太重要,无论如何你都是在做同样的事情。