PDF de programación - Inyección de Dependencias

Inyección de Dependenciasgráfica de visualizaciones

Publicado el 14 de Enero del 2017
1.034 visualizaciones desde el 14 de Enero del 2017
664,9 KB
4 paginas
Creado hace 13a (23/12/2010)
Inyección de Dependencias

Como colofón de la serie de cinco artículos dedicados a los principios SOLID, en esta ocasión toca hablar
del Principio de Inyección de Dependencias (Dependency Inyection, DI), abordando la problemática de
los modelos altamente acoplados y mostrando por qué este principio está tomando cada vez más
relevancia en nuestros desarrollos.

Introducción

Si nos remontamos a los primeros años de la pro-
gramación, nos encontraremos con programas rígi-
dos repletos de código monolítico y lineal. La propia
evolución hizo aparecer conceptos hoy por hoy
imprescindibles como la modularidad y la reutili-
zación de componentes, conceptos fundamentales
en el paradigma de la Programación Orientada a
Objetos.

La modularidad y reutilización de clases conlleva
un flujo de comunicación entre instancias cuyo mal
uso deriva en un hándicap que limita la flexibilidad,
robustez y reusabilidad del código debido a la depen-
dencia o alto acoplamiento entre las clases.

En la figura 1 podemos ver un sencillo diagrama
de clases de un sistema de adquisición y control de
datos meteorológicos. Existen dos clases participan-
tes: una para la captura de la temperatura, y otra que
representa a la estación meteorológica. Ambas tienen
una responsabilidad a la hora de mostrar los datos,
como puede apreciarse en el listado 1.

public class EstacioMeteorologica
{

public void MostrarDatos()
{

Console.WriteLine(

string.Format("Datos a {0} \n", DateTime.Now));

Termometro termometro = new Termometro();
termometro.MostrarTemperaturaActual();

}

}

public class Termometro
{

public int Valor { get; set; }
public void MostrarTemperaturaActual ()
{

Console.WriteLine(

string.Format("Temperatura: {0} º", Valor));

José Miguel Torres
MVP de Device Application Development

}

}

Figura 1

Listado 1

Identificando el problema

Cuando hablamos en términos de calidad, solemos utilizar
los adjetivos "bueno" o "malo" para definir la calidad de
un diseño. Sin embargo, no siempre utilizamos los argu-
mentos o criterios que sustentan la afirmación "éste es un
mal diseño". Existe un conjunto de criterios más allá del
siempre subjetivo TNTWIWHDI (That’s Not The Way I
Would Have Done It, "Yo no lo habría hecho así") acuñado
por Robert C. Martin, y son los que miden el nivel de rigidez,
la fragilidad y la inmovilidad del sistema.

En nuestro ejemplo de la estación meteorológica,
podemos afirmar que el diseño es rígido, porque cual-
quier cambio será difícil de llevar a cabo, ya que no cono-
cemos el impacto que la modificación de una clase de
bajo nivel (clase Termometro) tendrá sobre la clase de
alto nivel (clase EstacioMeteorologica).

Cuando los cambios tienen una repercusión en otras
entidades, no necesariamente dependientes, se dice que
un sistema o aplicación es frágil. Si nos fijamos en el
listado 1, la clase EstacioMeteorologica depende tanto
de Termometro como de System.Console. Un cambio
del flujo de salida de datos del programa (por ejemplo,
a una impresora en lugar de System.Console) repercu-
tiría en las clases de bajo nivel.

El término inmóvil lo utilizamos para medir el nivel de
dependencia entre una parte del diseño y otros datos no
directos. El ejemplo es inmóvil porque la clase Estacio‐
Meteorologica depende de las clases Termometro y Sys‐
tem.Console para mostrar los datos. Dicho en otras pala-
bras, no podríamos extraer la clase de mayor nivel y utilizarla
con otras entidades. Lo mismo pasaría con la clase de bajo
nivel por su dependencia de System.Console.

Entre los criterios que permiten determinar si
un diseño es bueno o malo están los que miden
su nivel de rigidez, fragilidad e inmovilidad

Planteemos un nuevo diseño a nuestro sistema. En
primer lugar, eliminemos la dependencia que la clase
Termometro tiene de System.Console, ya le que estamos
otorgando la responsabilidad de salida por pantalla cuan-
do realmente no le corresponde. El resultado sería el
que se muestra en el listado 2.

Ahora la clase Termometro ha quedado libre de
dependencias, y por tanto es reutilizable. Sin embargo,
aún EstacioMeteorologica depende tanto de
System.Console como de Termometro. Por otro lado, la
clase Termometro no es más que una representación de
un valor referencial meteorológico cualquiera; por tanto,
podríamos abstraer la interfaz IMeteoReferencia, tal y
como se muestra en el listado 3, y hacer que la clase
Termometro la implemente. Esto es un ejemplo de apli-
cación del patrón Fachada (Façade), mediante el cual
simplificamos la firma de varias clases a través de una
única interfaz.

public interface IMeteoReferencia
{

int Valor { get; set; }
string Mostrar();

}

public class EstacioMeteorologica
{

public void MostrarDatos()
{

Termometro termometro = new Termometro();
string temperatura =

termometro.MostrarTemperaturaActual();

Console.WriteLine(

string.Format("Datos a {0} \n{1}",

DateTime.Now, temperatura));

}

}

