design-patterns - objects - ioc informatica
¿Cuándo no usar IoC y DI? (8)
Acerca de su pregunta acerca de tener solo una implementación de interfaz. Cuando usa IoC, sigue siendo útil usar una interfaz. Será mucho más fácil crear pruebas unitarias reales (eso no depende de que la implementación de la interfaz funcione correctamente) utilizando simulaciones para estas interfaces. El núcleo del uso de IoC es hacer que el código sea más fácil de probar. Por lo tanto, no use IoC si no desea realizar la prueba, o si ya tiene un mejor plan para realizar pruebas sin este.
En mi humilde opinión, el aumento de IoC en la complejidad viene pagado por tener un código más fácil de probar y menos acoplado. Es más fácil aislar los problemas y hacer cambios futuros. También puedes controlar mejor su comportamiento.
Puedo ver cuándo no usar un contenedor IoC (ya que da como resultado una sobrecarga de configuración). Esto sucedería en proyectos pequeños, donde puede hacerlo manualmente, en lugar de usar un contenedor. Pero no puedo ver mucha pérdida por usar DI, a menos que no planees probar tu código ...
Veo muchos artículos que dicen lo genial que son IoC y DI, y ninguno acerca de por qué no es tan bueno porque puede hacer que el código sea más complejo. También veo que IoC no debería estar en la parte central de tu código, sino más bien para bibliotecas y complementos. Los artículos usualmente son una pequeña referencia de cómo los dos patrones pueden hacer que el código sea más complicado pero no mucho en los detalles de eso. Esa es mi pregunta: ¿dónde específicamente no deberías usar estos patrones?
Este es un buen hilo: ¿Qué es la Inversión de Control? . Si miras más abajo, hay una publicación sobre el corrector ortográfico y otra publicación sobre cómo IoC probablemente no sea un buen uso si solo se trata de un corrector ortográfico. Como regla general, si IoC no se usa, ¿alguna vez tengo una sola clase concreta para la interfaz? Es decir, tengo IMyClass. Y luego solo tenemos el MyClassA concreto que implementa IMyClass. ¿Por qué querría IoC allí?
Si tuviera MyClassA, MyClassB y MyClassC, cada uno implemente IMyClass, ¿son probablemente buenos candidatos para IoC?
Del mismo hilo, ¿alguien sabe lo que significa esta publicación?
- Inversión de Control = Matrimonio
- COI Contenedor = Esposa
Desde el Proyecto del Castillo :
¿Por qué no debería usarlo?
No debe usar un contenedor de Inversión de control si no está familiarizado con los conceptos y si no se da cuenta de los problemas que intenta resolver.
Además, dependiendo del tamaño y la complejidad del proyecto, un contenedor IoC podría ser excesivo. Prefiero usarlo en proyectos medianos a grandes.
Este artículo aborda su pregunta "¿dónde específicamente no debería usar estos patrones?" y da ejemplos detallados con respecto a su comentario de que "los dos patrones ([IoC y DI]) pueden hacer que el código sea más complicado":
http://java.dzone.com/articles/beyond-injection-concerns-ioc .
Para resumir dos de los puntos de este artículo:
- No debe usar IoC / DI donde la encapsulación es importante.
- No debe usar IoC / DI donde no pueda demostrar ejemplos concretos de cómo la complejidad agregada a través del uso de IoC / DI se ve sopesada por los beneficios de usar IoC / DI.
Inversión de Control = Matrimonio
COI Contenedor = Esposa
El matrimonio es la definición de un patrón conocido: la esposa es la implementación de ese patrón ;-)
Bernardo.
IoC / DI no son tecnologías, son paradigmas. Su pregunta es similar a preguntar "¿Cuándo no debería usar programación orientada a objetos?" Es una decisión que es más grande que las unidades individuales de su base de código.
Para responder a su pregunta específica, si tiene pocas clases suficientes donde puede construir razonablemente gráficos de objetos a mano, y no está repitiendo las mismas instancias gráficas de objetos varias veces, es posible que no necesite un contenedor IoC.
Las quejas sobre IoC son fáciles de entender: IoC convierte algo simple en algo complicado. Supongamos que quiere hacer algo con cada elemento de una lista (en pseudocódigo):
for each i in list:
do_something(i)
IoC, en esencia, está transfiriendo la responsabilidad de la iteración de bucle a otra persona. Por lo tanto, terminamos con algo más como esto:
ioc = new IocContainer()
ioc.register_callback(do_something)
ioc.go()
Tenga en cuenta que incluso en esta forma simple, el código es más largo que el original ... y eso sin contar la implementación de IocContainer.
Entonces, en su forma más exclusiva, el IocContainer puede inicializarse estáticamente o mediante una función Main () estática o en otro lugar oculto, y las funciones register_callback () se llaman automáticamente basándose en algún otro código que itera a través de un archivo XML que enumera todo sus funciones do_something () y (a veces) incluso el contenido de las listas para iterar.
¡Sí, el archivo XML ha hecho que tu software sea más configurable! ¿Derecha? ¡Puede cambiar qué cosas se hacen en su lista simplemente cambiando un archivo de texto simple!
Excepto, irónicamente, su código fuente ahora es más largo y más difícil de entender, depende de todo tipo de bibliotecas nuevas, posiblemente defectuosas (incluido el IocContainer y un analizador XML), y en realidad lo ha hecho más difícil de mantener: código XML es más difícil de comprender y editar que el bucle de código fuente simple original (sin importar en qué idioma esté escrito el bucle). También tiene menos control sobre exactamente cómo desea realizar la iteración (ordenada o sin clasificar? ¿Primero o primero?) Ya que IocContainer le está quitando esa responsabilidad.
Para cosas como complementos, puede tener sentido usar IoC, ya que es lógico que la aplicación principal tenga el control del proceso de ejecución y simplemente pida ayuda al plugin aquí y allá. Esto se llama "proporcionar ganchos" y ha existido mucho más tiempo que la terminología de IoC.
Para cosas como las pruebas unitarias (que es donde generalmente lo he visto dar vueltas), IoC por lo general resulta poco útil, porque tus pruebas deben ser capaces de simular una amplia variedad de situaciones extrañas, y el IoC simplemente entra constantemente en el forma de esto.
La suposición fundamental de IoC es que la carga de datos y el bucle es de alguna manera difícil y necesita ser eliminada; esta suposición simplemente no es cierta, porque nunca fue más que un par de líneas de todos modos (o podría moverla a una función separada), e incluso si guardó código, reduce su flexibilidad.
Supongo que diría que la respuesta simple solo usa IoC en los objetos que deseas probar unitario.
Si esto parece frívolo, lo siento, es por frustración en el código escrito, literalmente, SIN considerar las pruebas unitarias. Realmente no entiendo por qué hay complejidad añadida, si necesitaba saber el tipo de objeto real para asegurarse de que siempre puedo imprimir la clase en tiempo de ejecución.
Usar o no un contenedor de IoC no es una decisión que tomar a nivel de clases individuales: en cualquier proyecto, tendrá tipos creados y no creados por el contenedor.
El compromiso de la complejidad es esto:
- Para una pequeña cantidad de componentes, un contenedor IoC agrega algo de sobrecarga
- A medida que aumenta el número de componentes en una aplicación:
- Sin un contenedor IoC, agregar nuevos componentes o refactorizar tiende a ser cada vez más difícil
- Con un contenedor de IoC, agregar componentes nuevos o refactorizar permanece igual: solo debe preocuparse por las dependencias inmediatas del componente que está agregando o cambiando.
Si alguna vez ha experimentado el fenómeno de que incluso una base de código bien diseñada y mantenida se vuelve ingobernable con el tamaño, ha experimentado el problema que los contenedores de IoC resuelven.