Globales vs dependency injection

Algunas personas dicen que es mejor usar la dependency injection. ¿Porqué es eso?

Creo que es mejor tener pocas clases globales y de fácil acceso, en lugar de grandes constructores.

¿Influye de alguna manera la velocidad de aplicación?

Mezcla de estos dos sería probablemente el mejor.

La principal ventaja será el desacoplamiento , lo que ayudará con las pruebas unitarias. Esto depende completamente de cómo codifiques estas “clases fácilmente accesibles”.

La idea es esta. Una clase se separa de las dependencias de implementación ( class ) al tener solo una dependencia en el contrato ( interface ). Es posible que en su entorno en vivo nunca proporcione una nueva clase de implementación, pero en su entorno de prueba es muy probable que lo haga (ya sea una colilla hecha a mano o una clase burlada desde un marco de burla).

La velocidad de la aplicación necesitaría un perfil, pero el uso de un marco para DI probablemente incurriría en una sobrecarga en lugar de que usted hablara directamente con un singleton que usted conoce. La pregunta importante: ¿es esta sobrecarga un problema? Solo las expectativas de rendimiento y el perfil pueden decirlo. En mi experiencia, los beneficios superan con creces el detrimento de rendimiento insignificante.

Probablemente estés usando clases y métodos static como tus Globales. No tienen ninguna implicación de rendimiento. Sin embargo, las clases estáticas no se prestan a la capacidad de prueba .

¿Cuáles son las desventajas de los métodos estáticos?

Además, una vez que su código esté estrechamente acoplado a clases estáticas (Globales), no podrá reemplazarlos con implementaciones alternativas en el futuro. Por lo tanto, los Globales pueden no ser un buen diseño a menos que se utilicen en situaciones muy simplistas.

Tenga en cuenta que las clases y los métodos estáticos son enlaces de tiempo de comstackción donde, como DI, son enlaces de tiempo de ejecución . Te ayuda a mantener tus clases débilmente acopladas .

Hay una gran diferencia entre el uso de “globales” y DI. Primero, la ruta generalmente no está dirigida porque probablemente recorra el localizador de servicios y singleton . Ambos se consideran de alguna manera un anti-patrón de hoy. La razón es que se supone que debemos diseñar un código comprobable, que nos brinda grandes ventajas cuando necesitamos cambiar la base del código para el mantenimiento o para satisfacer nuevos requisitos. La capacidad de prueba es fácil de lograr si el código está desacoplado. Como adivina, los comportamientos globales no ayudan a desacoplar, así que, por ejemplo, si tiene un código que se adhiere a un singleton estático, para probar dicho código necesita el singleton en sí mismo, no puede burlarse de él, y esto es malo porque no puede Tensiona tu sistema como quieras. El localizador de servicios parece, a primera vista, mejor: puede burlarse de él evantualmente si necesita realizar una prueba, pero debe:

  • Sepa de antemano qué servicio (s) le preguntará al localizador el sistema bajo prueba
  • Siempre cree un “simulacro recursivo” porque probablemente también se burlaría del servicio devuelto.

El DI en el constructor es una buena forma de desacoplar el código porque indica muy claramente lo que el objeto necesita para ejecutar, y puede decidir de un vistazo qué simular, tallar y así sucesivamente. Preste atención a que DI funcionará y le ayudará solo si se asegura de no tener el kernel de DI como una dependencia a través de su código: esto transformaría la DI en un antipatrón (desacopla el código, pero lo une a un contenedor), por lo que recuerde estudiar e implementar realmente el patrón de raíz de omposición , esto le ayudará a escribir un código mejor y más comprobable.

Creo que la publicación principal sobre este tema tiene un muy buen resumen de DI y cómo usarlo de la manera correcta: Dependency Inject (DI) “amigable” de la biblioteca

Si desea profundizar en el tema, puedo recomendar el libro “Dependency Injection in .NET” de Mark Seeman.