¿Por qué necesito un contenedor IoC en lugar de un código DI sencillo? [cerrado]

Resuelto asked hace 15 años • 30 respuestas

He estado usando la inyección de dependencia (DI) por un tiempo, inyectando en un constructor, propiedad o método. Nunca sentí la necesidad de utilizar un contenedor de inversión de control (IoC). Sin embargo, cuanto más leo, más presión siento por parte 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 empezar a utilizar 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 mostrarse reacios a aprender nuevas tecnologías.

Por favor, convénceme de que necesito usar un contenedor de IoC. Voy a utilizar estos argumentos cuando hable con mis compañeros desarrolladores en el trabajo.

 avatar May 16 '09 08:05
Aceptado

Vaya, no puedo creer que Joel estuviera a favor de esto:

var svc = new ShippingService(new ProductLocator(), 
   new PricingService(), new InventoryService(), 
   new TrackingRepository(new ConfigProvider()), 
   new Logger(new EmailLogger(new ConfigProvider())));

Más allá de esto:

var svc = IoC.Resolve<IShippingService>();

Mucha gente no se da cuenta de que su cadena de dependencias puede anidarse y rápidamente resulta difícil de manejar conectarlas manualmente. Incluso con las fábricas, la duplicación de su código simplemente no vale la pena.

Los contenedores de COI pueden ser complejos, sí. Pero en este sencillo caso que he demostrado, 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 interfaz de usuario inteligente. Esta interfaz de usuario inteligente (la llamaremos Shindows Morms) quiere que implemente INotifyPropertyChanged para que pueda realizar un seguimiento de cambios y actualizar la interfaz de usuario en consecuencia.

"Está bien, eso no suena tan difícil", así que empiezas a escribir.

Empiezas con esto:

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime CustomerSince { get; set; }
    public string Status { get; set; }
}

..y terminar con esto :

public class UglyCustomer : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            string oldValue = _firstName;
            _firstName = value;
            if(oldValue != value)
                OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            string oldValue = _lastName;
            _lastName = value;
            if(oldValue != value)
                OnPropertyChanged("LastName");
        }
    }

    private DateTime _customerSince;
    public DateTime CustomerSince
    {
        get { return _customerSince; }
        set
        {
            DateTime oldValue = _customerSince;
            _customerSince = value;
            if(oldValue != value)
                OnPropertyChanged("CustomerSince");
        }
    }

    private string _status;
    public string Status
    {
        get { return _status; }
        set
        {
            string oldValue = _status;
            _status = value;
            if(oldValue != value)
                OnPropertyChanged("Status");
        }
    }

    protected virtual void OnPropertyChanged(string property)
    {
        var propertyChanged = PropertyChanged;

        if(propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(property));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Ese es un código de plomería repugnante, y sostengo que si escribes un código como ese a mano, le estás robando a tu cliente . Hay formas de trabajar mejores y más inteligentes.

¿Alguna vez escuchó ese término, trabajar más inteligentemente, no más duro?

Bueno, imagina que un tipo inteligente de tu equipo se acerca y dice: "Aquí tienes una manera más fácil".

Si hace que sus propiedades sean virtuales (cálmese, no es gran cosa), entonces podemos incorporar ese comportamiento de propiedad automáticamente. (Esto se llama AOP, pero no te preocupes por el nombre, concéntrate en lo que hará por ti)

Dependiendo de la herramienta de IoC que esté utilizando, podría hacer algo parecido a esto:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper());

¡Maricón! Todo ese INotifyPropertyChanged BS manual ahora se genera automáticamente para usted, en cada definidor de propiedad virtual del objeto en cuestión.

¿Es esto magia? ! Si puede confiar en el hecho de que este código hace su trabajo, entonces puede omitir con seguridad todas esas propiedades que envuelven palabrerías. Tienes problemas comerciales que resolver.

Algunos otros usos interesantes de una herramienta IoC para realizar AOP:

  • Transacciones de bases de datos declarativas y anidadas
  • Unidad de trabajo declarativa y anidada
  • Inicio sesión
  • Condiciones Pre/Post (Diseño por Contrato)
Ben Scheirman avatar Oct 07 '2009 15:10 Ben Scheirman

Estoy contigo, Vadim. Los contenedores IoC toman un concepto simple, elegante y útil y lo convierten en algo que debes estudiar durante dos días con un manual de 200 páginas.

Personalmente, estoy perplejo por cómo la comunidad de IoC tomó un hermoso y elegante artículo de Martin Fowler y lo convirtió en un conjunto de marcos complejos que generalmente tienen manuales de 200 a 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 perfecto 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 gente que no los entiende.

El beneficio más valioso de usar un contenedor IoC es que puede tener un interruptor de configuración en un solo lugar que le permite cambiar entre, por ejemplo, el modo de prueba y el modo de producción. Por ejemplo, supongamos que tiene dos versiones de sus clases de acceso a la base de datos... una versión que se registró agresivamente e hizo mucha validación, que usó durante el desarrollo, y otra versión sin registro ni validación que fue increíblemente 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 sencilla sin la complejidad de los contenedores de 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 tienes que mirar para descubrir qué intenta hacer el código aumenta al menos en uno. Y en algún lugar del cielo un ángel grita.

 avatar May 16 '2009 01:05

Es de suponer que nadie le obliga a utilizar un marco de contenedor DI. Ya estás usando DI para desacoplar tus clases y mejorar la capacidad de prueba, por lo que estás obteniendo muchos de los beneficios. En resumen, estás favoreciendo la simplicidad, lo cual generalmente es algo bueno.

Si su sistema alcanza un nivel de complejidad en el que la DI manual se convierte en una tarea ardua (es decir, aumenta el mantenimiento), compárelo con la curva de aprendizaje del equipo de un marco de contenedor DI.

Si necesita más control sobre la gestión de la vida útil de las dependencias (es decir, si siente la necesidad de implementar el patrón Singleton), consulte 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. Cíñete 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 excelente publicación de blog de Mark Seemann sobre esto: Cuándo usar un contenedor DI

 avatar Sep 19 '2009 02:09