Diseño ágil con TDD

7.3. Inversión del Control (IoC)

Inversión del Control es sinónimo de Inyección de Dependencias (DI). El nombre fue popularizado por el célebre Martin Fowler pero el concepto es de finales de los años ochenta. Dado el principio de la inversión de dependencias, nos queda la duda de cómo hacer para que la clase que requiere colaboradores de tipo abstracto, funcione con instancias concretas. Dicho de otro modo, ¿Quién crea las instancias de los colaboradores?

Retomemos el ejemplo de las clases de antes. Tradicionalmente la clase Logica tendría una sentencia de tipo _myPersistor = new MyDB() dentro de su constructor o de algún otro método interno para crear una instancia concreta, ya que no podemos crear instancias de interfaces ni de clases abstractas.

En tiempo de compilación nos vale con tener el contrato pero en tiempo de ejecución tiene que haber alguien que se ponga en el pellejo del contrato. Si lo hacemos así volvemos al problema de tener que modificar la clase Logica para guardar en ficheros binarios. La solución es invertir la forma en que se generan las instancias.

Habrá una entidad externa que toma la decisión de guardar en base de datos o en ficheros y en función de eso crea la instancia adecuada y se la pasa a Logica para que la asigne a su miembro _myPersistor. Hay dos formas, como parámetro en el constructor de Logica o bien mediante un setter o método que únicamente sirve para recibir el parámetro y asignarlo al atributo interno.

La entidad externa puede ser otra clase o bien puede ser un contenedor de inyección de dependencias. ¿Qué son los IoC Containers? Son la herramienta externa que gestiona las dependencias y las inyecta donde hacen falta.

Los contenedores necesitan de un fichero de configuración o bien de un fragmento de código donde se les indica qué entidades tienen dependencias, cuáles son y qué entidades son independientes. Afortunadamente hay una gran variedad de contenedores libres para todos los lenguajes modernos. Algunos de los más populares son Pinsor para Python, Spring Container para Java y .Net, Pico y Nano para Java, Needle y Copland para Ruby y Castle.Windsor para .Net.

Habiendo preparado las clases de nuestro ejemplo para la inversión del control, podemos especificar al contenedor que inyecte MyDB o FS mediante un fichero de configuración que lee la aplicación al arrancar y conseguir diferente comportamiento sin tocar una sola línea de código. Demoledor.

Si la aplicación es pequeña no necesitamos ningún contenedor de terceros sino que en nuestro propio código podemos inyectar las dependencias como queramos. Los contenedores son una herramienta pero no son imprescindibles. Su curva de aprendizaje puede ser complicada.

En nuestro pequeño ejemplo hemos seguido la mayor parte de los principios S.O.L.I.D, aunque no hemos entrado a ver qué hacen las clases en detalle pero por lo menos queda una idea ilustrativa del asunto que nos ocupa. No se asuste,resulta más sencillo de lo que parece y sino, TDD no lo va a ir cascando todo, ya verá.


Copyright (c) 2010-2013 Carlos Ble. La copia y redistribución de esta página se permite bajo los términos de la licencia Creative Commons Atribución SinDerivadas 3.0 Unported siempre que se conserve esta nota de copyright.