inyeccion injection explicacion ejemplo dependency dependencias control dependency-injection inversion-of-control

dependency-injection - injection - inyeccion de dependencias php



¿Inyección de dependencia a través de constructores o instaladores de propiedades? (14)

Bueno, eso depende :-).

Si la clase no puede hacer su trabajo sin la dependencia, entonces agréguela al constructor. La clase necesita la nueva dependencia, por lo que desea que su cambio rompa las cosas. Además, la creación de una clase que no está totalmente inicializada ("construcción en dos pasos") es un anti-patrón (en mi humilde opinión).

Si la clase puede funcionar sin la dependencia, un colocador está bien.

Estoy refactorizando una clase y agregando una nueva dependencia a ella. La clase está tomando sus dependencias existentes en el constructor. Entonces, por coherencia, agrego el parámetro al constructor.
Por supuesto, hay algunas subclases más aún más para las pruebas unitarias, así que ahora estoy jugando el juego de alterar todos los constructores para que coincida, y está tardando años.
Me hace pensar que usar propiedades con setters es una mejor forma de obtener dependencias. No creo que las dependencias inyectadas sean parte de la interfaz para construir una instancia de una clase. Agrega una dependencia y ahora todos sus usuarios (subclases y cualquier instancia de usted directamente) de repente lo saben. Eso se siente como una ruptura de la encapsulación.

Este no parece ser el patrón con el código existente aquí, entonces estoy buscando averiguar cuál es el consenso general, pros y contras de constructores versus propiedades. ¿Está usando mejor los setters de propiedades?


Constructor injection revela explícitamente las dependencias, haciendo que el código sea más legible y menos propenso a errores de tiempo de ejecución no controlados si los argumentos se comprueban en el constructor, pero realmente se reduce a una opinión personal, y cuanto más se usa DI, más se podrá tienden a oscilar hacia adelante y hacia atrás de una forma u otra dependiendo del proyecto. Personalmente, tengo problemas con el código que huele a constructores con una larga lista de argumentos, y creo que el consumidor de un objeto debe conocer las dependencias para utilizar el objeto de todos modos, por lo que se justifica el uso de la inyección de propiedades. No me gusta la naturaleza implícita de la inyección de propiedades, pero me parece más elegante, lo que da como resultado un código de aspecto más limpio. Pero, por otro lado, la inyección de constructor ofrece un mayor grado de encapsulación, y en mi experiencia trato de evitar los constructores por defecto, ya que pueden tener un efecto negativo sobre la integridad de los datos encapsulados si no se tiene cuidado.

Elija la inyección por constructor o por propiedad sabiamente en función de su escenario específico. Y no sienta que tiene que usar DI solo porque parece necesario y evitará malos olores de diseño y código. A veces no vale la pena el esfuerzo utilizar un patrón si el esfuerzo y la complejidad superan el beneficio. Mantenlo simple.


Depende de cómo quiera implementarlo. Prefiero la inyección de constructores donde siento que los valores que entran en la implementación no cambian con frecuencia. Por ejemplo: si la estrategia de compnay va con el servidor de oráculo, configuraré mis valores de origen de dats para las conexiones de un bean Achiveing ​​a través de la inyección del constructor. De lo contrario, si mi aplicación es un producto y existe la posibilidad de que se pueda conectar a cualquier base de datos del cliente, implementaría dicha configuración de base de datos y la implementación de múltiples marcas a través de la inyección setter. Acabo de tomar un ejemplo, pero hay mejores formas de implementar los escenarios que mencioné anteriormente.


El enfoque general preferido es usar la inyección de constructor tanto como sea posible.

La inyección del constructor indica exactamente cuáles son las dependencias necesarias para que el objeto funcione correctamente: nada es más molesto que reactivar un objeto y tenerlo bloqueado al invocar un método porque no se ha establecido alguna dependencia. El objeto devuelto por un constructor debe estar en un estado de trabajo.

Intenta tener solo un constructor, mantiene el diseño simple y evita la ambigüedad (si no es para humanos, para el contenedor DI).

Puede usar la inyección de propiedad cuando tiene lo que Mark Seemann llama un valor predeterminado local en su libro "Dependency Injection in .NET": la dependencia es opcional porque puede proporcionar una implementación de trabajo precisa pero quiere permitir que la persona que llama especifique una diferente si necesario.

(Respuesta anterior a continuación)

Creo que la inyección del constructor es mejor si la inyección es obligatoria. Si esto agrega demasiados constructores, considere usar fábricas en lugar de constructores.

La inyección del colocador es agradable si la inyección es opcional, o si desea cambiarla a la mitad. En general, no me gustan los setters, pero es una cuestión de gusto.


Es en gran medida una cuestión de gusto personal. Personalmente tiendo a preferir la inyección setter, porque creo que le da más flexibilidad en la forma en que puede sustituir implementaciones en tiempo de ejecución. Además, los constructores con muchos argumentos no son limpios en mi opinión, y los argumentos provistos en un constructor deben estar limitados a argumentos no opcionales.

Siempre que la interfaz de clases (API) sea clara en lo que necesita para realizar su tarea, está bien.


Esta es una publicación anterior, pero si se necesita en el futuro, tal vez esto sea de alguna utilidad:

https://github.com/omegamit6zeichen/prinject

Tuve una idea similar y se me ocurrió este marco. Probablemente esté lejos de ser completo, pero es una idea de un marco centrado en la inyección de propiedades


