The problem Let’s assume that we have three components: , and . A B C Another component, , has a dependency to and wants to call a method foo that belongs to component : Main A C a.getB().getC().foo(); The previous snippet is equivalent to: B b = a.getB();C c = b.getC();c.foo(); The problem with this code is that in order to call foo, needs to go all the way through components and to reach and finally invoke that method. needs to know all the 3 components, along with their internal structure, in order to be able to invoke that call. Main A B C Main The dotted lines represent the dependencies of the components and the arrows represent the calls Although our example is oversimplified, we could say that needs to know which method to call in order to obtain from , from and call . Moreover, the intermediate components ( and ) need to provide some API to support these chained calls. Clearly, such API changes their nature. Component should not act as a provider of component but instead have an API that justifies its existence. The problem is that we described here is a violation of the . Main B A C B foo B C A B Law of Demeter The Law of Demeter is a very simple guideline that helps us to write components that are not tightly coupled. The summarizes the Law of Demeter it the following 3 simple sentences: Wiki Page each unit should have only limited knowledge about other units: only units “closely” related to the current unit. each unit should only talk to its friends; don’t talk to strangers. only talk to your immediate friends. In OOP we learn that objects communicate with each other by passing messages, so a method call is actually message sent from the caller to the callee. For example, simply means that sends a message to for . In the second snippet, it is obvious that is responsible for sending all the messages, leaving the intermediate components without any actual logic other than giving their internal components. a.getB() Main A“asking” B Main Now let’s think about what needs to do. It needs to invoke foo but all it knows is component . It doesn’t need to for all the other components. It doesn’t even need to know they exist. All it needs to do is to component to find and call the method . will probably delegate this task to and will do something similar with . In this case, component what to do. Main A “search” “tell” A foo A B B C A “tells” B Advantages The Law of Demeter has some very beneficial implications. Each component interacts only with its direct dependencies. No indirect dependencies are known, which makes it easier to change their implementation independently. Imagine if we changed the implementation of component to call some component instead of component . With chain calls, such decisions are propagated to the caller. has to change in order to adopt this change. A X B Main Testing is also, a lot easier. In our example, we would have to mock all the intermediate components, which is clearly a design smell. Actually, when we write tests, it is easy to identify the code smell by noticing how many useless mocks we have to create. These are side effects of internal implementation leaking and poor encapsulation that lead to tightly coupled components. The Law of Demeter helps the design of the system by making the components more autonomous/decoupled, which is, in my opinion, the most important advantage. Law of Demeter in microservices In the world of microservices, components can be services located in different places across the network. The most important difference is that all the calls between components are now remote calls, thus failure is actually a possible scenario. Consider in our example, if each invocation was a remote call. How fragile would be when it does 3 remote calls to different components/services? Of course, even if we apply the Law of Demeter, 3 messages would have to be passed along the components in order to get the result of but now communicates only with the 1 component that needs to. As we will see in following paragraphs, this change in the communication protocol has a very big gain in terms of availability and performance. getComponent() Main foo() Main Usually, in order to tackle the problems of component failures and increase the performance and the resilience of our system we use event-driven architectures. In an event-driven architecture, the communication between microservices is achieved by sending an event to an event dispatcher instead of sending the message directly to the component we want to invoke. The callee listens for these events and processes them when they become available. These events are sent asynchronously to the dispatcher. More on event-driven architecture can be found in . this post The invocation is conceptually the same as sending the event with this invocation to a dispatcher where component has subscribed to these events. This extra level of indirection decouples the components more since the caller doesn’t need to know how to call but the fact that the communication is asynchronous means that in some cases the caller doesn’t have to wait for to finish its processing. In our example, if were actually a method that sends a notification or an email, the caller wouldn’t have to wait for this task to be completed. a.bar() A A A foo() Even if we use asynchronous communication in our example, when violating the Law of Demeter, there are still a few problems with the design due to the fact that the events that sends depend on each other. asks component for , in order to be able to ask component for etc. This chattiness is required for the construction of the final event. can’t send the event of invoking foo to before returns (actually will return the location of ). Also, in case one of the intermediate components/services is not available would not be able to construct the final event to send to , thus would not be able to complete its process and, depending on the business rules, it could fail to accomplish its task. In this case, the unavailability of the indirect components is propagated to . Main Main A B B C Main C B C B C Main C Main Main This design also has some problems in terms of performance. could have written the event of calling foo immediately and continue doing something useful instead of discovering other components. Main All these problems are the implications of the fact that instead of what it needs it tries to find a way of completing a large part of its task by the other components to gather information. One could say that acts like it does not trust the other components! Main “telling” “asking” Main Obviously, if we design our system in a way that doesn’t violate the Law of Demeter these problems go away for free. will send just 1 event and continue its tasks even if the other components are not available. Since sends only 1 event, there are no extra steps in order to create this event as there were previously so the communication protocol has been optimized. Clearly, the availability of doesn’t depend on the availability of the other components (except the event dispatcher). has completed its task just by what needs to be done. The other components will get the event from the dispatcher when they become available again. almost Main Main Main Main “telling” eventually We should design our components to be as loosely coupled as possible and Law of Demeter is a good way to go towards that direction. Further Reading: https://martinfowler.com/bliki/TellDontAsk.html https://pragprog.com/articles/tell-dont-ask