La loi de Demeter désigne un principe simple : une classe doit uniquement interagir avec ses dépendances directes, sans manipuler d’éléments qui ne lui ont pas été explicitement confiés ni remonter la chaîne des dépendances pour atteindre des objets plus lointains.
Essayons de l'illustrer avec l'exemple suivant :
class Car
{
public function __construct(
protected Engine $engine,
) {}
public function isRunning(): bool
{
return $this->engine->state->isRunning();
}
}
La ligne state->isRunning()
peut sembler anodine mais trahit une dépendance cachée, la classe Car
ne se contente plus de collaborer avec Engine
... elle interroge un détail interne de cette dernière qui ne la concerne pas.
Elle se met à dépendre d’une classe qu’elle n’a jamais rencontrée, qu’elle n’a pas demandée et dont elle ne devrait rien savoir : une dépendance transitive vient d'apparaître.

Le State
est un détail technique de Engine
, le besoin fonctionnel de la classe Car
est de savoir si le moteur tourne ... et non comment il tourne.
Cette situation transgresse la Loi de Demeter et est symptomatique d'un couplage excessif : une dépendance implicite vient de naître cachée dans une chaîne d’appels et comme toute les dépendances, elle rend l’architecture des classes plus rigide et plus vulnérable aux changements.
« The reason why the code is rigid is that the modules depend on each other in undesirable ways »
— Robert C. Martin
Ce genre de couplage passe souvent inaperçu car il n’apparaît pas dans la signature du constructeur, il reste insidieux tout en influençant profondément les dépendances d'une classe.
Si demain la classe State
évolue, ce ne sera plus seulement Engine
qu’il faudra adapter ... mais aussi Car
qui pourrait subir des effets de bords :

Tester une classe devient plus complexe lorsqu’on introduit des dépendances transitives et qu’on ne respecte pas le principe de Demeter : on se retrouve à devoir simuler non seulement les dépendances directes mais aussi les dépendances de ces dépendances, cette chaîne indirecte rend les tests plus fragiles et le système plus difficile à faire évoluer sereinement.
Pour éviter cela et minimiser le couplage, Engine
doit assumer la responsabilité de déterminer s’il est en fonctionnement ou non en encapsulant ce comportement plutôt qu'en exposant son état à l’extérieur de classe :
class Car
{
public function __construct(
private Engine $engine,
) {}
public function isRunning(): bool
{
return $this->engine->isRunning();
}
}
class Engine
{
public function __construct(
private State $state,
) {}
public function isRunning(): bool
{
return $this->state->isRunning();
}
}
class State
{
public function isRunning(): bool
{
return true;
}
}
Désormais, la lecture devient plus fluide car chaque classe interagit uniquement avec ce qu’elle connait, les relations sont plus claires, plus explicites et nous n'avons plus à remonter des chaînes d’objets pour accéder à une information.
Cette manière d’organiser le code n’est pas seulement plus élégante elle est aussi plus stable. En limitant les dépendances aux relations immédiates, on crée naturellement une architecture à la fois modulaire et plus résistante aux changements : les objets deviennent plus autonomes, plus faciles à tester et également plus faciles à faire évoluer.

Pour résumer, la Loi de Demeter recommande qu’une classe dépende uniquement des éléments qu’elle utilise directement afin de préserver la clarté et limiter le couplage : chaque objet doit se limiter à ce qu’on lui confie, sans chercher à contourner ses dépendances.
Un code enchaînant les appels vers des objets internes multiplie les points de fragilité, sa structure devient plus difficile à maintenir et les effets de bord plus difficiles à anticiper. On y perd en lisibilité, en testabilité et surtout en maîtrise des dépendances.
Mieux vaut s’en tenir à des interactions directes, explicites et limitées au strict nécessaire, c’est souvent ce qui distinguera un code souple d’un code fragile.
« Software entities should not depend on things they don’t directly use »
— Robert C. Martin