Ley de Demeter: No hables con extraños

La Ley de Demeter es un principio muy útil para reducir el acoplamiento entre clases y, cuando lo interiorizas, cambia bastante cómo diseñas tu código.

¿Qué es la Ley de Demeter?

La Ley de Demeter (también llamada “Ley de No Hables con Extraños”) la formuló Ian Holland en 1987 en la Universidad de Northeastern. Es un principio pensado para bajar el acoplamiento y subir la cohesión entre las clases de tu sistema.

El nombre viene de la mitología griega: Demeter era la diosa de la agricultura. La metáfora apunta a un software que crece sano, con cada clase desarrollándose de forma independiente sin crear dependencias innecesarias. Cursi, pero pega.

Mucha gente la considera la sexta regla no escrita de SOLID. Tiene sentido: encaja con la misma filosofía de reducir dependencias entre módulos.

Un método de una clase solo debe llamar a métodos de:

  1. La propia clase.
  2. Objetos que se pasan como parámetros.
  3. Objetos que se crean dentro de la clase.
  4. Objetos de variables de instancia.

Un método no debería llamar a métodos de objetos que se devuelven de otros métodos (chaining methods).

Ejemplo práctico de la Ley de Demeter

Vamos a ver un ejemplo práctico de cómo aplicarla.

Primero, un ejemplo que viola la Ley de Demeter:

class Money {
    public function getAmount();
}

class Discount {
    public function getPercentage();
}

class InvoiceLine {
    public function getMoney(): Money;
    public function getDiscount(): Discount;
}

class Invoice {
    private array $lines;

    public function getTotalPrice(): float
    {
        $total = 0;
        foreach($lines as $line) {
            $total += ($line->getMoney()->getAmount() - ($line->getMoney()->getAmount() * $line->getDiscount()->getPercentage() / 100));
        }
    }
}

Como puedes ver, para calcular el precio total de una factura se accede directamente a métodos de objetos que viven dentro de otros objetos: eso viola la Ley de Demeter.

Ahora veamos cómo refactorizarlo para cumplirla:

class Money {
    public function getAmount();
}

class Discount {
    public function getPercentage();
    public function applyDiscount(float $amount): float {
        return $amount - ($amount * $this->getPercentage() / 100);
    }
}

class InvoiceLine {
    public function getPrice(): float {
        $amount = $this->getMoney()->getAmount();
        return $this->getDiscount()->applyDiscount($amount);
    }
}

class Invoice {
    private array $lines;

    public function getTotalPrice(): float
    {
        $total = 0;
        foreach($lines as $line) {
            $total += $line->getPrice();
        }
    }
}

He creado un método applyDiscount en la clase Discount que aplica el descuento a un precio, y un método getPrice en InvoiceLine que calcula el precio de una línea aplicando ese descuento. Así Invoice deja de acceder a métodos de objetos que viven dentro de otros objetos.

Cuidado con llevar esto al extremo: a veces acabas creando métodos que no tienen sentido en la clase. Hay que buscar el equilibrio entre cumplir la Ley de Demeter y no forzar métodos que no pintan nada donde los metes.

Las soluciones a los problemas de la Ley de Demeter suelen ser muy específicas a cada caso, por lo que es importante analizar cada caso concreto para encontrar la mejor solución.

Conclusiones

La Ley de Demeter es un principio muy útil para estructurar tus clases con bajo acoplamiento y alta cohesión. Tenerla en el radar al diseñar el código se traduce en clases más limpias y mantenibles.

Sobre todo: analiza cada caso. A veces una violación de Demeter es la pista de que el dominio del sistema no está bien modelado y que hacen falta cambios más profundos en la estructura, no solo envolver la llamada en un método intermedio.

¿Conocías la Ley de Demeter? ¿La aplicas en tu código?

También puedes pasarte por mi canal de YouTube para ver el vídeo sobre la Ley de Demeter:

PD: Si tenéis cualquier duda podéis poneros en contacto conmigo enviando un DM a twitter.

Luis Miguel Martín
Luis Miguel Martín

CTO en LCApps. Escribo sobre Claude Code, MCP, agentes IA y arquitectura de software real.

💡

¿Te ha gustado este artículo?

Descubre patrones de diseño, decisiones técnicas y arquitecturas escalables.