Ya se han publicado varias preguntas con preguntas específicas sobre la inyección de dependencia , como cuándo usarla y qué marcos existen para ello. Sin embargo,
¿Qué es la inyección de dependencia y cuándo / por qué debería o no debería usarse?
Ya se han publicado varias preguntas con preguntas específicas sobre la inyección de dependencia , como cuándo usarla y qué marcos existen para ello. Sin embargo,
¿Qué es la inyección de dependencia y cuándo / por qué debería o no debería usarse?
Respuestas:
La inyección de dependencia es pasar dependencia a otros objetos o marco (inyector de dependencia).
La inyección de dependencia facilita las pruebas. La inyección se puede hacer a través del constructor .
SomeClass()
tiene su constructor de la siguiente manera:Problema : si se
myObject
trata de tareas complejas como el acceso al disco o el acceso a la red, es difícil hacer una prueba unitariaSomeClass()
. Los programadores tienen que burlarsemyObject
y pueden interceptar la llamada de fábrica.Solución alternativa :
myObject
como argumento al constructormyObject
se puede pasar directamente, lo que facilita las pruebas.Es más difícil aislar componentes en pruebas unitarias sin inyección de dependencia.
En 2013, cuando escribí esta respuesta, este era un tema importante en el blog de Google Testing . Sigue siendo la mayor ventaja para mí, ya que los programadores no siempre necesitan la flexibilidad adicional en su diseño de tiempo de ejecución (por ejemplo, para el localizador de servicios o patrones similares). Los programadores a menudo necesitan aislar las clases durante las pruebas.
fuente
La mejor definición que he encontrado hasta ahora es una de James Shore :
Hay un artículo de Martin Fowler que también puede resultar útil.
Básicamente, la inyección de dependencias proporciona los objetos que un objeto necesita (sus dependencias) en lugar de hacer que los construya él mismo. Es una técnica muy útil para las pruebas, ya que permite burlar o eliminar las dependencias.
Las dependencias se pueden inyectar en los objetos por muchos medios (como la inyección de constructor o la inyección de setter). Incluso se pueden usar marcos de inyección de dependencia especializados (por ejemplo, Spring) para hacerlo, pero ciertamente no son necesarios. No necesita esos marcos para tener inyección de dependencia. Crear instancias y pasar objetos (dependencias) explícitamente es tan buena inyección como inyección por marco.
fuente
Encontré este ejemplo divertido en términos de acoplamiento flojo :
Cualquier aplicación está compuesta de muchos objetos que colaboran entre sí para realizar algunas cosas útiles. Tradicionalmente, cada objeto es responsable de obtener sus propias referencias a los objetos dependientes (dependencias) con las que colabora. Esto conduce a clases altamente acopladas y código difícil de probar.
Por ejemplo, considere un
Car
objeto.A
Car
depende de las ruedas, el motor, el combustible, la batería, etc. para funcionar. Tradicionalmente definimos la marca de dichos objetos dependientes junto con la definición delCar
objeto.Sin inyección de dependencia (DI):
Aquí, el
Car
objeto es responsable de crear los objetos dependientes.¿Qué sucede si queremos cambiar el tipo de su objeto dependiente, digamos
Wheel
, después de losNepaliRubberWheel()
pinchazos iniciales ? Necesitamos recrear el objeto Car con su nueva dependenciaChineseRubberWheel()
, por ejemplo , pero solo elCar
fabricante puede hacerlo.Entonces, ¿qué hace
Dependency Injection
por nosotros ...?Cuando se usa la inyección de dependencias, los objetos reciben sus dependencias en tiempo de ejecución en lugar de tiempo de compilación (tiempo de fabricación del automóvil) . Para que ahora podamos cambiar el momento
Wheel
que queramos. Aquí,dependency
(wheel
) se puede inyectar enCar
tiempo de ejecución.Después de usar la inyección de dependencia:
Aquí, estamos inyectando las dependencias (Wheel y Battery) en tiempo de ejecución. De ahí el término: inyección de dependencia.
Fuente: Comprender la inyección de dependencia
fuente
new
un ¿neumático? Yo no. Todo lo que tengo que hacer es comprar (inyectar a través de param) de ellos, instalar y ¡wah-lah! Entonces, volviendo a la programación, digamos que un proyecto de C # necesita usar una biblioteca / clase existente, hay dos formas de ejecutar / depurar, 1-agregar referencia a todo el proyecto de estenew
, la opción 2 es pasarla como parámetro. Puede que no sea exacto, pero simple, estúpido y fácil de entender.La inyección de dependencia es una práctica en la que los objetos están diseñados de manera que reciben instancias de los objetos de otras piezas de código, en lugar de construirlos internamente. Esto significa que cualquier objeto que implemente la interfaz requerida por el objeto puede sustituirse sin cambiar el código, lo que simplifica las pruebas y mejora el desacoplamiento.
Por ejemplo, considere estas clases:
En este ejemplo, la implementación de
PersonService::addManager
yPersonService::removeManager
necesitaría una instancia delGroupMembershipService
para hacer su trabajo. Sin la Inyección de dependencias, la forma tradicional de hacerlo sería crear una instanciaGroupMembershipService
en el constructorPersonService
y usar ese atributo de instancia en ambas funciones. Sin embargo, si el constructor deGroupMembershipService
tiene varias cosas que requiere, o peor aún, hay algunos "setters" de inicialización que deben ser invocados enGroupMembershipService
, el código crece bastante rápido, y elPersonService
ahora depende no solo delGroupMembershipService
sino también de todo lo demás.GroupMembershipService
depende de. Además, el enlace aGroupMembershipService
está codificado en elPersonService
que significa que no se puede "simular" unGroupMembershipService
para fines de prueba o para usar un patrón de estrategia en diferentes partes de su aplicación.Con Dependency Injection, en lugar de crear una instancia
GroupMembershipService
dentro de suPersonService
, lo pasaría alPersonService
constructor o agregaría una Propiedad (getter y setter) para establecer una instancia local de la misma. Esto significa quePersonService
ya no tiene que preocuparse por cómo crear unGroupMembershipService
, solo acepta los que se le dan y trabaja con ellos. Esto también significa que cualquier cosa que sea una subclase deGroupMembershipService
, o implemente laGroupMembershipService
interfaz puede "inyectarse" en elPersonService
, yPersonService
no necesita saber sobre el cambio.fuente
La respuesta aceptada es buena, pero me gustaría agregar a esto que DI es muy parecido al clásico evitar las constantes codificadas en el código.
Cuando usa alguna constante como el nombre de una base de datos, la mueve rápidamente desde el interior del código a algún archivo de configuración y pasa una variable que contiene ese valor al lugar donde se necesita. La razón para hacerlo es que estas constantes generalmente cambian con más frecuencia que el resto del código. Por ejemplo, si desea probar el código en una base de datos de prueba.
DI es análogo a esto en el mundo de la programación orientada a objetos. Los valores allí en lugar de los literales constantes son objetos completos, pero la razón para mover el código que los crea a partir del código de clase es similar: los objetos cambian con más frecuencia que el código que los usa. Un caso importante donde se necesita dicho cambio son las pruebas.
fuente
Probemos un ejemplo simple con las clases de Automóvil y Motor , cualquier automóvil necesita un motor para ir a cualquier parte, al menos por ahora. A continuación, cómo se verá el código sin inyección de dependencia.
Y para crear una instancia de la clase Car, usaremos el siguiente código:
El problema con este código es que lo acoplamos estrechamente a GasEngine y si decidimos cambiarlo a ElectricityEngine, entonces tendremos que reescribir la clase Car. Y cuanto más grande sea la aplicación, más problemas y dolores de cabeza tendremos que agregar y usar un nuevo tipo de motor.
En otras palabras, con este enfoque es que nuestra clase Car de alto nivel depende de la clase GasEngine de nivel inferior que viola el Principio de Inversión de Dependencia (DIP) de SOLID. DIP sugiere que deberíamos depender de abstracciones, no de clases concretas. Entonces, para satisfacer esto, presentamos la interfaz IEngine y reescribimos el código de la siguiente manera:
Ahora nuestra clase Car depende solo de la interfaz IEngine, no de una implementación específica del motor. Ahora, el único truco es cómo creamos una instancia del automóvil y le damos una clase real de motor concreto como GasEngine o ElectricityEngine. Ahí es donde entra la inyección de dependencia .
Aquí básicamente inyectamos (pasamos) nuestra dependencia (instancia del motor) al constructor de automóviles. Entonces, nuestras clases tienen un acoplamiento flexible entre los objetos y sus dependencias, y podemos agregar fácilmente nuevos tipos de motores sin cambiar la clase Car.
El principal beneficio de la Inyección de dependencias es que las clases se acoplan más libremente, porque no tienen dependencias codificadas. Esto sigue el principio de inversión de dependencia, que se mencionó anteriormente. En lugar de hacer referencia a implementaciones específicas, las clases solicitan abstracciones (generalmente interfaces ) que se les proporcionan cuando se construye la clase.
Además, cuando tenemos muchas dependencias, es una muy buena práctica usar contenedores de Inversión de Control (IoC), que podemos decir qué interfaces deben asignarse a qué implementaciones concretas para todas nuestras dependencias y podemos hacer que resuelva esas dependencias cuando construya nuestro objeto Por ejemplo, podríamos especificar en la asignación para el contenedor IoC que la dependencia de IEngine debería asignarse a la clase GasEngine y cuando le pedimos al contenedor IoC una instancia de nuestra clase Car , construirá automáticamente nuestra clase Car con una dependencia GasEngine aprobada en.
ACTUALIZACIÓN: Recientemente vi un curso sobre EF Core de Julie Lerman y también me gustó su breve definición sobre DI.
fuente
Imaginemos que quieres ir a pescar:
Sin la inyección de dependencia, debe ocuparse de todo usted mismo. Necesita encontrar un bote, comprar una caña de pescar, buscar cebo, etc. Es posible, por supuesto, pero le impone una gran responsabilidad. En términos de software, significa que debe realizar una búsqueda de todas estas cosas.
Con la inyección de dependencia, otra persona se encarga de toda la preparación y pone a su disposición el equipo requerido. Recibirá ("se inyectará") el bote, la caña de pescar y el cebo, todo listo para usar.
fuente
Esta es la explicación más simple sobre la inyección de dependencia y el contenedor de inyección de dependencia que he visto:
Sin inyección de dependencia
Con inyección de dependencia
Uso de un recipiente de inyección de dependencia
La inyección de dependencia y los contenedores de inyección de dependencia son cosas diferentes:
No necesita un contenedor para realizar la inyección de dependencia. Sin embargo, un contenedor puede ayudarlo.
fuente
¿No significa "inyección de dependencia" simplemente usar constructores parametrizados y setters públicos?
El artículo de James Shore muestra los siguientes ejemplos para comparación .
fuente
new DatabaseThingie()
no genera una instancia myDatabase válida.Hacer que el concepto de inyección de dependencia sea simple de entender. Tomemos un ejemplo de botón de interruptor para alternar (activar / desactivar) una bombilla.
Sin inyección de dependencia
Switch necesita saber de antemano a qué bombilla estoy conectado (dependencia codificada). Entonces,
Interruptor -> Bombilla permanente // el interruptor está conectado directamente a la bombilla permanente, no es posible realizar pruebas
Con inyección de dependencia
Switch solo sabe que necesito encender / apagar la bombilla que me pasen. Entonces,
Switch -> Bulb1 OR Bulb2 OR NightBulb (dependencia inyectada)
Modificación de James Ejemplo para Switch y Bulb:
fuente
¿Qué es la inyección de dependencia (DI)?
Como otros han dicho, la inyección de dependencia (DI) elimina la responsabilidad de la creación directa y la gestión de la vida útil de otras instancias de objeto de las que depende nuestra clase de interés (clase de consumidor) (en el sentido UML ). En su lugar, estas instancias se pasan a nuestra clase de consumidor, generalmente como parámetros de constructor o mediante establecedores de propiedades (la gestión de la instancia del objeto de dependencia y el paso a la clase de consumidor generalmente se realiza mediante un contenedor de Inversión de control (IoC) , pero ese es otro tema) .
DI, DIP y SÓLIDO
Específicamente, en el paradigma de los principios SÓLIDOS de Robert C Martin de Diseño Orientado a Objetos ,
DI
es una de las posibles implementaciones del Principio de Inversión de Dependencia (DIP) . El DIP es elD
delSOLID
mantra - DIP otras implementaciones incluyen el Servicio de localización, y los patrones de plugin.El objetivo del DIP es desacoplar dependencias apretadas y concretas entre clases y, en cambio, aflojar el acoplamiento por medio de una abstracción, que se puede lograr a través de un
interface
,abstract class
opure virtual class
, dependiendo del lenguaje y el enfoque utilizado.Sin el DIP, nuestro código (lo he llamado 'clase consumidora') está directamente acoplado a una dependencia concreta y a menudo también está cargado con la responsabilidad de saber cómo obtener y administrar una instancia de esta dependencia, es decir, conceptualmente:
Mientras que después de la aplicación del DIP, el requisito se afloja y la preocupación de obtener y administrar la vida útil de la
Foo
dependencia se ha eliminado:¿Por qué usar DIP (y DI)?
El desacoplamiento de las dependencias entre clases de esta manera permite una fácil sustitución de estas clases de dependencia con otras implementaciones que también cumplen los requisitos previos de la abstracción (por ejemplo, la dependencia se puede cambiar con otra implementación de la misma interfaz). Además, como otros han mencionado, posiblemente la razón más común para desacoplar clases a través del DIP es permitir que una clase consumidora se pruebe de forma aislada, ya que estas mismas dependencias ahora se pueden tropezar y / o burlar.
Una consecuencia de DI es que la gestión de la vida útil de las instancias de objetos de dependencia ya no está controlada por una clase consumidora, ya que el objeto de dependencia ahora se pasa a la clase consumidora (mediante inyección de constructor o setter).
Esto se puede ver de diferentes maneras:
Create
en la fábrica, según sea necesario, y eliminar estas instancias una vez que estén completas.¿Cuándo usar DI?
MyDepClass
es seguro para subprocesos, ¿qué pasa si lo convertimos en un singleton e inyectamos la misma instancia a todos los consumidores?)Ejemplo
Aquí hay una implementación simple de C #. Dada la siguiente clase de consumo:
Aunque parezca inocuo, tiene dos
static
dependencias en otras dos clasesSystem.DateTime
ySystem.Console
, lo que no solo limita las opciones de salida de registro (el registro en la consola no tendrá valor si nadie está mirando), sino que es peor, es difícil probar automáticamente dada la dependencia en un reloj de sistema no determinista.Sin embargo, podemos aplicar
DIP
a esta clase, resumiendo la preocupación de la marca de tiempo como una dependencia, y acoplandoMyLogger
solo a una interfaz simple:También podemos aflojar la dependencia
Console
de una abstracción, como aTextWriter
. La inyección de dependencia se implementa típicamente comoconstructor
inyección (pasando una abstracción a una dependencia como parámetro al constructor de una clase consumidora) oSetter Injection
(pasando la dependencia a través de unsetXyz()
setter o una propiedad .Net con{set;}
definido). Se prefiere la inyección de constructor, ya que esto garantiza que la clase estará en un estado correcto después de la construcción y permite que los campos de dependencia internos se marquen comoreadonly
(C #) ofinal
(Java). Entonces, usando la inyección del constructor en el ejemplo anterior, esto nos deja con:(Se
Clock
debe proporcionar un concreto , que por supuesto podría volver aDateTime.Now
, y las dos dependencias deben ser proporcionadas por un contenedor de IoC a través de la inyección del constructor)Se puede construir una prueba unitaria automatizada, que demuestra definitivamente que nuestro registrador funciona correctamente, ya que ahora tenemos control sobre las dependencias, el tiempo, y podemos espiar la salida escrita:
Próximos pasos
La inyección de dependencia se asocia invariablemente con un contenedor de Inversión de control (IoC) , para inyectar (proporcionar) las instancias de dependencia concretas y para administrar instancias de vida útil. Durante el proceso de configuración / arranque, los
IoC
contenedores permiten definir lo siguiente:IBar
, devuelva unaConcreteBar
instancia" )IDisposable
y asumirán la responsabilidad de lasDisposing
dependencias en línea con la gestión de la vida útil configurada.Por lo general, una vez que los contenedores de IoC se han configurado / arrancado, funcionan sin problemas en segundo plano, lo que permite al codificador centrarse en el código disponible en lugar de preocuparse por las dependencias.
Según el ejemplo anterior, el desacoplamiento de dependencias requiere cierto esfuerzo de diseño, y para el desarrollador, se necesita un cambio de paradigma para romper el hábito de
new
crear dependencias directamente y, en su lugar, confiar en el contenedor para administrar las dependencias.Pero los beneficios son muchos, especialmente en la capacidad de evaluar a fondo su clase de interés.
Nota : La creación / cartografía / proyección (a través
new ..()
) de las proyecciones POCO / POJO / serialización DTO / Entidad Gráficos / Anonymous JSON et al - es decir, "sólo datos" clases o registros - usado o regresar de métodos están no considerarse como dependencias (en el Sentido UML) y no sujeto a DI. Usarnew
para proyectar estos está bien.fuente
El objetivo de la inyección de dependencias (DI) es mantener el código fuente de la aplicación limpio y estable :
Prácticamente, cada patrón de diseño separa las preocupaciones para que los cambios futuros afecten a los archivos mínimos.
El dominio específico de DI es la delegación de configuración e inicialización de dependencia.
Ejemplo: DI con script de shell
Si ocasionalmente trabaja fuera de Java, recuerde cómo
source
se usa a menudo en muchos lenguajes de secuencias de comandos (Shell, Tcl, etc., o inclusoimport
en Python mal utilizado para este propósito).Considere
dependent.sh
guión simple :El script depende: no se ejecutará con éxito por sí solo (
archive_files
no está definido).Usted define
archive_files
en laarchive_files_zip.sh
secuencia de comandos de implementación (utilizandozip
en este caso):En lugar de
source
ejecutar el script de implementación directamente en el dependiente, utiliza uninjector.sh
"contenedor" que envuelve ambos "componentes":La
archive_files
dependencia se acaba de inyectar en un script dependiente .Podría haber inyectado dependencia que implementa
archive_files
usandotar
oxz
.Ejemplo: eliminar DI
Si el
dependent.sh
script usara dependencias directamente, el enfoque se llamaría búsqueda de dependencias (que es opuesto a la inyección de dependencias ):Ahora el problema es que el "componente" dependiente tiene que realizar la inicialización por sí mismo.
El código fuente del "componente" no es limpio ni estable porque cada cambio en la inicialización de las dependencias requiere una nueva versión para el archivo de código fuente de los "componentes".
Ultimas palabras
DI no está tan enfatizado y popularizado en gran medida como en los marcos de Java.
Pero es un enfoque genérico para dividir las preocupaciones de:
El uso de la configuración solo con la búsqueda de dependencias no ayuda, ya que el número de parámetros de configuración puede cambiar por dependencia (por ejemplo, nuevo tipo de autenticación), así como el número de tipos de dependencias compatibles (por ejemplo, nuevo tipo de base de datos).
fuente
Todas las respuestas anteriores son buenas, mi objetivo es explicar el concepto de una manera simple para que cualquier persona sin conocimientos de programación también pueda entender el concepto
La inyección de dependencia es uno de los patrones de diseño que nos ayudan a crear sistemas complejos de una manera más simple.
Podemos ver una amplia variedad de aplicaciones de este patrón en nuestro día a día. Algunos de los ejemplos son grabadora de cinta, VCD, unidad de CD, etc.
La imagen de arriba es una imagen de una grabadora de cinta portátil de carrete, de mediados del siglo XX. Fuente .
La intención principal de una máquina grabadora es grabar o reproducir sonido.
Al diseñar un sistema, se requiere un carrete para grabar o reproducir sonido o música. Hay dos posibilidades para diseñar este sistema.
Si usamos el primero, necesitamos abrir la máquina para cambiar el carrete. Si optamos por el segundo, que es colocar un gancho para el carrete, obtendremos un beneficio adicional de reproducir cualquier música al cambiar el carrete. y también reduciendo la función solo a tocar lo que sea en el carrete.
Del mismo modo, la inyección de dependencias es el proceso de externalizar las dependencias para centrarse solo en la funcionalidad específica del componente, de modo que los componentes independientes se puedan acoplar para formar un sistema complejo.
Los principales beneficios que logramos mediante el uso de inyección de dependencia.
Hoy en día, este concepto forma la base de marcos bien conocidos en el mundo de la programación. Spring Angular, etc., son los marcos de software conocidos construidos en la parte superior de este concepto
La inyección de dependencia es un patrón utilizado para crear instancias de objetos de los que dependen otros objetos sin saber en el momento de la compilación qué clase se usará para proporcionar esa funcionalidad o simplemente la forma de inyectar propiedades a un objeto se llama inyección de dependencia.
Ejemplo de inyección de dependencia
Anteriormente estamos escribiendo código como este
Con la inyección de dependencia, el inyector de dependencia nos quitará la instancia
También puedes leer
Diferencia entre inversión de control e inyección de dependencia
fuente
¿Qué es la inyección de dependencia?
La inyección de dependencia (DI) significa desacoplar los objetos que dependen unos de otros. Digamos que el objeto A depende del objeto B, por lo que la idea es desacoplar estos objetos entre sí. No necesitamos codificar el objeto con una nueva palabra clave, en lugar de compartir dependencias con los objetos en tiempo de ejecución a pesar del tiempo de compilación. Si hablamos de
Cómo funciona la inyección de dependencia en primavera:
No necesitamos codificar el objeto con una nueva palabra clave, sino definir la dependencia del bean en el archivo de configuración. El contenedor de resorte será responsable de conectar todo.
Inversión de control (COI)
El COI es un concepto general y se puede expresar de muchas maneras diferentes y la inyección de dependencia es un ejemplo concreto de COI.
Dos tipos de inyección de dependencia:
1. Inyección de dependencia basada en constructor:
La DI basada en el constructor se logra cuando el contenedor invoca un constructor de clase con varios argumentos, cada uno de los cuales representa una dependencia de otra clase.
2. Inyección de dependencia basada en Setter:
La DI basada en Setter se logra mediante los métodos de establecimiento de llamadas de contenedor en sus beans después de invocar un constructor sin argumentos o un método de fábrica estático sin argumentos para instanciar su bean.
NOTA: Es una buena regla general utilizar argumentos de constructor para dependencias obligatorias y establecedores para dependencias opcionales. Tenga en cuenta que si usamos anotaciones basadas en anotaciones @Required en un setter se puede usar para hacer setters como dependencias requeridas.
fuente
La mejor analogía que se me ocurre es el cirujano y su (s) asistente (s) en un quirófano, donde el cirujano es la persona principal y su asistente que proporciona los diversos componentes quirúrgicos cuando los necesita para que el cirujano pueda concentrarse en el Lo que mejor hace (cirugía). Sin el asistente, el cirujano tiene que obtener los componentes él mismo cada vez que necesita uno.
DI para abreviar, es una técnica para eliminar una responsabilidad adicional común (carga) sobre los componentes para obtener los componentes dependientes, proporcionándolos.
DI lo acerca al principio de responsabilidad única (SR), como el
surgeon who can concentrate on surgery
.Cuándo usar DI: recomendaría usar DI en casi todos los proyectos de producción (pequeños / grandes), particularmente en entornos empresariales en constante cambio :)
Por qué: porque desea que su código sea fácilmente comprobable, simulable, etc. para que pueda probar rápidamente sus cambios y llevarlo al mercado. Además, ¿por qué no lo harías cuando hay muchas herramientas / marcos gratuitos increíbles para apoyarte en tu viaje a una base de código donde tienes más control?
fuente
Ejemplo, tenemos 2 clases
Client
yService
.Client
utilizaráService
Sin inyección de dependencia
Camino 1)
Camino 2)
Camino 3)
1) 2) 3) Usando
Ventajas
Desventajas
Client
clase de pruebaService
constructor, necesitamos cambiar el código en todo lugar crearService
objetoUsar inyección de dependencia
Forma 1) Inyección del constructor
Utilizando
Camino 2) Inyección Setter
Utilizando
Forma 3) inyección de interfaz
Verifique https://en.wikipedia.org/wiki/Dependency_injection
===
Ahora, este código ya se sigue
Dependency Injection
y es más fácil para laClient
clase de prueba .Sin embargo, todavía usamos
new Service()
mucho tiempo y no es bueno cuando se cambia elService
constructor. Para evitarlo, podemos usar inyectores DI como1) Manual simple
Injector
Utilizando
2) Usar biblioteca: para Android dagger2
Ventajas
Service
, solo necesita cambiarlo en la clase InyectorConstructor Injection
, cuando observe el constructor deClient
, verá cuántas dependencias de laClient
claseDesventajas
Constructor Injection
, elService
objeto se crea cuando seClient
crea, en algún momento usamos la función enClient
clase sin uso,Service
por lo que crearService
se desperdiciaDefinición de inyección de dependencia
https://en.wikipedia.org/wiki/Dependency_injection
fuente
Significa que los objetos solo deberían tener tantas dependencias como sea necesario para hacer su trabajo y las dependencias deberían ser pocas. Además, las dependencias de un objeto deben estar en interfaces y no en objetos "concretos", cuando sea posible. (Un objeto concreto es cualquier objeto creado con la palabra clave new.) El acoplamiento flojo promueve una mayor reutilización, una capacidad de mantenimiento más fácil y le permite proporcionar fácilmente objetos "simulados" en lugar de servicios caros.
La "Inyección de dependencia" (DI) también se conoce como "Inversión de control" (IoC), se puede utilizar como una técnica para fomentar este acoplamiento flojo.
Hay dos enfoques principales para implementar DI:
Inyección de constructor
Es la técnica de pasar dependencias de objetos a su constructor.
Tenga en cuenta que el constructor acepta una interfaz y no un objeto concreto. Además, tenga en cuenta que se produce una excepción si el parámetro de orden de venta es nulo. Esto enfatiza la importancia de recibir una dependencia válida. La inyección de constructor es, en mi opinión, el mecanismo preferido para dar a un objeto sus dependencias. Es claro para el desarrollador al invocar al objeto qué dependencias deben darse al objeto "Persona" para una ejecución adecuada.
Inyección de Setter
Pero considere el siguiente ejemplo ... Suponga que tiene una clase con diez métodos que no tienen dependencias, pero está agregando un nuevo método que sí depende de IDAO. Puede cambiar el constructor para usar la inyección de constructor, pero esto puede obligarlo a cambiar todas las llamadas de constructor por todas partes. Alternativamente, podría agregar un nuevo constructor que tome la dependencia, pero luego, ¿cómo sabe un desarrollador fácilmente cuándo usar un constructor sobre el otro? Finalmente, si la dependencia es muy costosa de crear, ¿por qué debería crearse y pasarse al constructor cuando solo puede usarse raramente? La "inyección Setter" es otra técnica de DI que se puede utilizar en situaciones como esta.
Setter Injection no obliga a las dependencias a pasar al constructor. En cambio, las dependencias se establecen en propiedades públicas expuestas por el objeto que lo necesita. Como se indicó anteriormente, los principales motivadores para hacer esto incluyen:
Aquí está el ejemplo de cómo se vería el código anterior:
fuente
Creo que como todos han escrito para DI, déjenme hacer algunas preguntas ...
Esto se basa en la respuesta publicada por @Adam N.
¿Por qué PersonService ya no tiene que preocuparse por GroupMembershipService? Usted acaba de mencionar que GroupMembership tiene varias cosas (objetos / propiedades) de las que depende. Si se requiere GMService en PService, lo tendría como una propiedad. Puede burlarse de eso independientemente de si lo inyectó o no. La única vez que me gustaría que se inyectara es si GMService tuviera clases secundarias más específicas, que no sabría hasta el tiempo de ejecución. Entonces querrás inyectar la subclase. O si quisieras usar eso como singleton o prototipo. Para ser sincero, el archivo de configuración tiene todo codificado en cuanto a qué subclase para un tipo (interfaz) va a inyectar durante el tiempo de compilación.
EDITAR
Un buen comentario de Jose Maria Arranz sobre DI
DI aumenta la cohesión al eliminar cualquier necesidad de determinar la dirección de dependencia y escribir cualquier código de pegamento.
Falso. La dirección de las dependencias es en forma XML o como anotaciones, sus dependencias se escriben como código XML y anotaciones. XML y anotaciones SON código fuente.
DI reduce el acoplamiento al hacer que todos sus componentes sean modulares (es decir, reemplazables) y tengan interfaces bien definidas entre sí.
Falso. No necesita un marco DI para construir un código modular basado en interfaces.
Acerca de reemplazable: con un archivo .properties muy simple y Class.forName puede definir qué clases pueden cambiar. Si se puede cambiar CUALQUIER clase de su código, Java no es para usted, use un lenguaje de script. Por cierto: las anotaciones no se pueden cambiar sin volver a compilar.
En mi opinión, hay una única razón para los marcos DI: la reducción de la placa de la caldera. Con un sistema de fábrica bien hecho, puede hacer lo mismo, más controlado y más predecible que su marco DI preferido, los marcos DI prometen reducción de código (XML y las anotaciones también son código fuente). El problema es que esta reducción de placa de caldera es real en casos muy simples (una instancia por clase y similar), a veces en el mundo real elegir el objeto de servicio apropiado no es tan fácil como asignar una clase a un objeto singleton.
fuente
Las respuestas populares no son útiles, porque definen la inyección de dependencia de una manera que no es útil. Acordemos que por "dependencia" nos referimos a algún otro objeto preexistente que nuestro objeto X necesita. Pero no decimos que estamos haciendo "inyección de dependencia" cuando decimos
Simplemente llamamos a eso pasar parámetros al constructor. Lo hemos estado haciendo regularmente desde que se inventaron los constructores.
La "inyección de dependencia" se considera un tipo de "inversión de control", lo que significa que la persona que llama extrae algo de lógica. Ese no es el caso cuando la persona que llama pasa los parámetros, por lo que si fuera DI, DI no implicaría una inversión de control.
DI significa que hay un nivel intermedio entre el llamador y el constructor que gestiona las dependencias. Un Makefile es un ejemplo simple de inyección de dependencia. La "persona que llama" es la persona que escribe "make bar" en la línea de comandos, y el "constructor" es el compilador. El Makefile especifica que la barra depende de foo, y hace un
antes de hacer un
La persona que escribe "make bar" no necesita saber que la barra depende de foo. La dependencia se inyectó entre "make bar" y gcc.
El objetivo principal del nivel intermedio no es solo pasar las dependencias al constructor, sino enumerar todas las dependencias en un solo lugar y ocultarlas del codificador (no hacer que el codificador las proporcione).
Por lo general, el nivel intermedio proporciona fábricas para los objetos construidos, que deben proporcionar un rol que cada tipo de objeto solicitado debe cumplir. Esto se debe a que al tener un nivel intermedio que oculta los detalles de la construcción, ya ha incurrido en la penalización por abstracción impuesta por las fábricas, por lo que también podría usar fábricas.
fuente
La inyección de dependencias significa una forma (en realidad de cualquier manera ) para que una parte del código (por ejemplo, una clase) tenga acceso a las dependencias (otras partes del código, por ejemplo, otras clases, de las que depende) de forma modular sin que estén codificadas (por lo tanto, pueden cambiar o anularse libremente, o incluso cargarse en otro momento, según sea necesario)
(y ps, sí, se ha convertido en un nombre demasiado exagerado de 25 $ para un concepto bastante simple) , mis
.25
centavosfuente
Sé que ya hay muchas respuestas, pero encontré esto muy útil: http://tutorials.jenkov.com/dependency-injection/index.html
Sin dependencia:
Dependencia:
Observe cómo la
DataSourceImpl
instanciación se traslada a un constructor. El constructor toma cuatro parámetros, que son los cuatro valores que necesita elDataSourceImpl
. Aunque laMyDao
clase todavía depende de estos cuatro valores, ya no satisface estas dependencias. Los proporciona cualquier clase que cree unaMyDao
instancia.fuente
La inyección de dependencia es una posible solución a lo que generalmente se podría llamar el requisito de "Ofuscación de dependencia". La ofuscación de dependencia es un método para eliminar la naturaleza 'obvia' del proceso de proporcionar una dependencia a una clase que lo requiere y, por lo tanto, ofuscar, de alguna manera, la provisión de dicha dependencia a dicha clase. Este no es necesariamente algo malo. De hecho, al ofuscar la manera en que se proporciona una dependencia a una clase, entonces algo fuera de la clase es responsable de crear la dependencia, lo que significa que, en varios escenarios, se puede proporcionar una implementación diferente de la dependencia a la clase sin realizar ningún cambio a la clase. Esto es ideal para cambiar entre los modos de producción y prueba (p. Ej., Utilizando una dependencia de servicio 'simulada').
Desafortunadamente, lo malo es que algunas personas han asumido que necesita un marco especializado para ofuscar la dependencia y que de alguna manera es un programador 'menor' si elige no usar un marco particular para hacerlo. Otro mito extremadamente perturbador, que muchos creen, es que la inyección de dependencia es la única forma de lograr la ofuscación de dependencia. Esto es demostrable e histórica y obviamente 100% incorrecto, pero tendrá problemas para convencer a algunas personas de que existen alternativas a la inyección de dependencia para sus requisitos de ofuscación de dependencia.
Los programadores han entendido el requisito de ofuscación de dependencia durante años y muchas soluciones alternativas han evolucionado tanto antes como después de concebir la inyección de dependencia. Existen patrones de fábrica, pero también hay muchas opciones que usan ThreadLocal donde no se necesita una inyección en una instancia particular: la dependencia se inyecta efectivamente en el hilo que tiene el beneficio de hacer que el objeto esté disponible (mediante métodos convenientes de obtención estática) para cualquierclase que lo requiere sin tener que agregar anotaciones a las clases que lo requieren y configurar intrincados 'pegamentos' XML para que esto suceda. Cuando sus dependencias son necesarias para la persistencia (JPA / JDO o lo que sea), le permite lograr una 'persistencia transnaparente' mucho más fácil y con clases de modelo de dominio y modelo de negocio formadas exclusivamente por POJO (es decir, sin marco específico / bloqueado en anotaciones).
fuente
Del libro, ' Desarrollador Java bien fundamentado: técnicas vitales de Java 7 y programación políglota
fuente
Antes de pasar a la descripción técnica, visualícelo primero con un ejemplo de la vida real porque encontrará muchas cosas técnicas para aprender la inyección de dependencia, pero el tiempo máximo que la gente como yo no puede entender el concepto principal.
En la primera imagen, suponga que tiene una fábrica de automóviles con muchas unidades. En realidad, un automóvil está construido en la unidad de ensamblaje, pero necesita motor , asientos y ruedas . Por lo tanto , la unidad de ensamblaje depende de todas estas unidades y son las dependencias de la fábrica.
Puede sentir que ahora es demasiado complicado mantener todas las tareas en esta fábrica porque junto con la tarea principal (ensamblar el automóvil en la unidad de ensamblaje) también debe centrarse en otras unidades . Ahora es muy costoso de mantener y el edificio de la fábrica es enorme, por lo que toma sus dólares extra en alquiler.
Ahora, mira la segunda imagen. Si encuentra algunas compañías proveedoras que le proporcionarán ruedas , asientos y motores más baratos que su costo de autoproducción, entonces no necesita fabricarlos en su fábrica. Puede alquilar un edificio más pequeño ahora solo para su unidad de ensamblaje, lo que disminuirá su tarea de mantenimiento y reducirá el costo adicional de alquiler. Ahora también puede centrarse solo en su tarea principal (montaje del automóvil).
Ahora podemos decir que todas las dependencias para ensamblar un automóvil se inyectan en la fábrica de los proveedores . Es un ejemplo de una inyección de dependencia (DI) de la vida real .
Ahora, en términos técnicos, la inyección de dependencias es una técnica mediante la cual un objeto (o método estático) suministra las dependencias de otro objeto. Entonces, transferir la tarea de crear el objeto a otra persona y usar directamente la dependencia se llama inyección de dependencia.
Esto te ayudará ahora a aprender DI con algunas palabras técnicas. Esto mostrará cuándo usar DI y cuándo no .
.
fuente
de Book Apress.Spring.Persistence.with.Hibernate.Oct.2010
fuente
La inyección de dependencia (DI) es una de Design Patterns, que utiliza la característica básica de OOP: la relación en un objeto con otro objeto. Mientras que la herencia hereda un objeto para hacer otro objeto más complejo y específico, la relación o asociación simplemente crea un puntero a otro objeto desde un objeto usando un atributo. El poder de DI está en combinación con otras características de OOP como son las interfaces y el código oculto. Supongamos que tenemos un cliente (suscriptor) en la biblioteca, que puede tomar prestado un solo libro por simplicidad.
Interfaz de libro:
Luego podemos tener muchos tipos de libros; uno de tipo es ficción:
Ahora el suscriptor puede tener asociación con el libro:
Las tres clases se pueden ocultar para su propia implementación. Ahora podemos usar este código para DI:
Hay muchas formas diferentes de usar la inyección de dependencia. Es posible combinarlo con Singleton, etc., pero aún así, en la base, solo es una asociación realizada creando un atributo de tipo de objeto dentro de otro objeto. La utilidad es única y única en la característica, ese código, que debemos escribir una y otra vez, siempre está preparado y hecho para que lo enviemos. Esta es la razón por la cual DI se vinculó tan estrechamente con la Inversión de Control (IoC), lo que significa que nuestro programa pasa el control de otro módulo en ejecución, que inyecta frijoles a nuestro código. (Cada objeto, que se puede inyectar, se puede firmar o considerar como un Bean). Por ejemplo, en Spring se realiza creando e inicializando ApplicationContextcontenedor, que funciona para nosotros. Simplemente en nuestro código creamos el Contexto e invocamos la inicialización de los beans. En ese momento la inyección se ha realizado automáticamente.
fuente
Inyección de dependencia para niños de 5 años.
Cuando sale y saca cosas del refrigerador por sí mismo, puede causar problemas. Puede dejar la puerta abierta, puede obtener algo que mamá o papá no quieren que tenga. Incluso podría estar buscando algo que ni siquiera tenemos o que ha expirado.
Lo que debe hacer es declarar una necesidad, "Necesito algo de beber con el almuerzo", y luego nos aseguraremos de que tenga algo cuando se siente a comer.
fuente
De Christoffer Noring, el libro de Pablo Deeleman "Learning Angular - Second Edition":
"A medida que nuestras aplicaciones crecen y evolucionan, cada una de nuestras entidades de código requerirá internamente instancias de otros objetos , que se conocen mejor como dependencias en el mundo de la ingeniería de software. La acción de pasar tales dependencias al cliente dependiente se conoce como inyección , y también implica la participación de otra entidad de código, llamada el inyector . El inyector se responsabilizará de crear instancias y arrancar lo requerido dependenciaspor lo que están listos para usar desde el momento en que se inyectan con éxito en el cliente. Esto es muy importante ya que el cliente no sabe nada sobre cómo crear instancias de sus propias dependencias y solo conoce la interfaz que implementa para usarlas ".
De: Anton Moiseev. libro "Desarrollo angular con mecanografiado, segunda edición":
"En resumen, DI le ayuda a escribir código de una manera débilmente acoplada y hace que su código sea más verificable y reutilizable ".
fuente
En palabras simples, la inyección de dependencias (DI) es la forma de eliminar dependencias o un acoplamiento estrecho entre diferentes objetos. La inyección de dependencia da un comportamiento coherente a cada objeto.
DI es la implementación del director del COI de Spring que dice "No nos llame, lo llamaremos". El uso del programador de inyección de dependencias no necesita crear objetos usando la nueva palabra clave.
Los objetos se cargan una vez en el contenedor Spring y luego los reutilizamos cuando los necesitamos buscando esos objetos desde el contenedor Spring usando el método getBean (String beanName).
fuente
La inyección de dependencia es el corazón del concepto relacionado con Spring Framework. Mientras que la creación del marco de cualquier proyecto Spring puede desempeñar un papel vital, y aquí la inyección de dependencia viene en el lanzador.
En realidad, supongamos que en Java creó dos clases diferentes como clase A y clase B, y cualquiera que sea la función disponible en la clase B que quiera usar en la clase A, entonces en ese momento se puede usar la inyección de dependencia. donde puede crear objetos de una clase en otra, de la misma manera que puede inyectar una clase completa en otra clase para que sea accesible. de esta manera se puede superar la dependencia.
LA INYECCIÓN DE DEPENDENCIA SIMPLEMENTE PEGA DOS CLASES Y AL MISMO TIEMPO MANTÉNDOLAS SEPARADAS.
fuente