¿Cuáles son los beneficios de usar la inyección de dependencia y los contenedores IoC?

62

Estoy planeando hacer una charla sobre la inyección de dependencia y los contenedores de IoC, y estoy buscando algunos buenos argumentos para usarlo.

¿Cuáles son los beneficios más importantes de usar esta técnica y estas herramientas?

Andy Lowry
fuente
1
Vea aquí y aquí las respuestas de StackOverflow y aquí un buen artículo completo sobre IoC. Y si quieres argumentos en contra para comparar, dirígete aquí a SO.
Jesse C. Slicer
14
no para ser un trasero ... pero si no sabes por qué se debe usar DI / IOC, ¿por qué estás hablando de eso? perder una apuesta? ;-)
Steven A. Lowe
2
@ Steven, su jefe podría haberle pedido que lo hiciera.
1
@ Steven, ya uso DI todo el tiempo (algunos dirían con demasiada frecuencia :-D), solo estoy buscando algunos buenos argumentos para que otras personas lo usen.
Andy Lowry el
2
La gente rara vez habla sobre el uso excesivo de DI. Si retrasa cada decisión, creará el equivalente OO del código de espagueti. Tener un diseño coherente requiere que, en algún momento, se tome una decisión real.
Macneil

Respuestas:

47

Lo más importante, para mí, es facilitar el cumplimiento del Principio de responsabilidad única .

DI / IoC me facilita la gestión de dependencias entre objetos. A su vez, eso me facilita dividir la funcionalidad coherente en su propio contrato (interfaz). Como resultado, mi código se ha modularizado mucho más desde que supe de DI / IoC.

Otro resultado de esto es que puedo ver mucho más fácilmente mi camino hacia un diseño que admita el Principio Abierto-Cerrado . Esta es una de las técnicas más inspiradoras de confianza (solo superada por las pruebas automatizadas). Dudo que pueda defender las virtudes del Principio Abierto-Cerrado lo suficiente.

DI / IoC es una de las pocas cosas en mi carrera de programación que ha sido un "cambio de juego". Hay una gran brecha en la calidad entre el código que escribí antes y después de aprender DI / IoC. Permítanme enfatizar eso un poco más. ENORME mejora en la calidad del código.

quentin-starin
fuente
3
¿Por qué es tan importante el principio abierto-cerrado? Si siente que necesita cambiar una API / interfaz, ¿por qué no debería hacerlo?
Arne Evertsson
@ArneEvertsson Escuche a Robert C. Martin hablar sobre el Principio Abierto-Cerrado. Serás iluminado.
Alternatex
@AmeEvertsson Open-Closed es muy importante cuando se proporciona su código (por ejemplo, como un producto comercial) como un módulo para que otros lo usen, ya que hace que su código sea más adaptable en uso sin que recurran a usted para cambiarlo
James Ellis-Jones
2
DI no simplifica la gestión de dependencias, ya que es considerablemente más complejo que simplemente crear una dependencia a una clase concreta. Sin embargo, proporciona flexibilidad, pero a menos que esté haciendo pruebas de unidad 'adecuadas', esa flexibilidad a menudo no será necesaria. Ambas ventajas clave descritas también se aplican al Localizador de servicios, que es más simple.
James Ellis-Jones
1
Voté esta respuesta hace años; Aquí hay algunos comentarios: 1) En la práctica, el uso extenso de DI tiende a funcionar contra SRP, porque los programadores simplemente siguen agregando métodos a sus "controladores", "servicios", "DAO", etc., en lugar de crear nuevas clases para Nueva funcionalidad. Es lo que normalmente ve suceder en proyectos Java y C # .NET que usan algún marco DI o contenedor. 2) El principio abierto-cerrado fue solo la ilusión de Bertrand Meyer sobre la utilidad de la herencia de clase (implementación); si lo busca en su libro de más de 1400 páginas, verá lo que quiero decir: es realmente una tontería.
Rogério
9

