Inversion of Control se trata principalmente de la gestión de la dependencia y proporciona código comprobable. Desde un enfoque clásico, si una clase tiene una dependencia, la tendencia natural es dar a la clase que tiene la dependencia control directo sobre la gestión de sus dependencias. Esto generalmente significa que la clase que tiene la dependencia 'actualizará' sus dependencias dentro de un constructor o bajo demanda en sus métodos.
Inversion of Control es solo eso ... invierte lo que crea dependencias, externaliza ese proceso y lo inyecta en la clase que tiene la dependencia. Usualmente, la entidad que crea las dependencias es lo que llamamos un contenedor IoC, que es responsable no solo de crear e inyectar dependencias, sino también de administrar sus vidas, determinar su estilo de vida (más sobre esto en un segundo) y también ofrece una variedad de otras capacidades. (Esto se basa en Castle MicroKernel/Windsor, que es mi contenedor de IoC de elección ... está sólidamente escrito, es muy funcional y extensible. Existen otros contenedores de IoC que son más simples si tiene necesidades más simples, como Ninject, Microsoft Unity y Spring.NET.)
Considere que tiene una aplicación interna que se puede usar en un contexto local o en un contexto remoto. Dependiendo de algunos factores detectables, su aplicación puede necesitar cargar implementaciones "locales" de sus servicios, y en otros casos puede necesitar cargar implementaciones "remotas" de sus servicios. Si sigue el enfoque clásico y crea sus dependencias directamente dentro de la clase que tiene esas dependencias, entonces esa clase se verá obligada a romper dos reglas muy importantes sobre el desarrollo de software: Separación de preocupaciones y Responsabilidad individual. Cruza los límites de la preocupación porque su clase ahora está preocupada tanto por su propósito intrínseco, como por la preocupación de determinar qué dependencias debe crear y cómo. La clase ahora también es responsable de muchas cosas, en lugar de una sola, y tiene muchas razones para cambiar: sus cambios de propósito intrínsecos, el proceso de creación para sus cambios de dependencias, la forma en que encuentra cambios de dependencias remotas, qué dependencias pueden necesitar sus dependencias , etc.
Al invertir su gestión de dependencias, puede mejorar la arquitectura de su sistema y mantener SoC y SR (o, posiblemente, lograrlo cuando no pudo debido a dependencias). Como una entidad externa, el contenedor IoC ahora controla cómo se crean e inyectan sus dependencias, también puede obtener capacidades adicionales. El contenedor puede administrar los ciclos de vida de sus dependencias, crearlas y destruirlas de maneras más flexibles que pueden mejorar la eficiencia. También obtienes la capacidad de administrar los estilos de vida de tus objetos. Si tiene un tipo de dependencia que se crea, utiliza y devuelve con mucha frecuencia, pero que tiene poco o ningún estado (por ejemplo, fábricas), puede darles un estilo de vida compartido, que le indicará al contenedor que cree automáticamente un grupo de objetos para ese tipo de dependencia particular. Existen muchos estilos de vida, y un contenedor como Castle Windsor generalmente te dará la posibilidad de crear el tuyo propio.
Los mejores contenedores IoC, como Castle Windsor, también proporcionan una gran capacidad de extensión. Por defecto, Windsor le permite crear instancias de tipos locales. Es posible crear instalaciones que amplíen las capacidades de creación tipo Windsor para crear dinámicamente proxies de servicio web y servidores de servicio WCF sobre la marcha, en tiempo de ejecución, eliminando la necesidad de crearlos manualmente o estáticamente con herramientas como svcutil (esto es algo que hice yo mismo recientemente .) Existen muchas instalaciones para que IoC admita marcos existentes, como NHibernate, ActiveRecord, etc.
Finalmente, IoC impone un estilo de codificación que garantiza el código de la unidad comprobable. Uno de los factores clave para hacer que la unidad de código sea comprobable es la gestión de la dependencia de externalización. Sin la capacidad de proporcionar dependencias alternativas (simulada, tropezada, etc.), probar una sola "unidad" de código de forma aislada es una tarea muy difícil, por lo que las pruebas de integración son el único estilo alternativo de prueba automatizada. Como IoC requiere que sus clases acepten dependencias mediante inyección (por constructor, propiedad o método), cada clase se reduce, si no siempre, a una sola responsabilidad de preocupación separada adecuadamente, y a dependencias totalmente burlables.
IoC = mejor arquitectura, mayor cohesión, separación mejorada de preocupaciones, clases que son más fáciles de reducir a una sola responsabilidad, dependencias fácilmente configurables e intercambiables (a menudo sin requerir una recompilación de su código), estilos de vida de dependencia flexibles y vida gestión del tiempo y código de prueba de la unidad. IoC es una especie de estilo de vida ... una filosofía, un enfoque para resolver problemas comunes y conocer las mejores prácticas críticas como SoC y SR.
Incluso (o mejor dicho, particularmente) con cientos de implementaciones diferentes de una sola interfaz, IoC tiene mucho que ofrecer. Puede tomar un tiempo para que su cabeza quede totalmente envuelta, pero una vez que comprenda completamente qué es IoC y qué puede hacer por usted, nunca querrá hacer las cosas de otra manera (excepto tal vez el desarrollo de sistemas integrados ...)
A propósito no mencioné las pruebas, porque él mencionó que ya está usando DI. Eso es todo lo que necesitas para burlarte y probar. DI es una estrategia; Los contenedores de IoC facilitan esa estrategia y la hacen más fácil de implementar (una reducción en su "código de macarrones") –
Esto probablemente debería haber sido hecho como un comentario en la publicación de Jeremy ... –