Algo sobre acoplamiento

Hoy tengo ganas de hablar un poco sobre acoplamiento. El acoplamiento está relacionado con la dependencia entre las clases. Mide cuánto una clase conoce otra. El alto acoplamiento suele ser malo porque un cambio en la clase A, impactará en la clase B.

Pero siempre es mejor ver un ejemplo (C#):

public class Procesador
{
	public void Procesar(object pedido)
	{
		Console.WriteLine("Procesando " + pedido);

                // Hacer cosas

                Console.WriteLine("Fin procesado " + pedido);
	}
}

(...)
// Uso
Procesador procesador = new Procesador();
procesador.Procesar("Un pedido");
(...)

El ejemplo tiene una especie de loggeo de actividad al principio y al final del método. El problema de esta implementación es que si la WriteLine cambia (o si necesitamos imprimir de otra forma el fin de línea) debemos modificar nuestra clase Procesador aunque en realidad su funcionalidad no se haya modificado. Esto también atenta contra el principio Single Responsability.

La solución típica es no depender de la clase Console sino de una interfaz. Propongo lo siguiente:

public class Procesador
{
	public Loggeador Log { get; set; }

	public Procesador(Loggeador log)
	{
		this.Log = log;
	}

	public void Procesar(object pedido)
	{
		this.Log.Loggear("Procesando " + pedido);

                // Hacer cosas

                this.Log.Loggear("Fin procesado " + pedido);
	}
}

public interface Loggeador
{
	void Loggear(string mensaje);
}

public class LoggeadorAConsola : Loggeador
{
	public void Loggear(string mensaje)
	{
		Console.WriteLine(mensaje);
	}
}

(...)
// Uso
Procesador procesador = new Procesador(new LoggeadorAConsola());
procesador.Procesar("Un pedido");
(...)

Sí, ya sé. Un montón de código.

¿Qué hice?
Definí una interfaz Loggeador y la implementé con LoggeadorAConsola. Una clase bobísima. Tiene solo un método que pasa a la Consola que le llega por parámetro.
También cambié Procesador para que dependa de esta interfaz y no use más a la consola.

¿Qué gané?
¡Me dijiste que depender no estaba bueno y ahora dependes de Loggeador!
Sí, pero mirá que dependo de una interfaz, es decir, de nada concreto. Ahora si a la gente de Microsoft le parece una buena idea hacer obsoleta esa clase, yo cambio LoggeadorAConsola y la clase Procesador ni se entera.

public class LoggeadorAConsola : Loggeador
{
	public void Loggear(string mensaje)
	{
		//Console.WriteLine(mensaje);
		Console2.WriteLine(mensaje);
	}
}

Pero pará. ¿Quién va a cambiar Console.WriteLine? Es muy tirado de los pelos.
Sí, lo es. Pero es para ilustrar. Además tiene otra ventaja:

Si yo ahora decido que estaría bueno loggear en HTML el \n no me sirve y tengo que usar un <br />; implemento un LoggeadorConBr, se lo setteo al Procesador y fin del problema. Es lo mismo para escribir a un archivo o incluso para escribir en muchos outputs. Te dejo la implementación a vos XD.

Otra gran ventaja, y para mí la más importante, es que Procesador es más testeable. Antes no había manera, por lo menos trivial y automática, de probar que el mensaje se estaba loggeando. Ahora puedo usar un Mock para verificar que se llame y verificar que los parámetros sean los correctos.

¡Saludos!

One thought on “Algo sobre acoplamiento

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>