Me parece que mis constructores comienzan a verse así:
public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )
con una lista de parámetros cada vez mayor. Dado que "Contenedor" es mi contenedor de inyección de dependencia, ¿por qué no puedo hacer esto?
public MyClass(Container con)
para cada clase? ¿Cuáles son las desventajas? Si hago esto, parece que estoy usando una estática glorificada. Por favor comparta sus pensamientos sobre IoC y la locura de la inyección de dependencia.
c#
java
dependency-injection
inversion-of-control
ioc-container
JP Richardson
fuente
fuente
Respuestas:
Tiene razón en que si usa el contenedor como un Localizador de servicios, es más o menos una fábrica estática glorificada. Por muchas razones , considero que esto es un antipatrón .
Uno de los maravillosos beneficios de la inyección de constructor es que hace que las violaciones del principio de responsabilidad única sean evidentemente evidentes.
Cuando eso sucede, es hora de refactorizar a Facade Services . En resumen, cree una nueva interfaz más detallada que oculte la interacción entre algunas o todas las dependencias específicas que necesita actualmente.
fuente
No creo que los constructores de tu clase deban tener una referencia a tu período de contenedor IOC. Esto representa una dependencia innecesaria entre su clase y el contenedor (¡el tipo de dependencia que IOC está tratando de evitar!).
fuente
MyClass myClass = new MyClass(IDependency1 interface1, IDependency2 interface2)
(parámetros de interfaz). Esto no está relacionado con posterior @ de derivación, que interpreto como diciendo un contenedor de inyección de dependencias no debe inyectarse en sus objetos, es decir,MyClass myClass = new MyClass(this)
La dificultad de pasar los parámetros no es el problema. El problema es que su clase está haciendo demasiado y debería desglosarse más.
La inyección de dependencia puede actuar como una advertencia temprana para las clases que se hacen demasiado grandes, específicamente debido al creciente dolor de pasar todas las dependencias.
fuente
Me encontré con una pregunta similar sobre la inyección de dependencia basada en el constructor y lo complejo que era pasar en todas las dependencias.
Uno de los enfoques que he usado en el pasado es usar el patrón de fachada de la aplicación usando una capa de servicio. Esto tendría una API gruesa. Si este servicio depende de repositorios, usaría una inyección de setter de las propiedades privadas. Esto requiere crear una fábrica abstracta y mover la lógica de crear los repositorios a una fábrica.
Código detallado con explicación se puede encontrar aquí
Mejores prácticas para IoC en la capa de servicios complejos
fuente
Leí todo este hilo, dos veces, y creo que las personas responden por lo que saben, no por lo que se les pregunta.
La pregunta original de JP parece que está construyendo objetos enviando un resolutor, y luego un montón de clases, pero estamos asumiendo que esas clases / objetos son en sí mismos servicios, listos para la inyección. ¿Y si no lo son?
JP, si está buscando aprovechar la DI y desea la gloria de mezclar la inyección con datos contextuales, ninguno de estos patrones (o supuestos "antipatrones") aborda específicamente eso. En realidad, se reduce a usar un paquete que lo apoyará en tal esfuerzo.
... este formato rara vez es compatible. Creo que la dificultad de programar dicho soporte, sumado al rendimiento miserable que se asociaría con la implementación, lo hace poco atractivo para los desarrolladores de código abierto.
Pero debería hacerse, porque debería ser capaz de crear y registrar una fábrica para MyClass'es, y esa fábrica debería poder recibir datos / entradas que no se conviertan en un "servicio" por el simple hecho de pasar datos. Si el "antipatrón" se trata de consecuencias negativas, entonces forzar la existencia de tipos de servicios artificiales para pasar datos / modelos es ciertamente negativo (a la par con su sensación de envolver sus clases en un contenedor. Se aplica el mismo instinto).
Sin embargo, hay un marco que puede ayudar, incluso si se ven un poco feos. Por ejemplo, Ninject:
Crear una instancia usando Ninject con parámetros adicionales en el constructor
Eso es para .NET, es popular y todavía no está tan limpio como debería ser, pero estoy seguro de que hay algo en el idioma que elijas emplear.
fuente
Inyectar el contenedor es un atajo que finalmente lamentará.
La inyección excesiva no es el problema, generalmente es un síntoma de otros defectos estructurales, especialmente la separación de preocupaciones. Este no es un problema, pero puede tener muchas fuentes y lo que hace que esto sea tan difícil de solucionar es que tendrá que lidiar con todos ellos, a veces al mismo tiempo (piense en desenredar espaguetis).
Aquí hay una lista incompleta de las cosas a tener en cuenta
Diseño de dominio deficiente (agregue la raíz ..., etc.)
Separación deficiente de las inquietudes (composición del servicio, comandos, consultas) Consulte CQRS y aprovisionamiento de eventos.
O Mappers (tenga cuidado, estas cosas pueden llevarlo a problemas)
Ver modelos y otros DTO (¡¡Nunca reutilices uno, y trata de mantenerlos al mínimo !!!!
fuente
Problema:
1) Constructor con una lista de parámetros cada vez mayor.
2) Si la clase se hereda (Ej .:),
RepositoryBase
entonces cambiar la firma del constructor provoca un cambio en las clases derivadas.Solución 1
Pase
IoC Container
al constructorPor qué
Por qué no
Solución 2
Cree una clase que agrupe todos los servicios y páselo al constructor
Clase derivada
Por qué
A
depende, esa información se acumula enA.Dependency
Por qué no
X.Dependency
separado)IoC Container
Sin embargo, la solución 2 es solo cruda, si hay un argumento sólido en su contra, se agradecería un comentario descriptivo
fuente
Este es el enfoque que uso
Aquí hay un enfoque burdo sobre cómo realizar las inyecciones y ejecutar el constructor después de inyectar valores. Este es un programa completamente funcional.
Actualmente estoy trabajando en un proyecto de hobby que funciona así https://github.com/Jokine/ToolProject/tree/Core
fuente
¿Qué marco de inyección de dependencia está utilizando? ¿Has intentado usar una inyección basada en setter?
El beneficio para la inyección basada en constructor es que parece natural para los programadores de Java que no usan marcos DI. Necesita 5 cosas para inicializar una clase, luego tiene 5 argumentos para su constructor. La desventaja es lo que has notado, se vuelve difícil de manejar cuando tienes muchas dependencias.
Con Spring, podría pasar los valores requeridos con setters en su lugar y podría usar las anotaciones @required para exigir que se inyecten. La desventaja es que debe mover el código de inicialización del constructor a otro método y hacer que Spring lo llame después de que se inyecten todas las dependencias marcándolo con @PostConstruct. No estoy seguro acerca de otros marcos, pero supongo que hacen algo similar.
Ambas formas funcionan, es una cuestión de preferencia.
fuente