2008-10-01 11 views
15

He estado agregando la inyección de dependencia a mi código porque hace que el código sea mucho más fácil para la prueba unitaria a través de la burla.¿La inyección de dependencia infringe la Ley de Demeter

Sin embargo, estoy requiriendo que los objetos más altos en mi cadena de llamadas tengan conocimiento de los objetos que están más abajo en la cadena de llamadas.

¿Esto rompe la Ley de Demeter? Si es así, ¿qué importancia tiene?

por ejemplo: una clase A tiene una dependencia en una interfaz B, la implementación de esta interfaz para usar se inyecta en el constructor de clase A. Cualquiera que desee utilizar la clase A ahora también debe tener una referencia a una implementación de B. Y puede llamar a sus métodos directamente el significado y tiene conocimiento de sus subcomponentes (interfaz B)

Wikipedia dice acerca de la ley de Demeter: "La noción fundamental es que un objeto dado debe asumir lo menos posible sobre la estructura o propiedades de cualquier otra cosa (incluidos sus subcomponentes) ".

+1

¿Puedes publicar un código de ejemplo? Si estás haciendo foo.bar(). Baz() entonces sí, estás rompiendo la Ley de Demeter. ¿Estás diciendo que terminas haciendo esto? – asterite

Respuesta

11

Dependency Injection PUEDE ROMPERSE LA LEY DE DEMETER. Si fuerza a los consumidores a hacer la inyección de las dependencias. Esto se puede evitar mediante métodos de fábrica estáticos y marcos DI.

Puede tener ambos diseñando sus objetos de tal manera que requieran que se pasen las dependencias, y al mismo tiempo tener un mecanismo para usarlos sin realizar la inyección explícitamente (funciones de fábrica y marcos DI).

+0

Creo que lo has clavado. Algunas de las otras respuestas a esta pregunta no se centran en la situación específica del que pregunta. – moffdub

+0

¿Puede explicar el término "consumidor" por favor? – meowsqueak

+0

En este caso, un consumidor de una clase es cualquier otro código que invoca métodos en esa clase. –

1

¿Viola la ley?
Estrictamente hablando, creo que sí.
¿Importa?
El principal peligro de violar la ley es que hace que su código sea más frágil.
Si realmente lo mantienes solo en las pruebas, parece que el peligro no es tan malo.
Mitigación
Mi comprensión de la Law of Demeter es que puede ser seguido por tener "métodos de contenedor", que impiden realizar llamadas directamente hacia abajo en objetos.

3

¿Cómo lo rompe? DI encaja perfectamente en la idea de menor conocimiento. DI le proporciona bajo acoplamiento: los objetos son menos acusados ​​entre sí.

Citando Wikipedia:

... un objeto A puede solicitar un servicio (llamada un método) de un objeto ejemplo B, pero objeto A no puede “llegar a través de” objeto B para acceder todavía otro objeto ...

Por lo general, DI funciona exactamente de la misma manera, es decir, utiliza los servicios proporcionados por los componentes inyectados. Si el objeto tratar de acceder a algunas de las dependencias del B, es decir, se sabe mucho acerca de B - que es, produce altos acoplamiento y rompe idea de DI

Sin embargo, estoy que requieren los objetos más alta mi cadena de llamadas para tener conocimiento de objetos más abajo en la cadena de llamadas

¿Algún ejemplo?

2

Si te entiendo correctamente, esto no es causado por el uso de la inyección de dependencia, sino que se debe al uso de estrategias de burla que te obligan a especificar las llamadas de función que esperas que haga un método. Eso es perfectamente aceptable en muchas situaciones, pero obviamente eso significa que debe saber algo sobre el método que está llamando, si ha especificado lo que cree que se supone que debe hacer.

Escribir un buen software requiere equilibrar las compensaciones.A medida que la implementación se vuelve más completa, se vuelve más inconsistente. Debe decidir qué riesgos crean esas incoherencias y si valen el valor creado por su presencia.

1

La Ley de Demeter especifica que el método M del objeto O puede llamar a métodos sobre objetos creados/instanciados dentro de M. Sin embargo, no hay nada que especifique cómo se crearon estos objetos. Creo que está perfectamente bien usar un objeto intermediario para crear estos, siempre y cuando el objetivo de ese objeto en la vida sea solo eso: crear otros objetos en su nombre. En este sentido, DI no infringe la Ley de Demeter.

0

Depende :-)

Creo que la respuesta arriba no es correcto, incluso con un marco de una gran cantidad de código utiliza la inyección de dependencias e inyecta objetos de alto nivel. A continuación, obtiene el código de spaghetti con muchas dependencias.

La inyección de dependencia se utiliza mejor para todas las cosas que podrían contaminar su modelo de objeto, por ejemplo, un ILogger. Si inyectas un objeto comercial, asegúrate de que esté en el nivel más bajo posible e intenta pasar el método tradicional si puedes. Solo usa la inyección de dependencia si se vuelve desordenada.

0

