Patrones de diseño: Inyección de dependencias.

¡Bienvenidos un día más a un nuevo rootie queridos amigos! Hoy vamos a hablar sobre la Inyección de Dependencias, pero primero me gustaría disculparme con nuestros lectores… ¡si con los 17 que nos leéis asiduamente! Quiero pedir perdón, por mi ausencia la semana pasada, ya que por causas de fuerza mayor, me he visto alejado del teclado, pero no os preocupéis, ¡he vuelto!

Inyección de dependencias, ¿Ezo qué eh lo que eh!?

Para los que cuando digo inyección de dependencias, sacáis la cartilla de vacunación, bienvenidos al siglo XXI, pasad, poneros cómodos y atended.

Antes de explicar que es esto de lo que hablamos, hemos de entender que una dependencia es cualquier objeto necesario para que una clase funcione.

inyeccion de dependencias
No es ni este tipo de Dependiente, ni las inyecciones que se gasta

La inyección de dependencias (o Dependency Injection en inglés) es un (muy útilpatrón de diseño en el que pasaremos objetos a la clase en vez de instanciarlos en la misma. Esto nos permite realizar un acoplamiento débil entre diferentes elementos de nuestro código.

Ventajas:

  • Reducción de dependencias: Por muy redundante que suene, es asī, ya que un componente es vulnerable a los cambios en sus dependencias. Por ejemplo si cambia la firma de método de una dependencia, el componente tendrá que cambiar esa llamada.
  • Código más reutilizable: Reducir el numero de dependencias, normalmente hacen que el código pueda ser usado más fácilmente en otro contexto. Si se necesita una implementación diferente nuestro código puede ser configurado para trabajar con la nueva implementación.
  • Test mas sencillos: El hecho de poder inyectar objetos en nuestras clases las hace mucho mas testeables. A través de la inyección de dependencias podemos pasar Mocks (Imitaciones de objetos) de las diferentes implementaciones. El comportamiento del mock puede ser configurado, lo que nos permitirá probar correctamente todos los escenarios. De ello hablaremos más en el futuro en los post dedicados a Testing.
  • Más fácil de leer: Es mucho más fácil identificar las dependencias del componente, ya que estas suelen encontrarse en el constructor.

¡Bonus track de ventajas! Arrastre de dependencias.

Este último punto es un agregado a las ventajas mencionadas, pero en el que me voy a explayar un poquito más.

Esta ventajas es la disminución del arrastre de dependencias. Esto quiere decir que no hace falta el tener que pasar objetos que no son necesarios en la llamada a otros objetos.

El problema:

Imaginemos que una clase Foo, al instanciarse crea un objeto, Configuración, que necesitaremos solo en ciertos objetos del sistema. Imaginemos ahora que nuestra clase FOO llama a las clases Bar esta llama a la clase Baz y esta última insantancia Yikes. De todos estos objetos solo Yikes necesita del uso de Configuración. Para representarlo de una forma sencilla, miremos el siguiente esquema

Las flechas representan llamadas de métodos. Como podemos ver todas las llamadas han de incluir la configuracion, pero Bar y Baz no necesitan la configuración, simplemente la estan “pasando” hasta Yikes que es dependiente de la misma.

Soluciones:

Una solución sería definir Configuración como un singleton estático (¡NOOOOOOOOOOOOOOO!), no voy a detallar todos los problemas de esta idea porque solo hablar de Singleton me salen sarpullidos, si googleais 5 segundos veréis porque. La otra es, si lo habéis adivinado, Inyección de dependencias. Pero con una pequeña diferencia, tendremos que usar un Contenedor de Inyección de Dependencias. Este contenedor tiene conciencia de todos los objetos, con lo cual puede conectar rapidamente los objetos con sus dependencias, esquematicamente quedaría así:

¡Noooooooooo! Singleton es el demoño

Implentación de Inyección de dependencias.

Una vez visto que es y las ventajas que nos ofrece este patron, veamos un pequeño ejemplo de como sería una implementación, con y sin inyección de depenencias.

Imaginemos que tenemos una clase Rooter que necesita de la clase Café, sin DI, sería así:

Como podemos ver, con este planteamiento, estamos haciendo que nuestro Rooter, solo pueda beber cafe para energizarse. También sucede que se produce un acoplamiento estrecho (tight coupling) lo que hace este código muy poco flexible.

inyección-dependencias-cafe
El día a día del rooter

¡Usando la DI!

Veamos la opción usando la inyección (¡pero no el Contenedor!)

Este segundo ejemplo podemos ver que hemos creado una Interface para las bebidas y que la hemos implementado a la clase Café. Una vez hecho esto, haciendo que el constructor solo acepte la interfaz hemos flexibilizado el código. Ademas hemos liberado a la clase Rooter de tener que crear sus propias dependencias. En este punto podríamos cambiar perfectamente la dependencia de la clase Rooter por cualquier otra que implemente BebidaInterfaz.

Uso de DI y conclusiones.

Hoy en día la gran mayoría de frameworks hacen uso de la inyección de dependencias, porque es sin duda un patrón que nos ofrece mucho. También hay que mencionar que el uso de la DI el Contenedor tiene un efecto negativo en el rendimiento, ya que aumenta los tiempos de carga, pero personalmente creo que es algo que merece la pena.

Y con esto queridos rooters nos despedimos por hoy. espero que el post de hoy os sea de ayuda, si no para implementar vuestra propia DI, para identificar cuando la estáis usando y las ventajas que esta técnica tiene.

Como siempre para cualquier duda, pregunta, comentario, soborno o amenaza, podéis usar los comentarios o en nuestras redes sociales Facebook y Twitter.

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *