Nickewas
Nickewas

Reputation: 49

Is this a good example of Law of Demeter?

I'm studying for an oral exam, and I wonder if I have understood Law of Demeter correctly. In essence, I have understood that the Law of Demeter aims to loosen coupling by making classes less dependent on one another, and by not giving away explicitly how the classes get certain information. This is concluded in the quote "Only talk to your immediate friends". I have come up with this simplified example:

If we have a class Board and we have game pieces on our playing field and for example want to find out which pieces have moved an intuitive way to find this out would be to write something like:

Board.getGamePiece(p).getMovement();

But this violates the Law of Demeter. We thus delegate that task to the getMovement method by simply writing:

Board.getMovement(p);

Have I understood it correctly and are there any errors within my explanation? I am a bit unsure as to how to use the term "delegate" here, is it used correctly in my example?

Upvotes: 0

Views: 444

Answers (2)

rzwitserloot
rzwitserloot

Reputation: 103273

I have understood Law of Demeter correctly

It's a nebulous, unscientific principle. It's not like the law of gravity, and it's not like a language specification. You're elevating it as a binary concept (code either violates it or it does not). This is doubly wrong:

  • It's a matter of opinion, and it's shades of gray. There is no such thing as 'this code violates it, and this code doesn't'.
  • It's a guideline, not a rule. Sometimes writing code that many would agree is a total violation of this principle is nevertheless the correct way to write it (in the sense that it leads to the most efficient, easiest to understand, easiest to test, and easiest to modify in the face of future change requests).

Board.getGamePiece(p).getMovement();

vs

Board.getMovement(p);

This is my opinion, but, then, any comment on these lines in the perspective of the LoD is opinion, and if someone tries to tell you it isn't, they're wrong :)

These are, in the sense of LoD, completely equal, and this code (either version) is completely fine.

The point is: Both imply that you have knowledge of the concept that there is such a thing as a game piece, and that pieces can move. Both lines of code also return a Movement in some way or form, so in either case, this code isn't just aware that 'game pieces exist' and 'they can move' but also 'and this is what a move looks like and how to interact with it'.

You've gained nothing by writing board.getMovement(p).

Remove these nebulous concepts and you start getting somewhere. If you had written board.advance() as a method, which applies 1 turn's worth of events by asking each piece for the movement it wants to make, then moving all pieces and processing e.g. that some pieces have now taken damage, then you now have considerably fewer concepts involved: The code that ran board.advance() knows that there is a board, and that there is such a thing as turns, and that you can advance by one turn.

The code does not need to know that pieces exist, or that they can move.

Translating 'LoD' into java as any code that looks like: a.method1().method2() is necessarily a break of LoD, well, feel free to do that. However, if you mix that up a bit and end up at:

  1. a.method1().method2() breaks LoD.
  2. Breaking LoD is bad code style and leads to hard to maintain code.
  3. Thus, a.method1().method2() is bad code.

Then you messed up somewhere. It isn't; rigorous application of this principle will then cause you to duplicate a ton of code and adds MORE dependencies from the level of the programmer (now the code in board needs to know much more about what pieces can do than if you didn't do this).

This gets us to another lesson about such nebulous style guidelines: They are almost always in direct competition. If you try to 'optimize' for LoD, you will most likely fail a ton of other rules such as DRY.

In the end the goal is to write maintainable code. This is a lot harder than trying to apply some rote concepts such as 'avoid a.x().y()'. Programming is hard.

Upvotes: 2

pantulis
pantulis

Reputation: 1705

I think you grok the idea but I'm not sure if your example really makes sense. In the context of a board game, it's difficult for the Board to not be concerned with the possible movements! (So applying Demeter here would not make sense as possible the Board already has access to the Movement class).

Upvotes: 1

Related Questions