¿Los marcos de inyección de dependencia plantean un riesgo de dependencia?

13

He estado refactorizando un sistema existente para usar la inyección de dependencia, y ese trabajo ha ido sin problemas.

Después de un tiempo, noté que una gran cantidad de bibliotecas internas se volvieron dependientes del marco DI que utilicé. Como resultado, todo el proyecto ahora depende de este marco de terceros.

Vi una ironía en desacoplar todas las dependencias al hacerlas dependientes de una biblioteca compartida.

Mi primera reacción fue crear una biblioteca contenedor alrededor del marco de dependencia. Por lo tanto, podría reemplazar este marco si es necesario. Después de estimar el trabajo involucrado, me di cuenta de que la API resultante sería similar al marco existente y, por lo tanto, dificultaría su reemplazo. Entonces abandoné la idea.

Mi preocupación es que el marco DI que estoy usando se vuelve obsoleto o necesita ser reemplazado.

¿Existe un patrón de desarrollo cuando se trabaja con DI que reduce el acoplamiento entre un proyecto y el marco de DI?

Reactgular
fuente
44
El patrón "no usar un marco DI". Aunque debo preguntarme si está resolviendo un problema que realmente no tiene: ¿qué posibilidades tiene de cambiar el marco DI?
Oded
1
@Oded un buen marco DI debería poder trabajar con código de forma transparente, pero hay casos en los que eso no es posible. Luego debe usar las API DI dentro de sus clases. En esos casos, es difícil compartir o cambiar el marco DI sin necesidad de cambiar esas clases. Dado que esta es la primera vez que trabajo con ese marco DI. No estoy seguro si tendré que reemplazarlo.
Reactgular
8
Su sistema también depende de la electricidad. Te sugiero que desacoples eso primero.
Idan Arye
3
@MathewFoscarini ¿No es esto un antipatrón? Puedes hacerlo, pero no deberías, ya que ofusca la dependencia.
maaartinus
2
@MathewFoscarini DIFramework.Get<IService>()no es realmente una inyección de dependencia; Es un patrón relacionado llamado Service Locator. A muchas personas no les gusta el Localizador de servicios porque lo une al marco y porque se abusa demasiado fácilmente (como Singleton). Martin Fowler tiene un excelente artículo sobre estos patrones: martinfowler.com/articles/injection.html
Benjamin Hodgson

Respuestas:

8

Tiene toda la razón: el uso de un marco DI probablemente hará que su código dependa de eso. En realidad, eso es demasiado sorprendente, ya que esto suele ser cierto para cualquier otro marco o biblioteca de base, especialmente cuando esa biblioteca admite su proyecto con algunas características genéricas utilizadas en cualquier parte de su código. Por ejemplo, cuando decide usar un determinado marco de UI o marco web, esta decisión es difícil de cambiar luego de haber creado una cierta cantidad de código basado en esa biblioteca. Cuando decide utilizar una Stringclase específica (quizás no estándar) , no puede cambiar fácilmente esa decisión más adelante. Tal decisión es arquitectónica, es como elegir un cierto lenguaje de programación e intentar cambiar esa decisión después de haber escrito> 100K líneas de código.

El hecho de que todo su código dependa de un determinado marco podría no ser un problema, siempre y cuando haga lo que espera de él y siempre que se mantenga correctamente. Pero puede convertirse en un problema si ese no es el caso. Hay algunas estrategias para lidiar con esa situación:

  • elija un marco de un proveedor en el que tenga confianza y que pueda entregarle actualizaciones y nuevos lanzamientos durante varios años a partir de ahora

  • elija un marco de código abierto que tenga pocas líneas de código suficientes (y una licencia adecuada), para que pueda realizar cualquier mantenimiento por su cuenta, dado que el proveedor desaparece del mercado

  • escribe tu propio marco

  • vivir con la situación mientras el vendedor esté disponible, y cuando realmente desaparezca, elija un marco diferente e intente crear un adaptador que emule el marco antiguo usando el nuevo

La idea de crear una biblioteca de contenedor de antemano no es nueva en absoluto, pero rara vez he visto que funciona, ya que tendrías que hacer suposiciones para una situación futura en la que no sabes si te golpeará o cuándo, y qué el "nuevo" marco se verá así. Por otro lado, hace algunos años intercambiamos con éxito un marco de interfaz de usuario completo en un proyecto C ++ con ~ 120K de líneas de código aplicando la estrategia de adaptador que mencioné anteriormente.

Doc Brown
fuente
19

La inyección de constructor ordinario no requiere un marco en absoluto. Lo único que pierde es la capacidad de centralizar sus dependencias en un archivo de configuración.

Los contenedores DI son un patrón de "software empresarial", que se utiliza cuando el gráfico de objetos es muy grande y complejo. Sospecho que el 95% de las aplicaciones no lo requieren.

Robert Harvey
fuente
55
Estoy de acuerdo en que los proyectos pequeños no lo requieren , pero más del 95% de los proyectos pueden beneficiarse de él.
maaartinus
11
@maaartinus: Complejidad adicional innecesaria para un beneficio mínimo.
Robert Harvey
1
¿Que? Estas son mis estadísticas por clase: 0.5 anotaciones, 0.1 línea de configuración. Entonces, ¿a qué complejidad te refieres?
maaartinus
2
@RobertHarvey: aunque estoy 100% de acuerdo con sus declaraciones anteriores, el OP afirma que ya ha introducido un marco DI. Decirle "mejor no" no es realmente una respuesta a su pregunta.
Doc Brown
1
@maaartinus cuanto más automatiza el marco y más cosas puede inyectar, más complejo. Hay archivos de configuración XML, inyección de constructor, inyección de propiedad, burla automática de objetos, inyección diferida, etc., etc. Estos marcos DI pueden volverse muy complejos.
Reactgular
0

No creo que los marcos DI puedan volverse obsoletos en el corto plazo. ¿Qué debería pasar para que quede obsoleto?

  • ¿Una invención de un patrón nuevo e inteligente tal vez? Sin embargo, debería parecer que requeriría cambios mucho más grandes en el código.
  • ¿Un cambio en el idioma tal vez? Peor aún.

Yo diría que la DI actual es lo suficientemente madura y no estoy al tanto de que suceda mucho allí. No ha especificado su idioma, por lo tanto, hablando de Guice , es bastante discreto y funciona con anotaciones estándar de Java (también usa el suyo propio para cosas no estandarizadas, pero rara vez lo necesita). Es de código abierto, ampliamente utilizado y con licencia de Apache. ¿Cual podría ser el problema?

Estoy bastante seguro de que cambiar el marco DI sería mucho más fácil que cambiar cualquier otra biblioteca (por ejemplo, un cambio en la interfaz de usuario significa mucho más trabajo).

maaartinus
fuente