jueves, 12 de junio de 2008

Inversion de Control (IoC)

Hace un tiempo atrás convencí a un amigo de que aprendiera Spring, contándole de todas las ventajas que podría lograr utilizando este framework. El comenzó a estudiarlo y como a todos nos ha pasado, le sorprendió la facilidad con la que puede desarrollar aplicaciones.
Hasta ahí todo iba muy bien, pero cuando le pregunte que le pareció la “inversión de control” y la “inyección de dependencia”, me dijo que lo único que entendía era que Spring utilizaba estos patrones…...pero de que se trataba……ni idea!!!!
Así que mi querido amigo XXX (no te voy a echar al agua)…...este post es para ti.
Imaginemos que tenemos una clase “Componente” que necesita usar la clase “Servicio”. Una solución para esto podría ser :







El problema de esto es que estamos acoplando las clases. Qué pasaría si por algún requerimiento, el desarrollador modifica el código, solicitando ahora algún parámetro en el constructor de la clase “Servicio”?. Esto nos llevaría no solo a modificar el código de la clase “Servicio”, sino también el de la clase “Componente”.
O pero aun, tu jefe te dice que no le gusta como esta implementada la clase “Servicio”, así que él, en un acto de iluminación divina, desarrollo la clase “Servicio2” la cual (supuestamente) es mejor a la anterior. Por lo tanto, nuevamente tendremos que modificar nuestra clase “Componente”:







…..y mejor ni pensemos si alguien se pone original (nunca faltan!!!!) y comience a modificar el constructor de la clase “Servicio2”.
Pero como nada es tan terrible, una solución para estos casos es la “Inversión de control”.
El primer cambio que tendremos que hacer a nuestro código, es olvidarnos de usar “new XXX()”, para lo cual definiremos un método “setXXX” que nos pase una referencia de una instancia de la clase “Servicio2” :







Hasta aquí todo va bien, pero que pasaría si nuestro jefe, en un acto de arrepentimiento te dice “evaluando la situación, pienso que debemos volver a usar la clase “Servicio” hasta que nuevo aviso (por no decir, hasta que arregle los errores en mi código)”, y nosotros que ya pensábamos que teníamos casi todo controlado, nuevamente tendremos que volver a cambiar el código de la clase “Componente”, modificando el atributo y el método “setXXX”.
Pero como buenos programadores, sabemos que no va a faltar el jefe original que se le ocurra volver a cambiar el servicio, así que, para evitar problemas a futuro, definiremos una interfaz para el servicio. De ahora en adelante, cualquier clase servicio que se le pase a la clase “Componente”, deberá implementar esta interfaz (ufff….ya no deberemos tocar el código de la clase “Componente”).











Como vemos, cambiar el tipo de servicio en la clase “Componente” ya no tiene impacto en nuestro código!!!! (Obviamente..…hasta que no falte el original que cambie la interfaz!!!).
Hasta aquí toda esta correcto, pero nos falta un pequeño elemento, el “Ensamblador”, cuya tarea principal es obtener la información de cómo cada uno de los elementos debe ser inyectado en otros elementos.
Para estos casos, es donde frameworks como PicoContainer o Spring utilizan el patrón “Inversión de Control”, los cuales se encargan de realizar la inyección de los elementos. El como lo hacen, puede ser a través de código o en un archivo de configuración.
Para el caso de la “Inyección de dependencias” existen tres mecanismos:
  • Inyección de Interfaz (IoC tipo 1)
  • Inyección de Setter (IoC tipo 2)
  • Inyección de Constructor (IoC 3)

Que diferencias existen entre los distintos tipos de inyección, va mas allá de este post, pero el señor Martin Fowler lo explica muy bien en este articulo.

La inversión de control no es la única forma de solucionar este problema, también existe el patrón “Service Locator”, pero eso es tema para otro post.

7 comentarios:

Ricardo Medina dijo...

Está muy bueno el artículo Jose, entretenido y super claro

Jose Luis dijo...

Buenisimo tu articulo.
Gracias por compartirlo.
Un Saludo

Jose Luis dijo...

Muy bueno el artico .
Gracias por compartirlo con Nosotros
Saludo.

Anónimo dijo...

Excelente... mas claro no ha podido ser.

Francisco dijo...

recien entiendo la Inversion de Control con claridad y el uso de Interfaces, mas claro ni el agua se agradece por compartir el conocimiento.

elperucho dijo...

Saludos Jose, buen articulo realmente muy bien explicado y con un ejemplo muy sencillo y cotidiano.

Solo una observacion la palabra reservada "implements" es utilizada en VB.NET para implementar herencias, recuerda que estas trabajando en C# y se utiliza ":", esto no quiere decir que el ejemplo este malo, el ejemplo esta bien planteado.

Anónimo dijo...

implements es de Java también usado para implementar Interfaces!!