【问题标题】:Do the 'Array#dig' or 'Hash#dig' methods violate the Law of Demeter?'Array#dig' 或 'Hash#dig' 方法是否违反得墨忒耳法则?
【发布时间】:2016-01-18 00:36:12
【问题描述】:
dig 方法:
通过在每一步调用 dig 提取由 idx 对象序列指定的嵌套值,如果任何中间步骤为 nil,则返回 nil。
这意味着:
[1, {foo: :bar}].dig(1, :foo)
通过依次查找Array 对象和Hash 对象来返回:bar。
对dig 的第一次调用是在Array 对象上进行的,但对dig 的下一次调用是在从Array 返回的Hash 对象上进行的。
dig的使用不违反Law of Demeter吗?
【问题讨论】:
标签:
ruby
syntax
law-of-demeter
【解决方案1】:
dig 几乎只是您在引入该方法之前执行的数组和散列访问的语法糖,因此它不会比您已经违反的或多或少违反得墨忒耳定律。考虑你的例子:
[1, {foo: :bar}].dig(1, :foo)
[1, {foo: :bar}][1][:foo]
你有相同的数据结构,你得到相同的值,但令人高兴的是,现在你不必在每一步都检查nil。
得墨忒耳法则是一种设计启发式。如果您发现自己通过三个对象来完成某件事,那么执行此操作的代码必须了解所有这三个对象的相关信息。这表明您可能想要重构以减少模块所具有的依赖项的数量,但是您用来进行访问的方法,无论是 [] 还是 dig,并不完全相关。
【解决方案2】:
是的,可以说。但并不比通常的做法更重要,hash[:foo][:bar][:baz] 或(更安全)hash[:foo] && hash[:foo][:bar] && hash[:foo][:bar][:baz]。 dig 是这些的快捷方式。
我确实认为您走在正确的轨道上,即使用嵌套哈希来传递复杂数据类似于违反得墨忒耳法则,无论是否使用 dig,它都在做得墨忒耳法则的意思反对。从某种意义上说,您的代码需要了解哈希的结构,而不仅仅是调用具有清晰 API 的方法。然后可以说dig 违反了经常发生的 LoD 行为——并使其更容易做到,而纯粹主义者可能会说这是一个坏主意。
但在实际编程中,至少在 ruby 中,得墨忒耳法则更像是一个一般性的好主意,而不是一个要盲目遵循的实际法则。
也有人可能会争辩说,dig 在某些方面避免了在没有它的情况下发生的 LoD 违规。 技术上当使用 dig 时,您不再违反 LoD,因为您现在只是在您拥有的对象上调用 one 方法(一个 dig 调用)直接参考。我不认为技术性太重要了,无论哪种方式你都在做同样的事情。