viernes, 29 de abril de 2016

Inyección de dependencias

Cuantas veces hemos oído hablar o leído acerca de la inyección de dependencias y en ese momento a muchos nos llega a la mente Spring, a otros ni sentido les hace, bien pues en este mi primer post de mi blog les voy a explicar de forma rápida y sencilla lo que es.

Primero ¿que es la inyección de dependencias?

Pues la inyección de dependencias no es otra cosa que... chan chan chan chan... inyectar la dependencia a una clase... jejeje así de simple es, pero bien ya dejémonos de jaladas y veamos de forma mas clara, la inyección de dependencias es un "recurso" que se usa para desacoplar las clases, es decir, la idea es que una clase no cree la instancia de otra clase dentro de su código, sino mas bien que la instancia de la clase de la cual se depende sea creada desde fuera y que sea "inyectada" a la clase que la usa, en términos simples eso es la inyección de dependencia.

Ejemplo:

Pero bueno, creo que hasta acá no he dicho nada que no hayan ya leído o escrito, así que vamos a un ejemplo:

Pensaremos en un portal de empleado, en el que un empleado puede consultar los dias pendientes que tiene de vacaciones, viendo el diseño se puede pensar en las siguientes clases:

public class EmpleadosBusiness {

    private EmpleadosDAO empleadosDAO;

    public EmpleadosBusiness(){
        empleadosDAO = new EmpleadosDAO();
    }

    public int obtenerDiasPendientesVacaciones(Empleado empleado) {
        return this.empleadosDAO.obtenerDiasPendientesVacaciones(empleado);
    }
}


public class EmpleadosDAO {

    public int obtenerDiasPendientesVacaciones(Empleado empleado) {
        // se conecta a la base de datos y consulta cuantos dias 
        // pendientes de vacaciones tiene el empleado.
        return diasPendietes;
    }
}

Pues bien, acá no estamos aplicando inyección de dependencias, ya que la clase EmpleadosBusiness depende directamente de EmpleadosDAO pero en el constructor estamos creando la instancia de EmpleadosDAO.

Ahora lo que vamos a hacer es "inyectarle" la dependencia a EmpleadosBusiness, con esto el código queda así:

public class EmpleadosBusiness {

    private EmpleadosDAO empleadosDAO;

    public EmpleadosBusiness(EmpleadosDAO empleadosDAO) {
        this.empleadosDAO = empleadosDAO;
    }

    public int obtenerDiasPendientesVacaciones(Empleado empleado) {
        return this.empleadosDAO.obtenerDiasPendientesVacaciones(empleado);
    }
}


public class EmpleadosDAO {
 
    public int obtenerDiasPendientesVacaciones(Empleado empleado) {
        // se conecta a la base de datos y consulta cuantos dias 
        // pendientes de vacaciones tiene el empleado.        
        return diasPendietes;
    }
}

Como pueden notar, la clase EmpleadosDAO no tiene alteraciones, ya que no es necesario en esta versión, pero lo que si cambia es el constructor de la clase EmpleadosBusiness, el que ahora ya no crea la instancia de EmpleadosDAO, sino que en lugar de eso solo recibe la instancia y la usa.

Esa es la forma básica de la inyección de dependencias, pero aunque si es un paso adelante, aún se le puede hacer algo más (digo, ya empezamos con esto, ahora nos chingamos y lo hacemos bien de una vez) y ese algo más es quitar la dependencia directa de la clase EmpleadosDAO, pero ¿y esto como?, pues bien, usando interfaces (pinches interfaces son la onda), de esta forma el código queda así:

public class EmpleadosBusiness {
 
    private EmpleadosDAO empleadosDAO;

    public EmpleadosBusiness(EmpleadosDAO empleadosDAO) {
        this.empleadosDAO = empleadosDAO;
    }

    public int obtenerDiasPendientesVacaciones(Empleado empleado) {
        return this.empleadosDAO.obtenerDiasPendientesVacaciones(empleado);
    }
}


public class EmpleadosDAODataBaseImpl implements EmpleadosDAO {
 
   @Override
    public int obtenerDiasPendientesVacaciones(Empleado empleado) {
        // se conecta a la base de datos y consulta cuantos dias 
        // pendientes de vacaciones tiene el empleado.        
        return diasPendietes;
    }
}


public interface EmpleadosDAO {
 
   int obtenerDiasPendientesVacaciones(Empleado empleado);
}

Lo que hicimos fue renombrar la clase EmpleadosDAO a EmpleadosDAODataBaseImpl, luego crear la interface EmpleadosDAO, luego hacer que la clase EmpleadosDAODataBaseImpl implemente la interface EmpleadosDAO y por último hacer que la clase EmpledosBusiness trabaje con la interface, no con la clase concreta.

Al final así es como se ven las clases usando inyección de dependencias y bueno, al final ¿que ganamos? pues ganamos desacoplamiento entre las clases y algo muy importante en el diseño de clases... es mucho mas testeable, pero de esas dos cosas hablaremos después.