Mostrando entradas con la etiqueta IoC. Mostrar todas las entradas
Mostrando entradas con la etiqueta IoC. Mostrar todas las entradas

domingo, 14 de marzo de 2010

Inversión de Control e Inyección de dependencias

Inversión de control e inyección de dependencia son términos que se confunden constantemente, vale la pena aclarar desde el inicio que la inyección de dependencia es una forma de implementar la inversión de control, de la misma forma existen otras implementaciones con, por ejemplo, el patrón “Factory” o el “service locator”.

La característica principal de la inversión de control es que el control del flujo es invertido con respecto a los métodos tradicionales. En vez de tener un código central que lo controle, indicamos que es lo que estamos esperando, para que una entidad aparte se encargue de proveerlo, así, es esta entidad quien decide como y cuando proveer lo esperado. En pocas palabras, nuestro código es el llamado, y no como ocurre comúnmente, cuando nuestro código es quien tiene el control del flujo y lo que hace es hacer llamadas. Se dice que es una implementación del Principio de Hollywood “No llame, nosotros le llamamos”.

Para obtener flexibilidad, “testeabilidad” y reutilización, debemos buscar siempre el menor acoplamiento posible. Si hacemos este acoplamiento por medio de interfaces y utilizamos una entidad aparte para que nos provea la implementación concreta, nos simplificamos sobre manera cambios futuros, ya que solo deberíamos cambiar la implementación sin tener que modificar en lo absoluto el objeto dependiente.

Estando claros que la inyección de dependencia es una forma específica de implementar inversión de control. Podríamos decir que lo que haremos es “inyectar” los objetos necesarios, según una configuración previa, evitando que sea la misma clase quien se encargue de crearlos u obtenerlos, así nos desentendemos de manejar su implementación por completo, ósea, no nos preocupamos por su ciclo de vida del todo. Usualmente utilizaremos un contenedor que se encargue de todo lo referente a la inyección propiamente dicha (creación, inyección, dependencias, destrucción, etc), si este contenedor esta externo podríamos decir que estamos utilizando inversión de control.

Con una comprensión más clara de los conceptos, que de alguna forma, es muy posible ya estemos aplicando, estaremos en posibilidad de escribir código más desacoplado, flexible y sobre todo reutilizable.

sábado, 13 de marzo de 2010

Contenedor IoC

Cuando decidimos utilizar IoC ("Inversion of Control" - Inversión de Control) ocupamos un Contenedor o en otras palabras un software, en el cual podamos registrar nuestros objetos ya sea por medio de un archivo de configuración (usualmente XML) o desde el código mismo y que sea este quien se encargue de la inicialización de los objetos que estamos esperando. La idea es que podamos tomar ya sea una clase abstracta o una Interfase y pedirle al contenedor que nos resuelva la instancia concreta deacuerdo con la definición esperada. Steven Sanderson en su libro Pro ASP.NET MVCFramework (el cual les recomiendo) añade que un buen contenedor debe contar con tres características extra más allá de simplemente resolver la inicialización de la instancia.

Esta tres características son:

  • Resolución de dependencias en cadena: Lo que implica que si se esta resolviendo la dependencia de un objeto que requiere de otro, el contenedor debe ser capaz de proveer la dependencia requerida.
  • Tiempo de vida de los objetos: Debe encargarse de mantener el estilo de vida de los objetos. Si una instancia es solicitada más de una vez, el contenedor deberá escoger entre varias opciones, por ejemplo mantener una única instancia para todas las solicitudes (singleton), o crear una nueva por solicitud (transient), entre otras. Esto es lo que se conoce como el "lifestyle" del objeto, hay varias opciones predefinidas como singleton (que es la default), thread, transient, pooled y customizadas como PerWebRequest.
  • Valores de parámetros explícitos para los constructores: Esto quiere decir que si un constructor que debe inicializar el contenedor requiere de parámetros, deber existir un medio en la configuración que permita proveer los valores. El ejemplo clásico es el ConnectionString para el acceso a datos o el servidor SMTP para enviar correos.

Otra parte complicada es escoger cual de los contenedores disponibles actualmente vamos a usar. Entre los más comunes se encuentran:
  • Castle Windsor (El que usamos actualmente)
  • Spring.NET
  • StructureMap
  • Unity
  • Puzzle.NFactory

Después de una rápida vista por google, nos damos cuenta lo difícil que es escoger alguno, a Spring por ejemplo se le achaca la poca documentación y el echo que sea portado de Java. Muchos tienden a usar Castle Windsor por su documentación y se podría decir que es el más popular en este momento.

Hay que recordar que utilizar un Contenedor puede provocar un poco de "overhead"en la creación de los objetos, pero esto es compensado con todas la facilidades que su uso implica.