Listado 2

}

}
public class Termometro
{

public int Valor { get; set; }
public string MostrarTemperaturaActual ()
{

return string.Format("Temperatura:{0} º", Valor);

public class Termometro : IMeteoReferencia
{

public int Valor { get; set; }
public string Mostrar()
{

return string.Format("Temperatura:{0} º", Valor);

}

}

Listado 3

Ahora que hemos abstraído la interfaz, ésta nos
servirá como contrato para las clases que quieran uti-
lizarla. Esto nos permitirá desacoplar la clase Esta‐
cioMeteorologica de Termometro, tal y como muestra
el listado 4.

Sin embargo, aún no hemos solucionado el proble-
ma, pese a que estamos más cerca. Lo que pretendemos
es eliminar completamente la instanciación de la clase
Termometro, y la solución pasa por inyectar la depen-
dencia directamente a través del constructor, como se
muestra en el listado 5.

a
í
n
a
M
t
e
N
t
o
d

27

public class EstacioMeteorologica
{

private IMeteoReferencia termometro;

public EstacioMeteorologica()
{

termometro = new Termometro();

}

public void MostrarDatos()
{

Console.WriteLine(

string.Format("Datos a {0}", DateTime.Now));

Console.WriteLine(termometro.Mostrar());

}

}

Listado 4

public class EstacioMeteorologica
{

private IMeteoReferencia termometro;

public EstacioMeteorologica(

IMeteoReferencia termometro)

de la aplicación; es decir, justamente lo contrario. Además,
la clase de alto nivel sería difícilmente reusable debido a
este acoplamiento. Sencillamente, y resumiendo, la clase
EstacioMeteorologica no debe depender de la clase
Termometro; en todo caso, al contrario.

Existen tres formas de implementación de la Inyec-

ción de Dependencias:

• por constructor
• por setter
• por interfaz.

El primer caso lo hemos visto en la sección anterior,
donde hemos inyectado la dependencia a través del cons-
tructor de la clase; el listado 6 muestra una generalización.
La inyección por setter se realiza a través de una propiedad
de la clase (listado 7); y por último, la inyección por interfaz
se realiza a través de un método, recibiendo como pará-
metro el objeto a inyectar (listado 8).

{

}

this.termometro = termometro;

IMeteoReferencia referencia = ObtenerReferencia();
EstacioMeteorologica estacion =

new EstacioMeteorologica(referencia);

public void MostrarDatos()
{

Console.WriteLine(

string.Format("Datos a {0}", DateTime.Now));

Console.WriteLine(termometro.Mostrar());

}

}

Listado 5

El Principio de Inyección de Dependencias
Robert C. Martin afirma en el Principio de Inyección de
Dependencias:

A. Las clases de alto nivel no deberían depender de las
clases de bajo nivel. Ambas deberían depender de las
abstracciones.

B. Las abstracciones no deberían depender de los detalles.

Los detalles deberían depender de las abstracciones.

Imaginemos por un momento la solución inicial de
la estación meteorológica (listado 1). La clase de alto nivel
EstacioMeteorologica depende de la clase de bajo nivel
Termometro (o Barometro, Anemometro, etc.). Toda la lógica
de la solución se implementaría en la clase de alto nivel,
y cualquier modificación en las clases de bajo nivel tendría
repercusión no únicamente sobre la definición de la clase
de alto nivel, sino sobre la propia lógica de la aplicación,
llegando incluso a forzar cambios en la misma, cuando
debería ser la clase de alto nivel la que debería forzar el
cambio a las clases de bajo nivel sin comprometer la lógica

a
í
n
a
M
t
e
N
t
o
d

28

Listado 6. Inyección por constructor

EstacioMeteorologica estacion = new EstacioMeteorologica();
estacioMeteorologica.Referencia = ObtenerReferencia();

Listado 7. Inyección por setter

EstacioMeteorologica estacion = new EstacioMeteorologica();
estacioMeteorologica.LecturaContador(ObtenerReferencia());

Listado 8. Inyección por interfaz

Inversión de control y contenedores

No podemos hablar de DI sin dejar de hablar de la Inver-
sión de control (Inversion of Control, IoC). IoC también es
conocido como Principio de Hollywood, nombre derivado
de las típicas respuestas de los productores de cine a los
actores noveles: "no nos llames; nosotros lo haremos".

En escenarios de producción, las cla-
ses no son tan triviales como la que
hemos presentado en este artículo. Ima-
gine por un momento que la interfaz
IMeteoReferencia tiene una implemen-
tación de IEntradaDatos e IVerifica‐
dor, y éstas a su vez implementan otras
interfaces. En realidad, obtendremos una
jerarquía de dependencias (figura 3), cuyo
manejo en tiempo de diseño es imposi-
ble de gestionar "manualmente"; es aquí
donde entra a jugar el término contene-
dor IoC (IoC Container).

El principal cometido de un conte-
nedor IoC, a diferencia de una factoría,
es el de gestionar el ciclo de vida de los
objetos. El contenedor IoC registra una
implementación específica para cada
tipo de interfaz y retorna una instancia
de objeto. Esta resolución de objetos tie-
ne lugar en un único punto de las aplicaciones; normal-
mente, a nivel de infraestructura.

Conclusión

Con este artículo, hemos tratado de mostrar de una for-
ma práctica la relación existente entre dependencias,
det
  • Links de descarga
http://lwp-l.com/pdf223

Comentarios de: Inyección de Dependencias (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad