domingo, 8 de octubre de 2017

Inversión de Control IoC e Inyección de Dependencias DI

Principio de Inversión de Dependencias DIP 

DIP (Dependency Inversion Principle), se trata de una estrategia utilizada por la ingeniería del software, basada en los principios del manifiesto SOLID de ingeniería. Esta estrategia tiene como objetivo obtener la mejor eficiencia del software. Por ejemplo, la estrategia evita que los módulos de alto nivel, no dependan de los de bajo nivel y que por el contrario, dependan de las abstracciones. Ello quiere decir que, a través de este proceso, se logra reducir el factor de acomplamiento. En esencia, esta es la característica fundamental que justifica la estrategia del Control de Inversión IoC  y de la Inyección de Dependencias DI. 

Factor de Acoplamiento 

La construcción del software basado en el paradigma Orientado a Objetos, generalmente hace uso de los procesos que brinda la herencia y la implementación de interfaces. En efecto, gracias a este proceso, podemos construir software escalable y robusto. Sin embargo, existe un punto crítico al que debemos considerar. Este punto es el factor de acomplamiento. El factor no es más que la estrategia mecánica de acomplar clases e interfaces entre sí. Si este proceso tiende a ser muy diversificado y masivo, el factor nos arrojará una tasa elevada de acomplamiento y en consecuencia, podría condicionar los procesos de la mantenebilidad del software. 

Además, el contexto podría tender a ser complejo. Es cuando se acuña el término de factor "alto-acomplamiento" o altamente acomplado, en inglés Strongly-Coupled. Por tanto, cuando reducimos esta tasa de acoplamiento, estaremos haciendo la estretegia contraria, que es "bajo-acomplamiento" o débilmente acoplada que en inglés, se la conoce con el término de Weakly-Coupled. 

En consecuencia, resulta muy importante considerar estos puntos clave. Para mejorar estos aspectos y optimizarlos, podremos utilizar las estrategias que proponen IoC y DI, de manera de poder hacer eficiente la construcción de nuestro software. 

Inversión de Control IoC 

IoC (Inversion on Control) o Inversión de Control se trata de una estrategia de programación que básicamente controla el flujo del programa. El paradigma que plantea, resulta ser yuxtapuesto con respecto al proceso convencional que poseen los desarrolladores y programadores, que desde un principio, plantean todo el aspecto del flujo del programa. 

Inyección de Dependencias DI

DI (Dependency Injection) o Inyección de Dependencias se trata nada menos que de un patrón de diseño y cuyo gran objetivo final, es el de construir software con los factores mínimos de acomplamientos. El proceso hace uso de una técnica de "inyección" hacia los módulos en juego. Ello quiere decir que cuando se construyen las dependencias sobre una clase y se las proporciona, el proceso de inclusión, se realiza de modo similar a un proceso de inyectado. 

Para poder comprender mejor estos conceptos, vamos hacer uso de código en el lenguaje de C#, basado en clases a modo de ejemplo. No obstante, esta estrategia puede ser aplicada perfectamente en cualquier lenguaje orientado a objetos. 

public class Clientes
{
       public int Id { get; set; }
       public String Razon { getset; }
       public String Direccion { getset; }
       public String Telefono { getset; }
       public String Email { getset; }
}

Aquí hemos creado una clase de tipo Entidad de Datos llamada Clientes, a los efectos gestionar los datos en las subsiguientes clases, las que en esencia, nos permitirán demostrar los procesos DIP. 

public class NoDIP 
{
    private Clientes cliente;

    public NoDIP(
        int id, String razon, String direccion,
        String telefono, String email
    ) {
            cliente = new Clientes() {
            Id =id,
            Razon =razon,
            Direccion =direccion,
            Telefono =telefono,
            Email =email
        };
        Console.WriteLine("Datos del Cliente:");
        Console.WriteLine("Id: {0}", cliente.Id);
        Console.WriteLine("Razón: {0}", cliente.Razon);
        Console.WriteLine("Dirección: {0}", cliente.Direccion);
        Console.WriteLine("Teléfono: {0}", cliente.Telefono);
        Console.WriteLine("Email: {0}", cliente.Email);
    }
}

Esta clase no hace uso de la Inyección de Dependencias. Si observamos bien, podremos apreciar que la clase Clientes, es creada como campo dentro de la clase NoDIP. Luego, a través de los parámetros de su constructor, se pasan los datos del cliente mediante argumentos. El proceso siguiente, es pasar estos datos desde estos argumentos a la clase Clientes misma, usando su propio constructor dinamicamente. Finalmente, los datos, son pasados a los procesos de escritura de la consola, de modo de que más tarde, se muestren en pantalla. 

public class SiDIP
{
    public SiDIP(Clientes cliente) {
        Console.WriteLine("Datos del Cliente:");
        Console.WriteLine("Id: {0}", cliente.Id);
        Console.WriteLine("Razón: {0}", cliente.Razon);
        Console.WriteLine("Dirección: {0}", cliente.Direccion);
        Console.WriteLine("Teléfono: {0}", cliente.Telefono);
        Console.WriteLine("Email: {0}", cliente.Email);
    }
}

En esta clase hacemos de la Inyección de Dependencias. Si apreciamos el código, podremos ver que aquí simplemente a través del constructor de la clase SiDIP, pasamos como argumentos, la clase Clientes como constructor. Luego, los datos son pasados directamente a los procesos de la consola para que posteriormente, sean impresos en pantalla. Aquí se nota claramente la gran diferencia. Observemos que existe menos dependencia de la clase Clientes que en el anterior caso. 

Para poder probar nuestro ejemplo, simplemente creamos el siguiente código. 

class Program
{
    static void Main(string[] args)
    {

        NoDIP nodip = new DIP.NoDIP(
            1, "ALITEL SA", "Av Sperantus 123"
            "989-1234-5678", "info@alitelsa.com");

        Console.WriteLine("");

        SiDIP sidip = new DIP.SiDIP(
            new Clientes() {
                Id = 2, 
                Razon = "TERNARIUS SA"
                Direccion = "Av Saint Lorenze 234"
                Telefono = "989-9876-4532"
                Email = "info@ternarius.com"
            });

        Console.Read();
    }

La Resultante es la siguiente: 

Datos del Cliente:
Id: 1
Razón: ALITEL SA
Dirección: Av Sperantus 123
Teléfono: 989-1234-5678
Email: info@alitelsa.com

Datos del Cliente:
Id: 2
Razón: TERNARIUS SA
Dirección: Av Saint Lorenze 234
Teléfono: 989-9876-4532
Email: info@ternarius.com

Conclusiones 

Como hemos visto en este artículo, el factor de acomplamiento resulta ser bastante interesante para el desarrollo del software. Sus ventajas son bastantes amplias y aquí, tan solo he citado una de ellas. Tenemos que considerar que esta estrategia también se puede aplicar a las interfaces e incluso, tanto a métodos como a las propiedades. El uso racional y enfocado en este contexto, nos permitirá desarrolla software más eficiente y lo más importante de todo, de fácil mantenebilidad sin olvidar la escalabilidad.  

Hasta pronto.