Forem

Miguel Ángel Sánchez Chordi
Miguel Ángel Sánchez Chordi

Posted on

2

La ley de Demeter (LoD)

El tema que nos ocupa este post lleva el nombre de Deméter o Demetra, la diosa griega de la agricultura cuyo nombre se puede traducir como diosa madre o madre distribuidora. Y quizá sea esta ultima traducción la que inspiró a la gente de la Universidad Northeastern de Boston cuando la usaron para dar nombre a la ley que nos ocupa.

El objetivo de la Ley de Demeter es evitar el excesivo acoplamiento de nuestras clases, evitando que estas conozcan demasiado de la implementación de sus colaboradores. Se puede definir de forma muy sencilla con una única frase:

Habla solo con tus amigos, no hables con extraños

¿Qué quiere decir esto exactamente? Pues muy sencillo, esto viene a decir que dado un objeto, este solo debería de conocer (y acceder) los métodos públicos de sus colaboradores directos.

Si queremos tener un punto de vista más teórico, Bob Martin define la Ley de Demeter en Clean Code de la siguiente manera:

For all classes C. and for all methods M attached to C, all objects to which M sends a message must be instances of classes associated with the following classes:

1. The argument classes of M (including C).

2. The instance variable classes of C.

(Objects created by M, or by functions or methods which M calls, and objects in global variables are considered as arguments of M.)

Para simplificar un poco todo esto, veamos un ejemplo de una cadena de Demeter:

En este pequeño fragmento de código podemos observar las cadenas de llamadas que hacen que deje cumplirse la ley de Demeter en las líneas 15 y 16.

Fijemonos en la línea 16. En esta linea estamos accediendo a una dependencia que nos ha sido pasada por el constructor, desde aquí hemos accedido a un servicio llamado *notification_service, *y a su vez, desde este servicio hemos accedido a un sub-servicio de email, y finalmente hemos accedido al método *sendWelcomeEmail. *Si hay algo claro en todo esto, es que hemos hablado con muchos desconocidos.

Es importante recalcar que esta ley solo es aplicable a objetos que definan comportamiento (servicios, command handlers…) pero no a aquellos que representen estructuras de datos, como DTOs (entidades)

¿Cómo evitamos incumplir la Ley de Demeter?

Si detectamos que estamos incumpliendo la Ley de Demeter, lo primero es aceptar que tenemos un problema de arquitectura en la base de nuestro proyecto y esto puede implicar cambios bastante grandes.

En el anterior ejemplo, una solución muy correcta sería evitar pasarle al constructor una dependencia tan grande como el container, y pasarle únicamente aquellos servicios que vaya a necesitar (orm y notification_service), de tal forma que pueda acceder a métodos de colaboradores directos.

Una forma nada recomendable de solucionar la Ley de Demeter consiste en el uso de shortcut methods que nos permitan acceder a las funcionalidades deseadas con una única llamada. En realidad esto solo oculta el problema, ya que la cadena de Demeter sigue oculta, dividida entre más clases.

Veamos un ejemplo:

Aquí vemos el mismo código que antes, aunque un poco retocado: hemos inyectado las dependencias necesarias, y ademas hemos añadido shortcut methods a la clase Orm y a la clase NotificationService. Más abajo podemos ver un extracto de la definición de estas clases, con los nuevos métodos implementado: **el problema sigue existiendo, solo lo hemos barrido debajo de la alfombra. **Además, no siempre tendremos opción de modificar estos servicios, ya que pueden ser dependencias de terceros cuyo código no podemos modificar.

Conclusión

Hay quien dice que la Ley de Demeter es el quinto Beatle de los principios SOLID, una extension altamente necesaria en la OOP, y ciertamente, prestar atención a su cumplimiento nos dice mucho del tipo de arquitectura que estamos montando y su fragilidad o robustez.

Si detectamos el problema, es importante tratar de solucionarlo con buenas prácticas y no enmascarar un problema que puede comprometer nuestro sistema con el tiempo.

Hasta pronto!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay