La Ley de Demeter ( LoD ) o principio del mínimo conocimiento es una guía de diseño para el desarrollo de software , en particular programas orientados a objetos . En su forma general, la LoD es un caso específico de acoplamiento flexible . La guía fue propuesta por Ian Holland en la Universidad de Northeastern hacia fines de 1987, [1] y las siguientes tres recomendaciones sirven como un resumen sucinto: [2]
La idea fundamental es que un objeto determinado debe presuponer lo menos posible sobre la estructura o las propiedades de cualquier otra cosa (incluidos sus subcomponentes), de acuerdo con el principio de " ocultación de información ". Puede considerarse un corolario del principio del mínimo privilegio , que dicta que un módulo posee únicamente la información y los recursos necesarios para su propósito legítimo.
Se llama así por su origen en el Proyecto Demeter, un esfuerzo de programación adaptativa y programación orientada a aspectos . El proyecto recibió el nombre en honor a Demeter , "madre de la distribución" y diosa griega de la agricultura , para significar una filosofía de programación de abajo hacia arriba que también está incorporada en la ley misma. [3] [ se necesita una fuente no primaria ]
La ley se remonta a 1987, cuando fue propuesta por primera vez por Ian Holland, quien trabajaba en el Proyecto Demeter. Este proyecto fue la cuna de muchos principios de programación orientada a aspectos (AOP).
Una cita en uno de los restos del proyecto parece aclarar el origen del nombre: [4]
Deméter
La diosa griega de la agricultura.
El proyecto Demeter recibió su nombre porque estábamos trabajando en un lenguaje de descripción de hardware llamado Zeus y buscábamos una herramienta que simplificara la implementación de Zeus. Buscábamos un nombre de herramienta relacionado con Zeus y elegimos un hermano de Zeus: Demeter.
Más tarde, promovimos la idea de que el desarrollo de software al estilo Demeter se trata de hacer crecer el software, en lugar de construirlo. Introdujimos el concepto de plan de crecimiento, que básicamente es una secuencia de diagramas de clases UML cada vez más complejos.
Los planes de crecimiento son útiles para construir sistemas de forma incremental.
Un objeto a
puede solicitar un servicio (llamar a un método) de una instancia de objeto b
, pero a
no debe "pasar" por encima de otro objeto b
para acceder a otro objeto, c
para solicitar sus servicios. Si lo hiciera, implicaría que el objeto a
requiere implícitamente un mayor conocimiento de b
la estructura interna del objeto.
En cambio, b
la interfaz de 's debe modificarse si es necesario para que pueda atender directamente a
la solicitud de object y propagarla a cualquier subcomponente relevante. Alternativamente, a
podría tener una referencia directa a object c
y realizar la solicitud directamente a este. Si se sigue la ley, solo object b
conoce su propia estructura interna.
Más formalmente, la Ley de Deméter para funciones requiere que un método m
de un objeto a
sólo pueda invocar los métodos de los siguientes tipos de objetos: [5]
a
sí mismo;m
parámetros de;m
;a
atributos de;a
en el ámbito de m
.En particular, un objeto debe evitar invocar métodos de un objeto devuelto por otro método. Para muchos lenguajes orientados a objetos modernos que usan un punto como identificador de campo, la ley se puede expresar simplemente como "use solo un punto". [6] Es decir, el código a.m().n()
infringe la ley cuando a.m()
no lo hace. Como analogía , cuando uno quiere que un perro camine, no le ordena a las patas del perro que camine directamente; en cambio, le ordena al perro que, a su vez, ordene a sus propias patas.
La ventaja de seguir la Ley de Demeter es que el software resultante tiende a ser más fácil de mantener y adaptable . Dado que los objetos dependen menos de la estructura interna de otros objetos, la implementación de los objetos se puede cambiar sin tener que rehacer sus invocadores.
Basili et al. [7] publicaron resultados experimentales en 1996 que sugieren que una Respuesta para una Clase (RFC, el número de métodos potencialmente invocados en respuesta a llamar a un método de esa clase) más baja puede reducir la probabilidad de errores de software . Seguir la Ley de Demeter puede resultar en una RFC más baja. Sin embargo, los resultados también sugieren que un aumento en los Métodos Ponderados por Clase [8] (WMC, el número de métodos definidos en cada clase) puede aumentar la probabilidad de errores de software. Seguir la Ley de Demeter también puede resultar en una WMC más alta.
Una arquitectura multicapa puede considerarse un mecanismo sistemático para implementar la Ley de Deméter en un sistema de software. En una arquitectura multicapa, el código dentro de cada capa solo puede realizar llamadas al código dentro de la capa y al código dentro de la capa siguiente. "Saltarse capas" violaría la arquitectura multicapa.
Aunque el LoD aumenta la adaptabilidad de un sistema de software, puede resultar en la necesidad de escribir muchos métodos envolventes para propagar llamadas a los componentes; en algunos casos, esto puede agregar una sobrecarga de tiempo y espacio notable. [7] [9] [10]
A nivel de método, el LoD conduce a interfaces estrechas, dando acceso solo a la cantidad de información que necesita para hacer su trabajo, ya que cada método necesita saber sobre un pequeño conjunto de métodos de objetos estrechamente relacionados. [11] Por otro lado, a nivel de clase, si el LoD no se usa correctamente, se pueden desarrollar interfaces amplias (es decir, agrandadas) que requieren la introducción de muchos métodos auxiliares. [9] [10] Esto se debe a un diseño deficiente en lugar de ser una consecuencia del LoD per se. Si se usa un método contenedor, significa que el objeto que se llama a través del contenedor debería haber sido una dependencia en la clase que llama.
Una solución propuesta para el problema de las interfaces de clases ampliadas es el enfoque orientado a aspectos [12], donde el comportamiento del método se especifica como un aspecto en un alto nivel de abstracción. Las interfaces amplias se gestionan a través de un lenguaje que especifica las implementaciones. Tanto la estrategia de recorrido como el visitante adaptativo utilizan solo un conjunto mínimo de clases que participan en la operación, y la información sobre las conexiones entre estas clases se abstrae.
Como se esperaba, cuanto mayor sea el WMC, mayor será la probabilidad de detección de fallas.
Un efecto secundario de esto es que si se ajusta a LoD, si bien puede aumentar bastante la capacidad de mantenimiento y la "adaptabilidad" de su sistema de software, también termina teniendo que escribir muchos métodos de envoltura pequeños para propagar las llamadas de métodos a sus componentes (lo que puede agregar una sobrecarga de tiempo y espacio notable).
La desventaja, por supuesto, es que termina escribiendo muchos métodos de envoltura pequeños que hacen muy poco más que delegar el recorrido del contenedor y demás. La compensación de costos es entre esa ineficiencia y un acoplamiento de clases más alto.
Mantenimiento de software más sencillo, menor acoplamiento entre los métodos, mejor ocultamiento de la información, interfaces más estrechas, métodos más fáciles de reutilizar y pruebas de corrección más sencillas mediante inducción estructural.
Un método adaptativo encapsula el comportamiento de una operación en un solo lugar, evitando así el problema de dispersión, pero también abstrae sobre la estructura de clases, evitando así también el problema de enredo.