2009-02-26 9 views

Respuesta

9

Lea de este excelente article de Martin Fowler.

Además, eche un vistazo al wikipedia article.

La inyección de dependencia es el ejemplo más conocido de la inversión de control, lo que en definitiva se convierte el código de esto:

public class FileReader { } 
public class Application { 
    // inflexible concrete dependency 
    private FileReader fileReader = new FileReader(); 
} 

Para:

public interface Reader {} 
public class FileReader implements Reader {} 
public class Application { 
    // flexible abstract dependency injected in 
    private Reader reader; 

    public Application(Reader reader) { // constructor injection 
     this.reader = reader; 
    } 
    public void setReader(Reader reader) { // setter injection 
     this.reader = reader; 
    } 
} 
+1

toolkit == quickDraw. – duffymo

+0

(sopla humo del barril) – toolkit

+0

¿eh? ¿Es eso una broma interna? –

4

No, COI no es DDD o TDD .

Martin Fowler's article es una buena introducción.

+0

De acuerdo 100%, pero IOC es casi obligatorio para un buen TDD. ;-) –

+0

Lo siento, lugar equivocado. Significó agregar a otra respuesta. –

+0

No, estuve en el lugar, así que solo estoy agregando comentarios que prueban que soy un idiota total hoy. –

1

Para su pregunta sobre qué es COI, Wikipedia tiene un fairly extensive explanation.

En cuanto a tutoriales o ejemplos this tutorial lo cubre bastante bien y tiene un montón de código de exmaple.

+0

+1, solo para la cotización de DeMarco. – duffymo

12

IOC, o inversión de control, es, en la mayoría de las aplicaciones, la inversión de la ruta a través del código de la interfaz de usuario a la base de datos. Esta no es una respuesta completa, pero es una de las maneras más fáciles de entender el concepto.

Si desea aprender IOC, entre en TDD, ya que encontrará que la configuración de pruebas es mucho más fácil una vez que invierta.

Ejemplo:

flujo típico de la mayoría de las aplicaciones .NET que he visto es algo como esto:

UserCollection col = BusinessLayer.Class.GetLoggedInUsers(); 
//Business logic 
return col; 

entonces los negocios es la siguiente:

UserTable table = DataLayer.Class.GetLoggedInUsers(); 
return table; 

etc. Esto es todo pseudocódigo. Para usar IOC en este ejemplo, agregue una interfaz para la clase de capa de datos, como IUserRepository. Puedes usar genéricos, y yo recomendaría debajo del capó.

A continuación, puede hacer algo como esto:

IUserRepository repository = SetUpRepository(); 
UserCollection col = BusinessLayer.Class.GetUsers(repository); 

¿Por qué es esto importante? Para las pruebas, puede crear un repositorio simulado y alimentarlo a la clase ejecutiva. El simulacro contiene datos que siempre son los mismos, lo que significa que está ejercitando su código, no probando de punta a punta.

Si quieres C#, aquí es un ejemplo básico de weblogs.asp.net:

0

Si usted entiende DIP (Dependencia Inversión Principio), la COI es la torta. Sugiero aprender los principios orientados a objetos antes de aprender los patrones. Los principios básicos pueden apilarse como legos para lograr cualquier patrón.Brandon Joyce

7

Para hablar de jerga, la inversión de control es un patrón que admite, entre otras cosas, el principio de responsabilidad única.

Para entender por qué todo esto es útil, necesitas algo de exposición, así que ten paciencia conmigo.

La responsabilidad única básicamente significa que su clase debe ser tan independiente de otras partes del sistema como sea posible, para minimizar el impacto de cambiar una parte en la otra. (También puede vincular eso al hecho de que cambiar la implementación no debe desencadenar la recompilación de todos los archivos en sus proyectos, como es el caso al cambiar los archivos .h en un proyecto C/C++, por ejemplo). El efecto secundario es que termina con muchos objetos pequeños que hacen una sola cosa, pero muy bien (en un mundo ideal)

Pero en la mayoría de los casos, para llevar a cabo su trabajo, un objeto necesita hablar con otro objeto: depende de ellos.

Primera parte de la mitigación que separa la implementación de las interfaces. Eso significa confiar en interfaces (o clases abstractas, dependiendo de su idioma de elección), de modo que un objeto no esté vinculado a la implementación específica de otro.

, a utilizar un ejemplo canónico, en las necesidades de la capa de negocio, es necesario llevar a cabo una función que necesita acceso a - La capa de datos para recuperar objetos - algún otro servicio - un registrador para registrar información y o errors