Antes de añadir mi respuesta, debo calificarla. La Programación Orientada a Servicios se basa en los Principios OOP y el uso de OO Languages. Además, las SOA siguen la Inversión de Control y los Principios SÓLIDOS en los dientes. Así que muchos programadores orientados al servicio seguramente están llegando aquí. Entonces, esta respuesta es para los programadores orientados al servicio que llegan a esta pregunta, porque SOA se basa en OOP. Esto no responde directamente el ejemplo del PO, pero responde la pregunta desde una Perspectiva SOA.

En general, la Ley de Demeter no se aplica a Arquitecturas Orientadas a Servicios. Para OO, la Ley de Demeter está hablando de "objetos ricos" en OOP que tienen propiedades y métodos, y cuyas propiedades también pueden tener métodos. Con OOP Rich Models, es posible acceder a través de una cadena de objetos y métodos de acceso, propiedades, métodos de propiedades, métodos de propiedades, etc. Pero en Programación Orientada a Servicios, los Datos (Propiedades) están separados del Proceso (Métodos)) Sus Modelos (principalmente) solo tienen propiedades (Ciertamente nunca dependencias), y sus Servicios solo tienen Métodos y dependencias en otros Servicios.

En SOP, puede revisar libremente las propiedades de un modelo y las propiedades de sus propiedades. Nunca podrá acceder a métodos que no debería, solo un árbol de datos. Pero, ¿qué pasa con los Servicios? ¿La Ley de Demeter se aplica allí?

Sí, la Ley de Demeter puede ser aplicada a los servicios de SOP. Pero, nuevamente, la ley fue originalmente diseñada para modelos ricos en OOP. Y aunque la ley puede ser aplicada a los Servicios, la Inyección de Dependencia adecuada cumple automágicamente la Ley de Demeter. En ese sentido, DI no podría violar la ley.

En oposición limitada a Mark Roddy, no puedo encontrar ninguna situación en la que legítimamente se puede hablar de Dependency Injection y "consumidores" en la misma oración. Si por "consumidores" te refieres a una clase que está consumiendo otra clase, eso no tiene sentido.Con DI, tendría una raíz de composición que componga su gráfico de objetos, y una clase nunca debería saber que existe otra clase. Si por "consumidores" te refieres a un programador, entonces ¿cómo se forzarían a no a "hacer la inyección"? El programador es el que tiene que crear la raíz de composición, por lo que debe hacer la inyección. Un programador nunca debe "hacer la inyección" como una instanciación dentro de una clase para consumir otra clase.

Por favor revise el siguiente ejemplo que muestra soluciones reales separadas, sus referencias, y el código de aplicación:

In SOA, DI doesn't allow breaking of LoD

En la parte superior derecha, tenemos el "Core". Muchos paquetes en NuGet y NPM tienen un proyecto "Core" que tiene Model, Interfaces y posiblemente incluso implementaciones predeterminadas. El Núcleo nunca debería depender nunca de algo externo.

En la esquina superior izquierda, tenemos una implementación externa del Core. La implementación depende del Núcleo, y también lo tiene conocimiento.

En la esquina inferior izquierda, tenemos un dominio independiente. El Dominio tiene una Dependencia en alguna Implementación del Núcleo, pero No necesita saber sobre la implementación.

Aquí es donde señalo que ni el Dominio ni la Implementación se conocen. Hay un 0% de posibilidades de que cualquiera llegue a (o más allá) del otro, porque ni siquiera saben que existen. El dominio solo sabe que hay un contrato, y de alguna manera puede consumir los métodos por lo que sea que se inyecte en él.

En la esquina inferior izquierda está la raíz de composición o el punto de entrada. Esto también se conoce como el "límite frontal" de la aplicación. La raíz de una aplicación conoce todos sus componentes y hace poco más que tomar entrada, determinar a quién llamar, componer objetos y devolver resultados. En otras palabras, solo puede decirle al dominio "Aquí, usa esto para cumplir tu contrato de ICalculateThings, luego dame el resultado de CalculateTwoThings.

De hecho, hay una manera de destruir todo en el mismo proyecto, hacer instancias concretas de Servicios, haga que sus dependencias sean propiedades públicas en lugar de campos privados, STILL Do Dependency-Injection (horriblemente), y luego haga que los servicios llamen a dependencias de dependencias. Pero eso sería malo, m'kay. Debería intentarlo Sería malo hacer eso.

Nota al margen, lo sobre-compliqué a propósito. Estos proyectos podrían existir en una sola solución (siempre y cuando el Arquitecto controle la Arquitectura de Referencia), y podría haber algunas simplificaciones más. Pero la separación en la imagen realmente muestra ho Poco conocimiento tiene el sistema sobre sus partes. Solo la raíz de composición (punto de entrada, límite frontal) necesita conocer las partes.

Conclusión (TL; DR;): En Oldskewl OOP, los modelos son ricos, y la Ley de Demeter se puede romper fácilmente buscando modelos de modelos para acceder a sus métodos. Pero en Newskewl SOP (construido sobre Principios e idiomas de OOP), los datos se separan del proceso. Así que puede sentirse libre de examinar las propiedades de los modelos. Luego, para los Servicios, las dependencias son siempre privadas, y nada sabe que exista algo más aparte de lo que les dicen las abstracciones, los contratos, las interfaces.

Cuestiones relacionadas