0

The dig method:

Extracts the nested value specified by the sequence of idx objects by calling dig at each step, returning nil if any intermediate step is nil.

This means that:

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

returns :bar by performing a lookup on an Array object and on the Hash object in turn.

The first call to dig is made on an Array object but the next call to dig is made on the Hash object returned from the Array.

Does the use of dig not violate the Law of Demeter?

gnerkus
  • 11,357
  • 6
  • 47
  • 71

2 Answers2

1

dig is pretty much just syntactic sugar on the array and hash accesses you performed before the method was introduced, so it doesn't violate the Law of Demeter any more or less than you already were. Consider your example:

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

You have the same data structure, you're getting the same value, but pleasantly, now you don't have to check for nil every step of the way too.

The Law of Demeter is a design heuristic. If you find yourself reaching through three objects to accomplish something, the code doing the reaching has to know things about all three of those objects. It's a sign that you might want to refactor to reduce the number of dependencies your modules have, but the method you use to do the reaching, whether [] or dig, isn't entirely relevant.

Kristján
  • 18,165
  • 5
  • 50
  • 62
1

yes, arguably. But no more so than the usual ways of doing this, hash[:foo][:bar][:baz] or (more safely) hash[:foo] && hash[:foo][:bar] && hash[:foo][:bar][:baz]. dig is a shortcut for these.

I do think you are on the right track that using nested hashes to pass around complex data is akin to a violation of the Law of Demeter, whether using dig or not, it's doing the kind of thing the Law of Demeter is meant against. In the sense that your code needs to know about the structure of the hash, instead of just calling methods with clear API's. One could then say that dig is taking a kind of violation of the LoD that was being oftenly done -- and making it even easier to do, which a purist could say was a bad idea.

But in practical programming, in ruby at least, the Law of Demeter is more of a general good idea to consider than an actual Law to be followed slavishly.

And one could also argue that in some ways dig avoids the LoD violations that were happening without it. Technically when using dig you are no longer violating the LoD, as you are now just calling one method (the one dig call) on the object you have a direct reference to. I don't think that technicality matters too much, you are really doing the same thing either way.

jrochkind
  • 22,799
  • 12
  • 59
  • 74