Los ejemplos que realmente me abrieron los ojos fueron ver cómo hacía posible probar fácilmente los objetos creados de esta manera. Antes de eso, tuve problemas para intentar aislar objetos para una prueba unitaria. A menudo escribía pruebas para interactuar con un sistema mucho más grande. Esto fue realmente difícil porque el sistema en su conjunto era mucho menos predecible y mucho más propenso a cambiar que los componentes individuales.

Winston Ewert
fuente
3

Las ventajas de las inyecciones de dependencia son:

  1. Su código es limpio y más legible.
  2. Los códigos están sueltamente acoplados.
  3. Más reutilizable ya que las implementaciones se configuran en el archivo XML, se puede utilizar en un contexto diferente.
  4. El código puede ser fácilmente comprobable con diferentes implementaciones simuladas.
Solaimani SA
fuente
1

Creo que los beneficios reales son más políticos que técnicos. DI es simplemente una alternativa al patrón Localizador de servicios , nada más. Por sí solo, no hace que sea más fácil seguir principios como SRP u OCP, ni desacoplar capas. Otros encuestados aquí están confundiendo diferentes conceptos y técnicas, en mi opinión.

Puede lograr los mismos objetivos con respecto a la alta cohesión y el bajo acoplamiento mediante el uso de localizadores de servicios, o simplemente creando instancias de dependencias directamente cuando corresponda (que es la mayor parte del tiempo).

Ahora, sé que muchos estarán en desacuerdo con esta opinión. Estaré encantado de discutir ejemplos concretos.

Rogério
fuente
2
Pero invocar directamente un localizador de servicios o crear instancias de una dependencia concreta generalmente conecta sus dependencias, o al menos de dónde provienen sus dependencias. Eso parece derrotar el propósito de DI. Todavía tiene que inyectar el localizador de servicios también.
Matt H
El uso de un Localizador de servicios no conecta nada excepto el uso de la clase Localizador de servicios, que normalmente no se "inyecta". Crear instancias de una clase de implementación concreta está perfectamente bien en casos en los que no necesita una configuración externa (por ejemplo, los programadores generalmente crean instancias directamente de la clase ArrayList en lugar de usar DI, lo cual sería excesivo).
Rogério
1
Usted menciona "bajo acoplamiento" y luego dice que un localizador de servicios no tiene impacto en el nivel de acoplamiento de una aplicación. Lo mismo para crear instancias de colaboradores directamente en el código, no puedo pensar en una forma más perfecta de acoplar un objeto con sus dependencias. ¿Cómo prueba la unidad en ambos escenarios? Respetuosamente, estoy completamente en desacuerdo con todo lo que dijiste.
Clint Eastwood
@ Jonathan Deberías leer el artículo que introdujo DI entonces; el autor concluye diciendo que DI y ServiceLocator son "más o menos equivalentes", con una "ligera ventaja" para este último. El acoplamiento que importa es entre un componente y otros componentes que pueden tener múltiples implementaciones; un ServiceLocator es un servicio de infraestructura con una sola implementación, por lo que está bien. Tenga en cuenta que escribí "crear instancias de dependencias cuando corresponda "; por supuesto, si necesita separar la configuración del uso, no lo haría.
Rogério
1
@ Jonathan En cuanto a las pruebas unitarias, es un mito que la creación de instancias de los colaboradores impide la creación de tales pruebas; Existen herramientas de burla bien conocidas que hacen el trabajo de aislar una clase de las implementaciones de dependencia, ya sean inyectadas o no.
Rogério
-1

Cuando se usa DI para exponer objetos internos con el propósito de probar, el patrón ha sido abusado.

Thomas-Peter
fuente
1
¿Qué quieres decir con "objetos internos"? en OOP real (tenga en cuenta que probablemente solo el 1% de los programadores sabe lo que realmente significa), hay objetos que se comunican entre sí mediante el envío de mensajes (es decir, invocaciones de métodos). En ese sentido, cada objeto debe tener una única responsabilidad, no hay objetos "más importantes" que otros ... cada uno tiene un solo deber y cooperan para lograr la funcionalidad proporcionada por todo el sistema. Es importante probar cada objeto de forma aislada para que sepamos que no hemos perdido ningún caso, para eso es que DI es realmente bueno.
Clint Eastwood
He olvidado.
thomas-peter