Cohesion, Cohesion and the Law of Demeter

The law of Demeter indicates that you should only speak with objects that you know directly. That is, do not follow the chain of methods to talk with other objects. When you do this, you establish incorrect connections with intermediate objects, improperly coupling your code to another code.

This is bad.

The solution will be that the class you know about substantially exposes simple wrappers that delegate responsibility for the object with which it relates.

It's good.

But this, apparently, leads to the fact that the class has low cohesion . He is no longer responsible for what he does, but also has delegates, which in a sense makes the code less cohesive, duplicating parts of the interface of the object associated with it.

This is bad.

Does this really reduce cohesion? Is this the lesser of two evils?

Is this one of those gray areas of development where you can discuss where this line is, or are there strong, principled ways of deciding where to draw the line and what criteria you can use to make this decision?

+60
oop refactoring law-of-demeter cohesion
Oct 02 '08 at 15:40
source share
6 answers

Grady Butch in "Object-Oriented Analysis and Design":

“The idea of ​​cohesion also comes from structured design. Simply put, cohesion measures the degree of connectivity between elements of a single module (and for object-oriented design, one class or object). The least desirable form of cohesion is a coincidence in which absolutely unrelated abstractions are thrown into one class or module, for example, consider a class containing abstractions of dogs and spacecraft whose behavior is completely unrelated.The most desirable form of linkage is a functional Very, in which elements of the class or module work together to provide a well-bounded behavior. Thus, the class Dog is functionally united, if it covers the semantics of the dog, all dogs and nothing but the dog. "

Provide the Dog with the Client in the example above, and that might be a little clearer. Thus, the goal is simply to aim at functional cohesion and move as far away from coincidence as possible. Depending on your abstractions, this may be simple or may require some refactoring.

The combination of notes applies in the same way as to a “module” than to a single class, i.e. group of classes working together. Thus, in this case, the Customer and Order classes still have decent cohesion, because they have such a strong relationship, customers create orders, orders belong to customers.

Marcus Fowler says it would be more convenient for him to call this “Demon Offer” (see the article Mocks are not stubs ):

"Uterus testers are trying to talk more about avoiding train breaks - a chain of getThis (). GetThat (). GetTheOther () style chains. Avoiding a chain of methods is also known as Demeter’s law. Odor, the opposite problem of middle-aged objects, inflated by methods Forwarding is also a smell. (I always felt that I would be more comfortable with the Demeter Act if it was called Demeter Offer .) "

That I perfectly understand where I come from: it is quite acceptable and often it is necessary to have a lower level of cohesion than strict observance of the "law" may be required. Avoid matching cohesion and focus on functional grip, but do not suspend it in settings where it is necessary for a more natural combination with the abstraction of your design.

+43
03 Oct '08 at 5:47
source share

If you break the Law of Demeter, having

int price = customer.getOrder().getPrice(); 

the solution is not to create getOrderPrice () and convert the code to

 int price = customer.getOrderPrice(); 

but instead, it should be noted that this is the smell of code and make the appropriate changes, which we hope will increase grip and lower connectivity. Unfortunately, there is no simple refactoring that always applies, but you probably should apply say don't ask

+20
02 Oct '08 at 15:53
source share

I think you may have misunderstood what cohesion is. A class that is implemented in terms of several other classes does not necessarily have low cohesion if it is a clear concept and has a clear goal. For example, you may have a class Person , which is implemented in terms of the Date (for date of birth), Address and Education (list of schools where the person went to). You can provide wrappers in Person to get the year of birth, to the last school that the person went to, or to the state in which he lives, so as not to question the fact that Person is realized from the point of view of these other classes. This would reduce grip, but it would make Person no less cohesive.

+6
Oct 02 '08 at 16:00
source share

Its a gray area. These principles are designed to help you in your work, if you find that you work for them (i.e. they interfere with you and / or you complicate it, complicate your code), then you are too diligent and you need to back off.

Do it for you, do not work for it.

+3
Oct 02 '08 at 16:01
source share

I don’t know if this really reduces grip.

Aggregation / composition is all about a class that uses other classes to conform to the contract that it provides through its public methods. The class should not duplicate the interface of related objects. This actually hides any knowowledge about these aggregated classes from the calling method.

To obey the law of Demeter in the case of several levels of class dependency, you just need to apply aggregation / composition and good encapsulation at each level.

In other words, each class has one or more dependencies on other classes, however, it is only dependencies on the reference class, and not on any objects returned from properties / methods.

+1
02 Oct '08 at 16:00
source share

In situations where there seems to be a compromise between communication and cohesion, I would probably ask myself: “If someone else wrote this logic and I looked for an error in it, where would I look first?”, and write the code this way.

0
Oct 02 '08 at 15:45
source share



All Articles