Fuera de los marcos de inyección de dependencia, la inyección de dependencia (a través de la inyección del constructor o la inyección del colocador) es casi un juego de suma cero: disminuye el acoplamiento entre el objeto A y su dependencia B, pero ahora cualquier objeto que necesite una instancia de A debe ahora también construir el objeto B.
Ha reducido ligeramente el acoplamiento entre A y B, pero se ha reducido la encapsulación de A, y se ha incrementado el acoplamiento entre A y cualquier clase que debe construir una instancia de A, al acoplarlas también a las dependencias de A.
Por lo tanto, la inyección de dependencia (sin un marco) es igualmente dañina, ya que es útil.
El costo adicional suele ser fácilmente justificable, sin embargo: si el código del cliente sabe más sobre cómo construir la dependencia que el objeto en sí mismo, la inyección de dependencia realmente reduce el acoplamiento; por ejemplo, un Escáner no sabe mucho acerca de cómo obtener o construir un flujo de entrada para analizar la entrada, o de qué fuente el código del cliente quiere analizar la entrada, por lo que la inyección del constructor de un flujo de entrada es la solución obvia. p>
Las pruebas son otra justificación, para poder utilizar dependencias simuladas. Eso debería significar agregar un constructor adicional utilizado solo para pruebas que permita inyectar dependencias: si en cambio, cambia sus constructores para que siempre requieran inyectar dependencias, de repente, debe conocer las dependencias de sus dependencias para poder construir sus dependencias. dependencias directas, y usted no puede hacer ningún trabajo.
Puede ser útil, pero definitivamente debería preguntarse por cada dependencia, ¿vale la pena el costo de la prueba y realmente voy a querer burlarme de esta dependencia durante la prueba?
Cuando se agrega un marco de inyección de dependencia y la construcción de dependencias se delega no al código del cliente, sino al marco, el análisis de costo / beneficio cambia enormemente.
En un marco de inyección de dependencia, las compensaciones son un poco diferentes; lo que está perdiendo al inyectar una dependencia es la capacidad de saber fácilmente en qué implementación está confiando, y cambiar la responsabilidad de decidir en qué dependencia está confiando en algún proceso de resolución automatizado (por ejemplo, si necesitamos un Foo @ inyectado). , debe haber algo que @Provides Foo, y cuyas dependencias inyectadas estén disponibles), o para algún archivo de configuración de alto nivel que indique qué proveedor se debe usar para cada recurso, o para algún híbrido de los dos (por ejemplo, puede ser un proceso de resolución automatizado para dependencias que pueden ser anuladas, si es necesario, usando un archivo de configuración).
Al igual que en la inyección de constructores, creo que la ventaja de hacerlo termina siendo, de nuevo, muy similar al costo de hacerlo: no tiene que saber quién proporciona los datos en los que confía y, si los hay. Si hay varios proveedores potenciales, no tiene que saber cuál es el orden preferido para buscar proveedores, asegúrese de que todas las ubicaciones que necesitan los datos verifiquen a todos los proveedores potenciales, etc., porque todo eso se maneja a un alto nivel. La plataforma de inyección de dependencias.
Aunque personalmente no tengo mucha experiencia con los marcos DI, mi impresión es que ofrecen más beneficios que costos cuando el dolor de cabeza de encontrar el proveedor correcto de los datos o servicios que necesita tiene un costo mayor que el dolor de cabeza, cuando algo falla, de no saber de manera local qué código proporcionó los datos incorrectos que causaron una falla posterior en su código.
En algunos casos, otros patrones que ocultan las dependencias (p. ej., localizadores de servicios) ya se habían adoptado (y quizás también han demostrado su valor) cuando aparecieron los marcos DI en la escena, y se adoptaron los marcos DI porque ofrecían alguna ventaja competitiva. como requerir menos código repetitivo, o posiblemente hacer menos para ocultar al proveedor la dependencia cuando sea necesario determinar qué proveedor está realmente en uso.