He estado usando Dependency Injection (DI) por un tiempo, inyectando en un constructor, propiedad o método. Nunca sentí la necesidad de usar un contenedor de Inversión de Control (IoC). Sin embargo, cuanto más leo, más presión siento de la comunidad para usar un contenedor de IoC.
Jugué con contenedores .NET como StructureMap , NInject , Unity y Funq . Todavía no veo cómo un contenedor de IoC beneficiará / mejorará mi código.
También tengo miedo de comenzar a usar un contenedor en el trabajo porque muchos de mis compañeros de trabajo verán un código que no entienden. Muchos de ellos pueden ser reacios a aprender nuevas tecnologías.
Por favor, convencerme de que necesito usar un contenedor de IoC. Usaré estos argumentos cuando hable con mis colegas desarrolladores en el trabajo.
Respuestas:
Wow, no puedo creer que Joel esté a favor de esto:
Más allá de esto:
Muchas personas no se dan cuenta de que su cadena de dependencias puede anidarse, y rápidamente se vuelve difícil de manejar para conectarlas manualmente. Incluso con las fábricas, la duplicación de su código simplemente no vale la pena.
Los contenedores de IoC pueden ser complejos, sí. Pero para este caso simple, he demostrado que es increíblemente fácil.
Bien, justifiquemos esto aún más. Supongamos que tiene algunas entidades u objetos de modelo que desea vincular a una IU inteligente. Esta interfaz de usuario inteligente (la llamaremos Shindows Morms) quiere que implemente INotifyPropertyChanged para que pueda hacer un seguimiento de cambios y actualizar la interfaz de usuario en consecuencia.
"OK, eso no suena tan difícil", así que empiezas a escribir.
Empiezas con esto:
..y terminar con esto :
Es un código de plomería repugnante, y mantengo que si está escribiendo un código así a mano, le está robando a su cliente . Hay una forma mejor y más inteligente de trabajar.
¿Alguna vez escuchó ese término, trabaja de manera más inteligente, no más duro?
Bueno, imagina que un tipo inteligente de tu equipo vino y dijo: "Aquí hay una manera más fácil"
Si hace que sus propiedades sean virtuales (tranquilícese, no es un gran problema), entonces podemos incorporar ese comportamiento de propiedad automáticamente. (Esto se llama AOP, pero no se preocupe por el nombre, concéntrese en lo que va a hacer por usted)
Dependiendo de la herramienta de IoC que esté usando, podría hacer algo como esto:
¡Maricón! Todo ese manual INotifyPropertyChanged BS ahora se genera automáticamente para usted, en cada configurador de propiedad virtual del objeto en cuestión.
¿Es esto magia? SI ! Si puede confiar en el hecho de que este código hace su trabajo, puede omitir con seguridad toda esa propiedad que envuelve mumbo-jumbo. Tienes problemas comerciales que resolver.
Algunos otros usos interesantes de una herramienta IoC para hacer AOP:
fuente
Estoy contigo, Vadim. Los contenedores IoC toman un concepto simple, elegante y útil, y lo convierten en algo que debe estudiar durante dos días con un manual de 200 páginas.
Personalmente estoy perplejo de cómo la comunidad de IoC tomó un artículo hermoso y elegante de Martin Fowler y lo convirtió en un conjunto de marcos complejos, típicamente con manuales de 200-300 páginas.
Intento no juzgar (¡JAJA!), Pero creo que las personas que usan contenedores de IoC son (A) muy inteligentes y (B) carecen de empatía por las personas que no son tan inteligentes como ellos. Todo tiene mucho sentido para ellos, por lo que tienen problemas para comprender que muchos programadores comunes encontrarán los conceptos confusos. Es la maldición del conocimiento . Las personas que entienden los contenedores de IoC tienen problemas para creer que hay personas que no lo entienden.
El beneficio más valioso de usar un contenedor IoC es que puede tener un interruptor de configuración en un lugar que le permite cambiar entre, por ejemplo, el modo de prueba y el modo de producción. Por ejemplo, suponga que tiene dos versiones de sus clases de acceso a la base de datos ... una versión que se registró de forma agresiva e hizo mucha validación, que utilizó durante el desarrollo, y otra versión sin registro o validación que fue extremadamente rápida para la producción. Es bueno poder cambiar entre ellos en un solo lugar. Por otro lado, este es un problema bastante trivial que se maneja fácilmente de una manera más simple sin la complejidad de los contenedores IoC.
Creo que si usa contenedores IoC, su código se vuelve, francamente, mucho más difícil de leer. El número de lugares que tiene que mirar para descubrir qué está tratando de hacer el código aumenta en al menos uno. Y en algún lugar del cielo un ángel clama.
fuente
Presumiblemente, nadie te está obligando a usar un marco contenedor DI. Ya está utilizando DI para desacoplar sus clases y mejorar la capacidad de prueba, por lo que obtiene muchos de los beneficios. En resumen, estás favoreciendo la simplicidad, que generalmente es algo bueno.
Si su sistema alcanza un nivel de complejidad en el que la DI manual se convierte en una tarea (es decir, aumenta el mantenimiento), compárelo con la curva de aprendizaje en equipo de un marco de contenedor DI.
Si necesita más control sobre la gestión de la vida útil de la dependencia (es decir, si siente la necesidad de implementar el patrón Singleton), observe los contenedores DI.
Si usa un contenedor DI, use solo las funciones que necesita. Omita el archivo de configuración XML y configúrelo en código si es suficiente. Se adhieren a la inyección del constructor. Los conceptos básicos de Unity o StructureMap se pueden resumir en un par de páginas.
Hay una gran publicación de blog de Mark Seemann sobre esto: cuándo usar un contenedor DI
fuente
En mi opinión, el beneficio número uno de un IoC es la capacidad de centralizar la configuración de sus dependencias.
Si actualmente está usando la inyección de dependencia, su código podría verse así
Si utilizó una clase de IoC estática, a diferencia de, en mi humilde opinión, los archivos de configuración más confusos, podría tener algo como esto:
Entonces, su clase de IoC estática se vería así, estoy usando Unity aquí.
fuente
Los contenedores de IoC también son buenos para cargar dependencias de clase profundamente anidadas. Por ejemplo, si tenía el siguiente código usando Inyección de dependencia.
Si tenía todas estas dependencias cargadas en un contenedor de IoC, podría resolver el CustomerService y todas las dependencias secundarias se resolverán automáticamente.
Por ejemplo:
fuente
Soy fanático de la programación declarativa (mira cuántas preguntas SQL respondo), pero los contenedores de IoC que he visto parecen demasiado arcanos por su propio bien.
... o tal vez los desarrolladores de contenedores IoC no pueden escribir documentación clara.
... o ambos son verdaderos en un grado u otro.
No creo que el concepto de un contenedor IoC sea malo. Pero la implementación debe ser lo suficientemente potente (es decir, flexible) como para ser útil en una amplia variedad de aplicaciones, pero simple y fácil de entender.
Probablemente sean seis de una y media docena de la otra. Una aplicación real (no un juguete o una demostración) está destinada a ser compleja, y representa muchos casos de esquina y excepciones a las reglas. O encapsula esa complejidad en código imperativo, o bien en código declarativo. Pero tienes que representarlo en alguna parte.
fuente
El uso de un contenedor se trata principalmente de cambiar de un estilo imperativo / programado de inicialización y configuración a uno declarativo . Esto puede tener algunos efectos beneficiosos diferentes:
Por supuesto, puede haber dificultades:
fuente
Me parece que ya construyó su propio contenedor de IoC (utilizando los diversos patrones que describió Martin Fowler) y se pregunta por qué la implementación de otra persona es mejor que la suya.
Entonces, tienes un montón de código que ya funciona. Y se preguntan por qué querrían reemplazarlo con la implementación de otra persona.
Ventajas para considerar un contenedor de IoC de terceros
Contras
Por lo tanto, compara tus ventajas con tus desventajas y toma una decisión.
fuente
Creo que la mayor parte del valor de una IoC se obtiene mediante el uso de DI. Como ya lo está haciendo, el resto del beneficio es incremental.
El valor que obtenga dependerá del tipo de aplicación en la que esté trabajando:
Para múltiples inquilinos, el contenedor de IoC puede ocuparse de parte del código de infraestructura para cargar diferentes recursos del cliente. Cuando necesite un componente que sea específico del cliente, use un selector personalizado para manejar la lógica y no se preocupe por su código de cliente. Ciertamente puede construir esto usted mismo, pero aquí hay un ejemplo de cómo un IoC puede ayudar.
Con muchos puntos de extensibilidad, IoC se puede usar para cargar componentes desde la configuración. Es algo común de construir, pero el contenedor proporciona herramientas.
Si desea utilizar AOP para algunos problemas transversales, IoC proporciona enlaces para interceptar invocaciones de métodos. Esto se hace con menos frecuencia ad-hoc en proyectos, pero el IoC lo hace más fácil.
He escrito una funcionalidad como esta antes, pero si necesito alguna de estas características ahora, preferiría usar una herramienta prefabricada y probada si se ajusta a mi arquitectura.
Como lo mencionaron otros, también puede configurar centralmente qué clases desea usar. Aunque esto puede ser algo bueno, tiene un costo de dirección errónea y complicaciones. Los componentes centrales para la mayoría de las aplicaciones no se reemplazan mucho, por lo que la compensación es un poco más difícil de hacer.
Utilizo un contenedor de IoC y aprecio la funcionalidad, pero tengo que admitir que he notado la compensación: mi código se vuelve más claro a nivel de clase y menos claro a nivel de aplicación (es decir, visualizando el flujo de control).
fuente
Soy un adicto al COI en recuperación. Me resulta difícil justificar el uso de COI para la DI en la mayoría de los casos en estos días. Los contenedores IOC sacrifican la verificación del tiempo de compilación y supuestamente a cambio le brindan una configuración "fácil", una gestión de por vida compleja y el descubrimiento sobre la marcha de dependencias en tiempo de ejecución. Encuentro que la pérdida de tiempo de compilación y las excepciones y el tiempo de ejecución resultantes no valen la pena en la gran mayoría de los casos. En aplicaciones de grandes empresas, pueden hacer que sea muy difícil seguir lo que está sucediendo.
No compro el argumento de centralización porque también puede centralizar la configuración estática muy fácilmente al usar una fábrica abstracta para su aplicación y diferir religiosamente la creación de objetos a la fábrica abstracta, es decir, hacer una DI adecuada.
¿Por qué no hacer DI sin magia estática así:
La configuración de su contenedor es su implementación de fábrica abstracta, sus registros son implementaciones de miembros abstractos. Si necesita una nueva dependencia singleton, simplemente agregue otra propiedad abstracta a la fábrica abstracta. Si necesita una dependencia transitoria, simplemente agregue otro método e inyéctelo como Func <>.
Ventajas:
Recomiendo a los escépticos que prueben el próximo proyecto de campo verde y honestamente pregúntense en qué punto necesita el contenedor. Es fácil tener en cuenta un contenedor IOC más adelante, ya que solo está reemplazando una implementación de fábrica con un módulo de configuración de contenedor IOC.
fuente
El mayor beneficio de usar contenedores IoC para mí (personalmente, uso Ninject) ha sido eliminar la transferencia de configuraciones y otros tipos de objetos de estado global.
No programo para la web, la mía es una aplicación de consola y en muchos lugares en lo profundo del árbol de objetos necesito tener acceso a la configuración o metadatos especificados por el usuario que se crean en una rama completamente separada del árbol de objetos. Con IoC, simplemente le digo a Ninject que trate las configuraciones como un singleton (porque siempre hay solo una instancia de ellas), solicite las configuraciones o el diccionario en el constructor y listo ... ¡aparecen mágicamente cuando los necesito!
Sin usar un contenedor de IoC, tendría que pasar la configuración y / o metadatos a través de 2, 3, ..., n objetos antes de que el objeto lo necesitara.
Hay muchos otros beneficios para los contenedores DI / IoC ya que otras personas han detallado aquí y pasar de la idea de crear objetos a solicitar objetos puede ser alucinante, pero usar DI fue muy útil para mí y para mi equipo, así que tal vez puedan agregarlo a tu arsenal!
fuente
Los marcos de IoC son excelentes si quieres ...
... tirar la seguridad de tipo. Muchos (¿todos?) Marcos de IoC te obligan a ejecutar el código si quieres estar seguro de que todo está conectado correctamente. "¡Hey! ¡Espero tener todo configurado para que mis inicializaciones de estas 100 clases no fallen en la producción, arrojando excepciones de puntero nulo!"
... ensucia tu código con globales (los marcos de trabajo de IoC son todos sobre el cambio de estados globales).
... escriba código malo con dependencias poco claras que es difícil de refactorizar ya que nunca sabrá qué depende de qué.
El problema con IoC es que las personas que los usan solían escribir código como este
lo cual obviamente es defectuoso ya que la dependencia entre Foo y Bar está conectada. Luego se dieron cuenta de que sería mejor escribir código como
lo cual también es defectuoso, pero es menos obvio. En Haskell el tipo de
Foo()
seríaIO Foo
pero realmente no desea la parte-IO
y debería ser una señal de advertencia de que algo está mal con su diseño si lo tiene.Para deshacerse de él (la parte IO), obtenga todas las ventajas de los marcos IoC y ninguno de sus inconvenientes podría utilizar una fábrica abstracta.
La solución correcta sería algo así como
o tal vez
e inyectar (pero no lo llamaría inyectar) Bar.
Además: vea este video con Erik Meijer (inventor de LINQ) donde dice que DI es para personas que no saben matemáticas (y no podría estar más de acuerdo): http://www.youtube.com/watch?v = 8Mttjyf-8P4
A diferencia del Sr. Spolsky, no creo que las personas que usan IoC-frameworks sean muy inteligentes, simplemente creo que no saben matemáticas.
fuente
IBar
lo es, de hecho lo esIO IBar
). Y sí, en el ejemplo de Haskell No puedo obtener una referencia nula.Descubrí que la implementación correcta de la Inyección de dependencias tiende a obligar a los programadores a usar una variedad de otras prácticas de programación que ayudan a mejorar la capacidad de prueba, la flexibilidad, la capacidad de mantenimiento y la escalabilidad del código: prácticas como el Principio de responsabilidad única, Separaciones de preocupaciones y codificación contra las API. Parece que me veo obligado a escribir más clases y métodos modulares de tamaño de bocado, lo que hace que el código sea más fácil de leer, ya que puede tomarse en trozos de tamaño de bocado.
Pero también tiende a crear árboles de dependencia bastante grandes, que se manejan mucho más fácilmente a través de un marco (especialmente si usa convenciones) que a mano. Hoy quería probar algo realmente rápido en LINQPad, y pensé que sería demasiado molesto crear un núcleo y cargarlo en mis módulos, y terminé escribiendo esto a mano:
En retrospectiva, hubiera sido más rápido usar el marco de IoC, ya que los módulos definen prácticamente todo esto por convención.
Después de pasar algún tiempo estudiando las respuestas y los comentarios sobre esta pregunta, estoy convencido de que las personas que se oponen al uso de un contenedor de IoC no están practicando una verdadera inyección de dependencia. Los ejemplos que he visto son de prácticas que comúnmente se confunden con la inyección de dependencia. Algunas personas se quejan de la dificultad de "leer" el código. Si se hace correctamente, la gran mayoría de su código debe ser idéntico cuando usa DI a mano como cuando usa un contenedor de IoC. La diferencia debería residir completamente en unos pocos "puntos de lanzamiento" dentro de la aplicación.
En otras palabras, si no le gustan los contenedores de IoC, probablemente no esté haciendo la inyección de dependencia de la forma en que se supone que debe hacerse.
Otro punto: la inyección de dependencia realmente no se puede hacer a mano si usa la reflexión en cualquier lugar. Si bien odio lo que hace la reflexión al código de navegación, debe reconocer que hay ciertas áreas donde realmente no se puede evitar. ASP.NET MVC, por ejemplo, intenta crear una instancia del controlador mediante la reflexión en cada solicitud. Para hacer la inyección de dependencia a mano, tendría que hacer que cada controlador sea una "raíz de contexto", así:
Ahora compare esto con permitir que un marco DI lo haga por usted:
Usando un marco DI, tenga en cuenta que:
ISimpleWorkflowInstanceMerger
, puedo probar que se usa de la manera que preveo, sin la necesidad de una conexión a la base de datos ni nada.ISimpleWorkflowInstanceMerger
interfaz. Esto me permite dividir la aplicación en módulos separados y mantener una verdadera arquitectura de varios niveles, lo que a su vez hace que las cosas sean mucho más flexibles.Una aplicación web típica tendrá bastantes controladores. Todo el dolor de hacer DI manualmente en cada controlador realmente se acumulará a medida que su aplicación crezca. Si tiene una aplicación con solo una raíz de contexto, que nunca intenta instanciar un servicio por reflexión, entonces este no es un problema tan grande. Sin embargo, cualquier aplicación que use Inyección de dependencias será extremadamente costosa de administrar una vez que alcance un cierto tamaño, a menos que use un marco de algún tipo para administrar el gráfico de dependencia.
fuente
Cada vez que usa la palabra clave "nuevo", está creando una dependencia de clase concreta y una pequeña campana de alarma debería sonar en su cabeza. Se vuelve más difícil probar este objeto de forma aislada. La solución es programar en las interfaces e inyectar la dependencia para que el objeto pueda ser probado con cualquier cosa que implemente esa interfaz (por ejemplo, simulacros).
El problema es que tienes que construir objetos en alguna parte. Un patrón de Fábrica es una forma de cambiar el acoplamiento de sus POXO (Objetos simples "inserte su lenguaje OO aquí"). Si usted y sus compañeros de trabajo están escribiendo código como este, entonces un contenedor de IoC es la próxima "Mejora incremental" que puede hacer en su base de código. Cambiará todo ese desagradable código de fábrica de tus objetos limpios y lógica empresarial. Lo conseguirán y lo amarán. Diablos, dale una charla a la compañía sobre por qué lo amas y entusiasma a todos.
Si tus compañeros de trabajo aún no están haciendo DI, entonces te sugiero que te concentres en eso primero. Corre la voz sobre cómo escribir código limpio que sea fácilmente comprobable. El código DI limpio es la parte difícil, una vez que esté allí, cambiar la lógica de cableado del objeto de las clases Factory a un contenedor IoC debería ser relativamente trivial.
fuente
Debido a que todas las dependencias son claramente visibles, promueve la creación de componentes que están acoplados libremente y al mismo tiempo son fácilmente accesibles y reutilizables en toda la aplicación.
fuente
No necesita un contenedor de IoC.
Pero si sigue rigurosamente un patrón DI, encontrará que tener uno eliminará una tonelada de código redundante y aburrido.
Ese es a menudo el mejor momento para usar una biblioteca / marco, de todos modos, cuando entiendes lo que está haciendo y puedes hacerlo sin la biblioteca.
fuente
Simplemente estoy en el proceso de extraer el código DI interno y reemplazarlo con un COI. Probablemente eliminé más de 200 líneas de código y las reemplacé por unas 10. Sí, tuve que aprender un poco sobre cómo usar el contenedor (Winsor), pero soy un ingeniero que trabaja en tecnologías de Internet en el Siglo XXI, así que estoy acostumbrado a eso. Probablemente pasé unos 20 minutos mirando el cómo. Valió la pena mi tiempo.
fuente
A medida que continúa desacoplando sus clases e invirtiendo sus dependencias, las clases siguen siendo pequeñas y el "gráfico de dependencia" continúa creciendo en tamaño. (Esto no está mal.) El uso de las características básicas de un contenedor de IoC hace que el cableado de todos estos objetos sea trivial, pero hacerlo manualmente puede ser muy pesado. Por ejemplo, ¿qué pasa si quiero crear una nueva instancia de "Foo" pero necesita una "Barra"? Y una "Barra" necesita una "A", "B" y "C". Y cada uno de ellos necesita otras 3 cosas, etc., etc. (sí, no puedo encontrar buenos nombres falsos :)).
El uso de un contenedor de IoC para construir su gráfico de objetos por usted reduce la complejidad de una tonelada y lo lleva a una configuración única. Simplemente digo "créeme un 'Foo'" y se da cuenta de lo que se necesita para construir uno.
Algunas personas usan los contenedores IoC para mucha más infraestructura, lo cual está bien para escenarios avanzados, pero en esos casos estoy de acuerdo en que puede ofuscar y dificultar la lectura del código y la depuración de nuevos desarrolladores.
fuente
Ídem sobre la unidad. Si te haces demasiado grande, puedes escuchar el crujido en las vigas.
Nunca me sorprende cuando la gente comienza a hablar sobre cuán limpio se ve el código IoC, son los mismos tipos de personas que en un momento hablaron sobre cómo las plantillas en C ++ eran la forma elegante de regresar en los años 90, pero hoy en día las criticarán como arcanas . Bah!
fuente
En el mundo .NET, AOP no es demasiado popular, por lo que para DI un marco es su única opción real, ya sea que escriba uno usted mismo o use otro marco.
Si usó AOP, puede inyectar cuando compila su aplicación, que es más común en Java.
Hay muchos beneficios para DI, como el acoplamiento reducido para que las pruebas unitarias sean más fáciles, pero ¿cómo lo implementará? ¿Quieres usar la reflexión para hacerlo tú mismo?
fuente
Entonces, han pasado casi 3 años, ¿eh?
El 50% de los que comentaron a favor de los marcos de trabajo de IoC no entienden la diferencia entre IoC y IoC Frameworks. Dudo que sepan que puedes escribir código sin ser implementado en un servidor de aplicaciones
Si tomamos el marco Java Spring más popular, es la configuración de IoC movida de XMl al código y ahora se ve así
`@Configuration public class AppConfig {
} `Y necesitamos un marco para hacer esto ¿por qué exactamente?
fuente
Honestamente, no creo que haya muchos casos en los que se necesiten contenedores IoC, y la mayoría de las veces, solo agregan complejidad innecesaria.
Si lo está utilizando solo para simplificar la construcción de un objeto, tendría que preguntar, ¿está creando instancias de este objeto en más de una ubicación? ¿Un singleton no satisfaría sus necesidades? ¿Estás cambiando la configuración en tiempo de ejecución? (Cambio de tipos de fuente de datos, etc.).
En caso afirmativo, es posible que necesite un contenedor de IoC. Si no es así, simplemente está alejando la inicialización de donde el desarrollador puede verla fácilmente.
¿Quién dijo que una interfaz es mejor que la herencia de todos modos? Digamos que estás probando un servicio. ¿Por qué no usar el constructor DI y crear simulacros de las dependencias usando la herencia? La mayoría de los servicios que uso solo tienen algunas dependencias. Hacer pruebas unitarias de esta manera evita mantener un montón de interfaces inútiles y significa que no tiene que usar Resharper para encontrar rápidamente la declaración de un método.
Creo que para la mayoría de las implementaciones, decir que los Contenedores de IoC eliminan el código innecesario es un mito.
Primero, hay que configurar el contenedor en primer lugar. Entonces todavía tiene que definir cada objeto que necesita inicializarse. Por lo tanto, no guarda el código en la inicialización, lo mueve (a menos que su objeto se use más de una vez. ¿Es mejor como Singleton?). Luego, para cada objeto que haya inicializado de esta manera, debe crear y mantener una interfaz.
¿Alguno tiene alguna idea sobre esto?
fuente
ShippingCostCalculator
oProductUIPresentation
, o cualquier otra estrategia / aplicación, dentro de exactamente la misma base de código , mediante la implementación de un solo archivo XML modificado.Necesitaría un contenedor de IoC si necesitara centralizar la configuración de sus dependencias para que puedan intercambiarse fácilmente en masa. Esto tiene más sentido en TDD, donde se intercambian muchas dependencias, pero donde hay poca interdependencia entre las dependencias. Esto se hace a costa de ofuscar el flujo de control de la construcción de objetos hasta cierto punto, por lo que es importante tener una configuración bien organizada y razonablemente documentada. También es bueno tener una razón para hacer esto, de lo contrario, es una mera abstracción chapada en oro . Lo he visto tan mal que fue arrastrado a ser el equivalente a una declaración goto para constructores.
fuente
Aquí es por qué. El proyecto se llama IOC-with-Ninject. Puede descargarlo y ejecutarlo con Visual Studio. Este ejemplo usa Ninject, pero TODAS las declaraciones 'nuevas' están en una ubicación y puede cambiar por completo la forma en que se ejecuta su aplicación cambiando el módulo de enlace que debe usar. El ejemplo está configurado para que pueda vincularse a una versión simulada de los servicios o la versión real. En proyectos pequeños que pueden no importar, pero en proyectos grandes es un gran problema.
Para ser claros, ventajas como las veo: 1) TODAS las declaraciones nuevas en una ubicación en la raíz del código. 2) Totalmente re-factorizar código con un cambio. 3) Puntos extra por 'factor genial' porque es ... bueno: genial. :pags
fuente
Trataré de encontrar por qué mi COI podría no ser bueno desde mi perspectiva.
Como con todo lo demás, el contenedor IOC (o como lo diría Einstein I = OC ^ 2) es un concepto que debe decidir por sí mismo si lo necesita o no en su código. La reciente protesta de la moda sobre el COI es solo eso, la moda. No caigas en la moda, eso es lo primero. Hay miles de conceptos que podrías implementar en tu código. En primer lugar, estoy usando la inyección de dependencia desde que comencé a programar y aprendí el término cuando se popularizó con ese nombre. El control de la dependencia es un tema muy antiguo y se abordó hasta ahora de billones de maneras, dependiendo de lo que se estaba desacoplando de qué. Desacoplar todo de todo es una tontería. El problema con el contenedor IOC es que intenta ser tan útil como Entity Framework o NHibernate. Si bien escribir un mapeador relacional de objetos es simplemente obligatorio tan pronto como tenga que acoplar cualquier base de datos con su sistema, el contenedor IOC no siempre es necesario. Entonces, cuando el contenedor IOC es útil:
1: No es tan frecuente que tenga tantas dependencias en su código, o que las conozca al principio del diseño. El pensamiento abstracto es útil cuando el pensamiento abstracto es debido.
2: acoplar su código con código de terceros es un problema enorme. Estaba trabajando con código que tiene más de 10 años y que seguía en ese momento conceptos sofisticados y avanzados ATL, COM, COM + y así sucesivamente. No hay nada que pueda hacer con ese código ahora. Lo que estoy diciendo es que un concepto avanzado ofrece una ventaja aparente, sin embargo, esto se cancela a largo plazo con la ventaja obsoleta en sí. Simplemente lo había hecho todo más caro.
3: El desarrollo de software es lo suficientemente difícil. Puede extenderlo a niveles irreconocibles si permite que algún concepto avanzado se recorte en su código. Hay un problema con IOC2. Aunque desacopla las dependencias, también desacopla el flujo lógico. Imagine que ha encontrado un error y necesita establecer un descanso para examinar la situación. IOC2, como cualquier otro concepto avanzado, lo está haciendo más difícil. Arreglar un error dentro de un concepto es más difícil que arreglar un error en un código simple, porque cuando arreglas un error, un concepto debe ser obedecido nuevamente. (Solo para darle un ejemplo, C ++ .NET cambia constantemente la sintaxis tanto que necesita pensar mucho antes de refactorizar alguna versión anterior de .NET). Entonces, ¿cuál es el problema con IOC? El problema está en resolver dependencias. La lógica para resolver está comúnmente oculta en el propio IOC2, escrito tal vez de manera poco común que necesita aprender y mantener ¿Su producto de terceros estará allí en 5 años? Microsoft no lo era.
El síndrome "Sabemos cómo" está escrito por todas partes con respecto a IOC2. Esto es similar a las pruebas de automatización. Término elegante y solución perfecta a primera vista, simplemente pone todas sus pruebas a ejecutar durante la noche y ve los resultados por la mañana. Es realmente doloroso explicar compañía tras compañía lo que realmente significan las pruebas automatizadas. Las pruebas automatizadas definitivamente no son una forma rápida de reducir la cantidad de errores que puede introducir de la noche a la mañana para aumentar la calidad de su producto. Pero, la moda está haciendo que esa noción sea molestamente dominante. IOC2 sufre el mismo síndrome. Se cree que necesita implementarlo para que su software sea bueno. Cada entrevista reciente Me preguntaron si estoy implementando IOC2 y automatización. Esa es una señal de moda: la compañía tenía una parte del código escrito en MFC que no abandonarán.
Necesita aprender IOC2 como cualquier otro concepto en software. La decisión de si es necesario utilizar IOC2 es del equipo y de la empresa. Sin embargo, al menos TODOS los argumentos anteriores deben mencionarse antes de tomar la decisión. Solo si ve que el lado positivo supera el lado negativo, puede tomar una decisión positiva.
No hay nada malo con IOC2, excepto que solo resuelve los problemas que resuelve e introduce los problemas que presenta. Nada más. Sin embargo, ir en contra de la moda es muy difícil, tienen la boca sudorosa, los seguidores de todo. Es extraño cómo ninguno de ellos está allí cuando el problema con su fantasía se hace evidente. Se han defendido muchos conceptos en la industria del software porque generan ganancias, se escriben libros, se realizan conferencias y se fabrican nuevos productos. Eso es moda, generalmente de corta duración. Tan pronto como las personas encuentran algo más, lo abandonan por completo. IOC2 es útil pero muestra los mismos signos que muchos otros conceptos desaparecidos que he visto. No sé si sobrevivirá. No hay una regla para eso. Piensas que si es útil, sobrevivirá. No, no va de esa manera. Una gran empresa rica es suficiente y el concepto puede morir en pocas semanas. Ya veremos. NHibernate sobrevivió, EF quedó en segundo lugar. Quizás IOC2 también sobrevivirá. No olvide que la mayoría de los conceptos en el desarrollo de software no tienen nada de especial, son muy lógicos, simples y obvios, y a veces es más difícil recordar la convención de nomenclatura actual que comprender el concepto en sí. ¿El conocimiento de IOC2 hace que un desarrollador sea un mejor desarrollador? No, porque si un desarrollador no pudo idear un concepto similar al IOC2, entonces le será difícil entender qué problema está resolviendo IOC2, usarlo parecerá artificial y puede comenzar a usarlo. en aras de ser una especie de políticamente correcto. No olvide que la mayoría de los conceptos en el desarrollo de software no tienen nada de especial, son muy lógicos, simples y obvios, y a veces es más difícil recordar la convención de nomenclatura actual que comprender el concepto en sí. ¿El conocimiento de IOC2 hace que un desarrollador sea un mejor desarrollador? No, porque si un desarrollador no pudo idear un concepto similar al IOC2, entonces le será difícil entender qué problema está resolviendo IOC2, usarlo parecerá artificial y puede comenzar a usarlo. en aras de ser una especie de políticamente correcto. No olvide que la mayoría de los conceptos en el desarrollo de software no tienen nada de especial, son muy lógicos, simples y obvios, y a veces es más difícil recordar la convención de nomenclatura actual que comprender el concepto en sí. ¿El conocimiento de IOC2 hace que un desarrollador sea un mejor desarrollador? No, porque si un desarrollador no pudo idear un concepto similar al IOC2, entonces le será difícil entender qué problema está resolviendo IOC2, usarlo parecerá artificial y puede comenzar a usarlo. en aras de ser una especie de políticamente correcto. ¿El conocimiento de IOC2 hace que un desarrollador sea un mejor desarrollador? No, porque si un desarrollador no pudo idear un concepto similar al IOC2, entonces le será difícil entender qué problema está resolviendo IOC2, usarlo parecerá artificial y puede comenzar a usarlo. en aras de ser una especie de políticamente correcto. ¿El conocimiento de IOC2 hace que un desarrollador sea un mejor desarrollador? No, porque si un desarrollador no pudo idear un concepto similar al IOC2, entonces le será difícil entender qué problema está resolviendo IOC2, usarlo parecerá artificial y puede comenzar a usarlo. en aras de ser una especie de políticamente correcto.
fuente
Personalmente, uso IoC como algún tipo de mapa de estructura de mi aplicación (Sí, también prefiero StructureMap;)). Hace que sea fácil sustituir mis implementaciones habituales de interfaz con implementaciones de Moq durante las pruebas. Crear una configuración de prueba puede ser tan fácil como hacer una nueva llamada de inicio a mi IoC-framework, sustituyendo cualquier clase que sea mi límite de prueba con un simulacro.
Probablemente esto no sea para lo que IoC está allí, pero es para lo que más lo uso.
fuente
EL CONTENEDOR COI RESUELVE UN PROBLEMA QUE NO PODRÍAS TENER, PERO ES UN AGRADABLE PROBLEMA
http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-its-a-nice-problem-to-have/
fuente
No necesita un marco para lograr la inyección de dependencia. También puede hacer esto mediante conceptos básicos de Java. http://en.wikipedia.org/wiki/Dependency_injection#Code_illustration_using_Java
fuente
Me doy cuenta de que esta es una publicación bastante antigua, pero parece estar todavía bastante activa, y pensé que contribuiría con un par de puntos que aún no se han mencionado en otras respuestas.
Diré que estoy de acuerdo con los beneficios de la inyección de dependencia, pero prefiero construir y administrar los objetos yo mismo, usando un patrón no muy diferente al descrito por Maxm007 en su respuesta. He encontrado dos problemas principales con el uso de contenedores de terceros:
1) Tener una biblioteca de terceros que administre la vida útil de sus objetos "automáticamente" puede prestarse a resultados inesperados. Hemos descubierto que, especialmente en proyectos grandes, puede tener muchas más copias de un objeto de lo que espera, y más de lo que tendría si administrara manualmente los ciclos de vida. Estoy seguro de que esto varía según el marco utilizado, pero el problema existe. Esto también puede ser problemático si su objeto contiene recursos, conexiones de datos, etc., ya que el objeto a veces puede vivir más de lo esperado. De manera inevitable, los contenedores IoC tienden a aumentar la utilización de recursos y la huella de memoria de una aplicación.
2) Los contenedores IoC, en mi opinión, son una forma de "programación de caja negra". He descubierto que, en particular, nuestros desarrolladores menos experimentados tienden a abusar de ellos. Le permite al programador no tener que pensar en cómo los objetos deberían relacionarse entre sí o cómo desacoplarlos, ya que les proporciona un mecanismo en el que simplemente pueden agarrar cualquier objeto que quieran de la nada. Por ejemplo, puede haber una buena razón de diseño para que ObjectA nunca sepa sobre ObjectB directamente, pero en lugar de crear una fábrica, un puente o un localizador de servicios, un programador inexperto simplemente dirá "no hay problema, simplemente tomaré ObjectB del contenedor de IoC". ". Esto realmente puede conducir a un mayor acoplamiento de objetos, que es lo que se supone que IoC debe ayudar a prevenir.
fuente
La inyección de dependencia en un proyecto ASP.NET se puede lograr con unas pocas líneas de código. Supongo que hay una ventaja en usar un contenedor cuando tienes una aplicación que usa múltiples front-end y necesita pruebas unitarias.
fuente