Tengo una gran base de código con muchos singletons "antipatrón", clases de utilidad con métodos estáticos y clases que crean sus propias dependencias usando new
palabras clave. Hace que un código sea muy difícil de probar.
Quiero migrar gradualmente el código al contenedor de inyección de dependencia (en mi caso Guice
, porque es un GWT
proyecto). Desde mi entendimiento de la inyección de dependencia, es todo o nada. O bien Spring / Guice maneja todas las clases o ninguna. Como la base de código es grande, no puedo transformar el código durante la noche. Entonces necesito una forma de hacerlo gradualmente.
El problema es que cuando comienzo con una clase que necesita ser inyectada en otras clases, no puedo usar un simple @Inject
en esas clases, porque esas clases aún no están administradas por el contenedor. Por lo tanto, esto crea una larga cadena hasta las clases "superiores" que no se inyectan en ninguna parte.
La única forma en que veo es hacer que un Injector
contexto / application esté disponible globalmente a través de un singleton por el momento, para que otras clases puedan obtener un bean administrado de él. Pero contradice la idea importante de no revelar composition root
la aplicación.
Otro enfoque sería de abajo hacia arriba: para comenzar con clases de "alto nivel", inclúyalas en el contenedor de inyección de dependencia y baje lentamente a clases "más pequeñas". Pero luego tengo que esperar mucho tiempo, ya que puedo probar esas clases más pequeñas que aún dependen de las variables globales / estáticas.
¿Cuál sería la forma de lograr una migración tan gradual?
PD La pregunta Acercamientos graduales a la inyección de dependencia es similar en el título, pero no responde a mi pregunta.
fuente
Respuestas:
En este momento
C#
es mi idioma de su elección, puedo leerJava
pero probablemente descuartizar la sintaxis tratando de escribirlo ... Los mismos conceptos se aplican entreC#
yJava
aunque, por lo que espero que esto se mostrarán los pasos de cómo se puede mover gradualmente su base de código para ser más comprobableDado:
podría refactorizarse fácilmente para usar DI, sin el uso de un contenedor de COI, y podría incluso dividirlo en varios pasos:
(potencial) Paso uno: tome las dependencias pero no cambie el código de llamada (UI):
Refactor 2 (o primer refactorizador si implementa el contenedor IOC y cambia el código de llamada inmediatamente):
El paso 2 podría hacerse técnicamente por sí mismo, pero (potencialmente) sería mucho más trabajo, dependiendo de cuántas clases estén actualmente "renovando" la funcionalidad que está buscando para DI.
Considere ir con el paso 1 -> ruta del paso 2 - para el que podría crear pruebas unitarias
Foo
, independientemente deBar
. Mientras que antes del refactorizador del paso 1 no se lograba fácilmente sin usar la implementación real de ambas clases. Hacer el paso 1 -> paso 2 (en lugar del paso 2 inmediatamente) permitiría cambios más pequeños con el tiempo, y ya tendrá el inicio de un arnés de prueba para garantizar que su refactor funcione sin consecuencias.fuente
El concepto es el mismo si está utilizando Java, PHP o incluso C #. Gemma Anible aborda esta pregunta bastante bien en este video de YouTube:
https://www.youtube.com/watch?v=Jccq_Ti8Lck (PHP, ¡lo siento!)
Reemplaza el código no comprobable con "fachada" (a falta de un término mejor) que llame a un código nuevo y comprobable. Luego, gradualmente, puede reemplazar las llamadas más antiguas con los servicios inyectados. He hecho esto en el pasado y funciona bastante bien.
fuente