Here is an example of such a composition in the code, as I understand it violates the principle of minimal awareness (Principle of Least Knowledge) ( see the Law of Demeter ):

class A: def method1(self): pass def method2(self): pass def method3(self): pass class B: def __init__(self): self.a = A def method1(self): pass b = B() bamethod1() 

However, I noticed that they often use this approach to extend the class interface.

An example from Java and C #:

 System.out.println() 

Example from Django:

 MyModel.objects.create() 

So it is interesting when to expand the class in this way can be considered correct?

    2 answers 2

    Restrictions are imposed according to common sense and subject area.

    I will write about the person. A person, in most cases, can move his limbs, think with his head and do some other actions that are rather superficial. If you are writing a game and the people there are not subject to any modifications, then they should have the same operations as in real life. It should be borne in mind that for honey. equipment or games with people modification - access can be much wider.

    A simple example is человек.рука.двигать() .

    Whatever happens in the implementation, such a code will remain valid and should not turn into a person человек.ДвигатьРукой() человек.Двигать(рука) человек.ДвигатьРукой() or person человек.ДвигатьРукой() человек.Двигать(рука) .


    At the same time, people do not know how to control specific muscles in the hand, for example, which means that the object must hide the implementation guides.

    Those. рука.Двигать() but not рука.мышцы[x].двинуть(y, z) .


    Even easier - when a property is necessary and invariably, substantiated by the subject area - you can refer to it, otherwise it should be hidden by the main class.

    • рука.мышцы what the рука.мышцы is человек.рука рука.мышцы different from the рука.мышцы . Rarely, but sometimes a человека no рук . That is, exactly where the border between “such a property is always there and we can refer to it” and “such a property is not always and it cannot be addressed” - Kromster
    • @Kromster is a complex domain level question. If you are engaged in medical equipment - you may need access to the arm muscles, I do not argue. In all other cases, access to them must be closed to imitate the real world. PS: and if there are no hands, then this is a typical NRE , let it pour in. - Monk
    • therefore, it would be good to clarify according to what criteria the properties are permissible to cause a train or not. - Kromster
    • Direction thought understood. Thanks for the clarifications. - Mr Fix
    • 3
      @Mrfix do not rush to accept the answer, maybe someone will write more clearly. Anyway, glad to help. - Monk

    First you need to understand what the problem is when one object puts its insides outward, after which it becomes clear when this is not a problem.

    Encapsulation and information hiding is intended to simplify development. Good design allows you to focus on the minimum number of concepts at one point in time and limit the number of changes to the minimum number of modules in case of changing requirements.

    When an object exposes its insides outward, this can lead to a more fragile solution. By its nature, an open class interface should be more stable, and implementation details hidden from its clients. In this case, the implementation can be replaced without disturbing the customers.

    When implementation details are leaked into an open interface, in the form of open fields or even properties, this limits the ability of the class author to change. The code of the form ABCDEFoo() has low stability, since making changes to one of the 5 classes will probably break it.

    On the other hand, not every open property reveals implementation details. Sometimes, these properties are part of the essence of the problem being solved. For example, a square has coordinates and a reversal of the form: square.Position.X may well be justified.

    Sometimes, you have to break this rule for another reason, for example, when developing libraries.

    Any complex system is hierarchical, and we just need to group related concepts. The same System.out from the Java world is a similar example. We want to combine all system operations behind a certain facade, which will be a convenient entry point for research. In this regard, we are not going to move out to another class, and we definitely will not duplicate operations from PrintStream in the System class.

    So, as a conclusion: the law of Demeter is not violated if the whole-part relationship is part of the subject area. The law of Demeter is not violated in the case of facade classes, the only task of which is to provide access to some objects.

    But the law of Demeter is violated if the exhibited property is an implementation detail that may change in the future.

    • one
      The façade class generally hides the interfaces of the classes it holds, behind its interface, and does not provide access to them. - Mr Fix
    • I agree, in this case it is not quite a facade, but also not a class with its own behavior. - Sergey Teplyakov