2010-09-28 7 views
6

He estado leyendo acerca de los frameworks de Inversion of Control y estoy jugando con la pregunta: "¿Por qué demonios necesito un framework para hacer esto?"Por qué usar un framework IoC

No entendí mal mi pregunta ... el patrón es algo que los programadores usamos a menudo pero ... ¿un marco completo para hacer eso?

Me falta algo y esa es la razón por la que estoy publicando la pregunta. He visto muchos ejemplos en la web y simplemente no lo entiendo. mi mente está bloqueada a la idea tal vez.

Basta con echar un vistazo a el ejemplo de la página de inicio de Ninject:

public class Samurai { 
    public IWeapon Weapon { get; private set; } 
    public Samurai(IWeapon weapon) { 
     Weapon = weapon; 
    } 
} 

public class WarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<IWeapon>.To<Sword>(); 
    } 
} 

La clase "Samurai" está bien para mí. El marco "NinjectModule" me parece innecesario.

Asumo adelante en el código que vamos a crear nuevas instancias "Samurai" que pasan en los casos "espada" a él, algo así como:

Samurai theWarrior = new Samurai(WarriorModule.GetInstance(IWeapon));//no coupling 

que podrían sustituirse por:

Samurai theWarrior = new Samurai(new Sword());//still no coupling 

o

Samurai theWarrior = new Samurai(GetWeaponFromXML());//no coupling yet 

lo que es la parte que me falta? ¿Podría hablarnos de algún escenario en el que IOC Framework podría ser necesario en mi aplicación?

Gracias.

ACTUALIZAR DESPUÉS DE 4 RESPUESTAS: Me gustaron todas las respuestas que obtuve de ustedes. Acabo de leer esta publicación dependency-injection-dissection/ donde el chico la usa para Unit Testing y el enlace StackOverflow que acabas de proporcionar. Sí, me faltaba la parte de la complejidad grande y grande, así que permítame personalizar el uso de un framework IoC. Gracias de nuevo.

Yo votaría sus respuestas, pero acabo de recibir un mensaje naranja que dice que no puedo.

Gracias al hombre que destacó el código que publiqué.

+1

que sugeriría la edición de su pregunta para que los bloques de código bloques de código reales, ya sea por 'resaltando y pulsando Ctrl-k 'o insertando cuatro espacios delante de cada línea de código. – jcolebrand

+0

'nuevo Samurai (nueva espada()); // aún no hay acoplamiento 'Hay un acoplamiento fuerte aquí, usa' nuevo'. Cuando refactorices eso, tendrás que cambiar cada lugar que crea una espada. – nos

+0

posible duplicado de [¿Por qué necesito un contenedor IoC en lugar de un código DI directo?] (Http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed -to-straight-forward-di-code) –

Respuesta

4

Su ejemplo es bastante sencillo teniendo sólo las dos capas, pero cuando se tiene un ejemplo de la vida real, que pronto se complica:

contenedor
var form = new OrderEntryForm(
    new OrderService(
     new OrderReposity(
      new DatabaseGateway(
       new DataProviderFactory())))) 

Un COI puede hacer todo el cableado para usted, haciendo que su la vida es mucho más fácil.

Este es un ejemplo de una pregunta similar, que va en todos los detalles: https://stackoverflow.com/questions/45191/ioc-explain-and-more-important-when-to-use-it/45197#45197

+0

¿Cómo reduce un contenedor IoC la complejidad? Quiero decir que aún tendrías que definir todo el árbol, pero tienes que usar otro idioma que sea más propenso a errores. –

6

Este es el problema con los ejemplos de código. O bien son complejos y no has explicado tu punto, o son triviales y luego parecen inútiles.

Lo que el WarriorModule está haciendo es vincular un tipo concreto a una interfaz, por lo que siempre que otra clase necesite una implementación de esa interfaz, recibe una automáticamente por el contenedor IoC. La clase con la dependencia no depende del tipo concreto, por lo que tiene un acoplamiento más bajo y una mayor capacidad de prueba. Creo que ya lo sabías.

En los escenarios de reemplazo, la clase Samurai no está acoplada a la clase de espada, pero el código de llamada aún lo es. Podrías sacar ese otro nivel, pero ese código ahora tendría la dependencia, y tu clase interviniente ahora tendría que ordenar todas las dependencias.

El contenedor IoC hace esto para todas las asignaciones, poniéndolo en solo unos pocos lugares (las clases de módulo). El resto de su código es libre de no importarle, no tener dependencias en tipos concretos.

Espero que ayude.

+0

Le gusta este comentario; "Este es el problema con los ejemplos del código. Son complejos o no explicaron su punto, o son triviales y luego parecen inútiles". Normalmente diría más a este último. Particularmente con Ninject, ninguno de los ejemplos proporcionados justifica su uso porque son demasiado simples, y no demuestran ninguno de los detalles que hacen que valga la pena más allá de la DI manual. –

+0

Si tiene un buen diseño, no tiene mucho acoplamiento. ¿Y dónde está la diferencia si defino el cableado con XML o código en un solo lugar? –

1

Recientemente comencé a usar el Unity para IoC y no tengo dudas de que me hace la vida más fácil.

Voy a pegar mi código textualmente y espero que lo encuentres útil. Alguien con más experiencia podría darte más.

Además, me pareció útil leer el documento sobre DI de Fowler.

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     using (IUnityContainer container = new UnityContainer()) 
     { 
      container 

       .RegisterType<ILogger, StatSyncherFormView>(new myLife()) 

       // GUI 
       .RegisterType<IStatSyncherView, StatSyncherFormView>() 

       // Services 
       .RegisterType<ISalesForceWebServices, SalesForceWebServices1>() 

       .RegisterInstance(new SalesForceWebServices1(
        "XXX", "XXX", 
        "https://login.salesforce.com/services/Soap/c/19.0/0DF70000000CfHq", 
        "https://na5-api.salesforce.com/services/Soap/s/19.0")) 


       .RegisterType<ISalesForceService, SalesForceService1>() 

       .RegisterType<IRestApiCall, RestApiCall1>() 

       .RegisterType<IDirectTrackService, DirectTrackService1>() 

       .RegisterType<IDAgentsService, DAgentsService1>() 

       .RegisterType<IQuickBooksService, QuickBooksService1>(); 

      StatSyncherPresenter p = container.Resolve<StatSyncherPresenter>(); 

      Application.Run((Form)p.view); 
     } 
    } 

Una de las cosas que me parece más útil es:

public class AnyClassCreatedByContainer 
{ 
    [Dependency] 
    public ILogger Logger { get; set; } 
} 
1

Aunque Samurai theWarrior = new Samurai(new Sword()); todavía no hay acoplamiento, si es que se quiere dar a todos los samurais en la aplicación de un <insert favourite weapon here>, que tendría que cambiar todo tu código de llamada para cambiar a la nueva arma, mientras que con IoC lo cambiarías en un punto y todos tus samurais estarían usando la nueva arma.

Cuestiones relacionadas