Perfero la inyección del constructor, porque esto parece más lógico. Es como decir que mi clase requiere estas dependencias para hacer su trabajo. Si es una dependencia opcional, las propiedades parecen razonables.

También uso la inyección de propiedades para configurar cosas a las que el contenedor no tiene referencias, como una vista ASP.NET en un presentador creado usando el contenedor.

No creo que rompa la encapsulación. El funcionamiento interno debe permanecer interno y las dependencias deben lidiar con una preocupación diferente.


Personalmente prefiero el "patrón" Extraer y anular sobre la inyección de dependencias en el constructor, en gran parte por la razón que se describe en su pregunta. Puede establecer las propiedades como virtual y luego anular la implementación en una clase comprobable derivada.


Por supuesto, poner el constructor significa que puede validar todo de una vez. Si asigna cosas en campos de solo lectura, entonces tiene algunas garantías sobre las dependencias de su objeto desde el momento de la construcción.

Es un verdadero dolor agregar nuevas dependencias, pero al menos de esta manera el compilador sigue quejándose hasta que sea correcto. Lo cual es algo bueno, creo.


Prefiero la inyección de constructor porque ayuda a "hacer cumplir" los requisitos de dependencia de una clase. Si está en el administrador, un consumidor tiene que configurar los objetos para que la aplicación compile. Si usa la inyección setter, es posible que no sepa que tiene un problema hasta el tiempo de ejecución, y según el objeto, puede ser tarde en el tiempo de ejecución.

Aún utilizo la inyección setter de vez en cuando cuando el objeto inyectado puede necesitar mucho trabajo, como la inicialización.


Recientemente me encontré con una situación en la que tenía varias dependencias en una clase, pero solo una de las dependencias iba a cambiar necesariamente en cada implementación. Dado que las dependencias de acceso a datos y registro de errores probablemente solo se cambiarían para fines de prueba, agregué parámetros opcionales para esas dependencias y proporcioné implementaciones predeterminadas de esas dependencias en mi código de constructor. De esta manera, la clase mantiene su comportamiento predeterminado a menos que sea anulado por el consumidor de la clase.

El uso de parámetros opcionales solo se puede lograr en marcos que los admitan, como .NET 4 (tanto para C # como para VB.NET, aunque VB.NET siempre los ha tenido). Por supuesto, puede lograr una funcionalidad similar simplemente usando una propiedad que pueda ser reasignada por el consumidor de su clase, pero no obtiene la ventaja de la inmutabilidad proporcionada al tener un objeto de interfaz privado asignado a un parámetro del constructor.

Dicho todo esto, si está presentando una nueva dependencia que debe ser proporcionada por cada consumidor, tendrá que refactorizar su constructor y todo el código que los consumidores de su clase. Mis sugerencias anteriores solo se aplican si tiene el lujo de poder proporcionar una implementación predeterminada para todo su código actual, pero aún así puede anular la implementación predeterminada si es necesario.


Se supone que los usuarios de una clase deben conocer las dependencias de una clase determinada. Si tuviera una clase que, por ejemplo, se conectara a una base de datos y no proporcionara un medio para inyectar una dependencia de capa de persistencia, un usuario nunca sabría que una conexión a la base de datos debería estar disponible. Sin embargo, si modifico el constructor, les digo a los usuarios que existe una dependencia en la capa de persistencia.

Además, para evitar tener que modificar cada uso del antiguo constructor, simplemente aplique el encadenamiento de constructores como un puente temporal entre el constructor antiguo y el nuevo.

public class ClassExample { public ClassExample(IDependencyOne dependencyOne, IDependencyTwo dependencyTwo) : this (dependnecyOne, dependencyTwo, new DependnecyThreeConcreteImpl()) { } public ClassExample(IDependencyOne dependencyOne, IDependencyTwo dependencyTwo, IDependencyThree dependencyThree) { // Set the properties here. } }

Uno de los puntos de la inyección de dependencia es revelar qué dependencias tiene la clase. Si la clase tiene demasiadas dependencias, entonces puede ser el momento para que se lleve a cabo alguna refactorización: ¿Todos los métodos de la clase usan todas las dependencias? Si no, entonces ese es un buen punto de partida para ver dónde se podría dividir la clase.


Si tiene una gran cantidad de dependencias opcionales (que ya es un olor), entonces la inyección de setter es la mejor opción. Sin embargo, la inyección de constructores revela mejor sus dependencias.


Una opción que podría valer la pena considerar es componer dependencias múltiples complejas a partir de dependencias simples simples. Es decir, defina clases adicionales para dependencias compuestas. Esto hace que las cosas sean un poco más sencillas. Inyección de constructores de WRT, menos parámetros por llamada, mientras se mantiene la necesidad de proporcionar todas las dependencias para crear instancias.

Por supuesto, tiene más sentido si hay algún tipo de agrupación lógica de dependencias, por lo que el compuesto es más que un agregado arbitrario, y tiene más sentido si hay múltiples dependientes para una única dependencia compuesta, pero el bloque de parámetros "patrón" tiene ha existido por mucho tiempo, y la mayoría de los que he visto han sido bastante arbitrarios.

Personalmente, sin embargo, soy más partidario de usar métodos / definidores de propiedades para especificar dependencias, opciones, etc. Los nombres de las llamadas ayudan a describir lo que está sucediendo. Sin embargo, es una buena idea proporcionar ejemplos de esto-es-cómo-hacer-configurar-fragmentos, y asegurarse de que la clase dependiente haga suficientes comprobaciones de errores. Es posible que desee utilizar un modelo de estado finito para la configuración.