A su vez, cada servicio o dependencia tiene sus propias dependencias, que su clase debería tener en cuenta incluso si no las usa. Según la cantidad de referencias, la configuración del objeto puede salirse de control rápidamente. Ahora multiplique eso por la cantidad de clases que necesita escribir y terminará con un caos de cosas.

El uso de un contenedor de COI básicamente le ayuda a deshacerse de ese lío. Cuando necesita un objeto, no lo "actualiza". En su lugar, le pide al contenedor del COI que lo recupere por usted. El contenedor es responsable de entregar un objeto funcional, listo para ser usado, cualquiera que sean sus dependencias.

Lo que significa es que su clase no necesita conocer las dependencias de las clases en las que se basa, lo que reduce el enredo. Además, no necesita saber qué clase real implementa los servicios de los que depende, lo que significa que - La implementación del servicio se puede definir en otro proyecto (dll o lo que sea), por lo que modificarlo nunca afectará su clase - La implementación puede ser diferente según el contexto (piense en cambiar la base de datos, o incluso en ir a un servicio web para recuperar información según la configuración o incluso el estado actual de la aplicación).

Para intentar responder a sus otras preguntas, IOC es un patrón. TDD y DDD son metodologías de diseño, por lo tanto, uno no puede igualar al otro. Pero IOC es una herramienta invaluable para admitir TDD o DDD.

Sé que la sopa de acrónimos y las muestras parciales que puede encontrar no son fáciles de asimilar. El mejor consejo que puedo darte es probar algunos proyectos pequeños, prototipos que vas a descartar, solo para manejarlos. No es una forma fácil de hacerlo si lo buscas para el trabajo, pero vale la pena, aunque solo sea desde un punto de vista personal.

Espero que ayude un poco.

0

Inversion of Control es la abstracción de la estructura de la lógica. Un enfoque (a menudo utilizado como sinónimo de IoC) es Dependency Injection, que abstrae referencias entre objetos. Cuando los objetos se liberan de los detalles de implementación de una aplicación, como qué clase implementa qué servicio, son libres de centrarse en sus funciones principales.

Por ejemplo, supongamos que tiene una clase que necesita asignar objetos Foo a objetos Bar. Es posible escribir esto:

public class FooMapper 
{ 
    public Bar Map(Foo foo) 
    { 
     // ... 
    } 
} 

y utilizar de esta manera:

public class NeedsToMapFoos 
{ 
    public void MapSomeFoos() 
    { 
     var fooMapper = new FooMapper(); 

     // ... 
    } 
} 

Mientras válida, esto también es rígido. A NeedsToMapFoos solo le preocupa que la asignación ocurra, no es que ocurra de una manera específica.

Podemos representar el concepto de "ejecución de la operación sans" con una interfaz:

public interface IFooMapper 
{ 
    Bar Map(Foo foo); 
} 

y declarar una dependencia de esa operación:

public class NeedsToMapFoos 
{ 
    private readonly IFooMapper _fooMapper; 

    public NeedsToMapFoos(IFooMapper fooMapper) 
    { 
     _fooMapper = fooMapper; 
    } 

    public void MapSomeFoos() 
    { 
     // ...use _fooMapper... 
    } 
} 

Ahora NeedsToMapFoos tiene menos conocimiento, lo que significa que es menos complejo. En lugar de realizar tareas administrativas, es libre de enfocarse en el caso de negocios.

Los objetos bien factorizados como este también son más adaptables. Así como los diamantes son rígidos y la arcilla es maleable, la estructura interna determina la respuesta al cambio.

Finalmente, la lógica escrita en este estilo también es flexible. Digamos que FooMapper.Map es una operación cara y debe almacenarse en caché. Puede utilizar el patrón decorador para envolver la aplicación existente y sin problemas pasarlo a NeedsToMapFoos:

public class CachingFooMapper : IFooMapper 
{ 
    private readonly IFooMapper _innerMapper; 
    private readonly IDictionary<Foo, Bar> _cache; 

    public CachingFooMapper(IFooMapper innerMapper) 
    { 
     _innerMapper = innerMapper; 
    } 

    public Bar Map(Foo foo) 
    { 
     // Read bar from _cache. If not there, read from inner mapper and add to _cache. 
    } 
} 

// Usage 

new NeedsToMapFoos(new CachingFooMapper(new FooMapper())); 
Cuestiones relacionadas