Inyección de funcionalidad (II)

Si has visto los post anteriores, habrás notado que uno de los principales problemas que remaqué sobre algunos patrones y su aplicación, y en especial en lenguajes con lazos por tipos de datos, era que la infraestructura para realizar determinadas acciones era mucho más cara que la solución.

Por otro lado, los lenguajes dinámicos nos permiten quitarnos esos costos, o por lo menos, pensar la solución de otra forma.

Imaginemos que tenemos una clase, con una función:

public class MyClass
{
    public void Show(string message)
    {
        Console.WriteLine(message);
    }
}

Luego, creamos una instancia de esta clase y ejecutamos dicha función:

var o = new MyClass();
o.Show(“Hello World”);

Luego nos piden que debemos agregar información de depuración, de tal forma que al momento de realizar la llamada a la función Show, primero realice determinado comportamiento (No viene al caso) y recién luego, haga lo que la función Show original debía hacer. Si esto te parece simple, la condición es que NO PUEDES modificar el código de la clase MyClass. Ahora seguramente no te parece tan simple.

Aquí es donde uno podría pensar una gran estructura para solucionar este problema, nuevas clases, interfaces, patrones varios. Pero, el costo es más grande que la solución.

Que pasa con un lenguaje como Javascript (Nuestro lenguaje de juguete). Repliquemos lo anterior:

function MyClass() {
    this.show = function(message) {
        console.log(message);
    };
}

var o = new MyClass();
o.show(“Hello World”);

El resultado, hasta este punto es el mismo. Pero la idea sigue en el aire. En definitiva, necesitamos inyectar funcionalidad. Meternos en medio de las llamadas y hacer que se ejecute, primero, lo que necesitamos.

var oldShow = o.show;

o.show = function(message) {
    console.log(“Log information!”);
    oldShow(message);
};

Lo que hacemos, para este caso, es tomar la referencia a la función original del objeto y la remplazamos por nuestra definición. Nuestra función realiza las acciones que necesite, como en este caso, mostrar un mensaje adicional, y luego, delega el mando a la función original.

image

El desarrollador no notará la diferencia, pero nosotros hemos podido inyectar nueva funcionalidad sin modificar el flujo esperado.

El punto a favor de esto es que podemos dar de baja o alta funcionalidad bajo demanda. Por ejemplo, un paquete de funcionalidades de depuración que solo está activo cuando depuramos, pero simplemente no existe cuando implementamos en su destino final.

Posiblemente sobre esto último puedas pensar que para esto existen directivas de pre procesador, o condicionantes al momento de compilar. Y es, bajo cierto punto de vista, una forma de solucionarlo, pero hay que tener en cuenta que nuevamente el costo de la infraestructura será superior al beneficio, ya que en un punto necesitaremos escribir directamente sobre las clases, mientras que bajo el modelo de un lenguaje como Javascript, siempre, se puede hacer desde fuera del módulo a ser intervenido. O sea, no será necesario hacer ninguna línea de código ya que los objetos pueden ser inspeccionados e intervenidos desde el que intenta modificarlos.



Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s