Cuando llevas tiempo programando y te preocupas de que tu código sea reutilizable en varios proyectos, vas consiguiendo componentes -o librerías- de cierta embergadura que puedes usar en varios proyectos. Ojo, no hablo de librerías normalitas, de componentes pequeños reutilizables, sino de módulos grandes. Normalmente estos módulos interactúan entre sí, por lo que se suelen poner interfaces para que las dependencias no sean muy fuertes.
Sin embargo, estos módulos no son independientes. Dependen unos de otros a través de sus interfaces. Si no vamos con cuidado, es fácil que para usar un módulo tengamos que traernos otros que no nos interesan, símplemente porque necesitamos sus interfaces.
Veamos todo esto con un poco más de detalle. Imagina que vamos a controlar un GPS y vamos a pintar en un mapa la posición del GPS. Si queremos hacer módulos reutilizables, podemos hacer los siguientes
- Una clase o grupo de clases que se conecta con el GPS para obtener la posición que nos vaya dando este equipo.
- Una clase o grupo de clases que hacen de MAPA. En ella pintaremos la posición que nos de el GPS.
Solo dos, que si no, nos liamos mucho…
Tenemos que comunicar estos módulos entre sí de alguna forma, para que el GPS pase las posiciones al MAPA. Podríamos, por ejemplo, aplicar un patrón observador al GPS de forma que MAPA implemente la interface ObservadorDePosicion y se suscriba a cambios de posición en el GPS.
¿Cual es el problema?. La interface del observador de Posición estará posiblemente en GPS, así que MAPA necesita el módulo GPS, sólo por la interface, aunque en otro proyecto no haya GPS. Si ponemos esta interface en MAPA, entonces GPS necesita a MAPA sólo por esa interface, aunque no haya mapa en nuestro próximo proyecto con GPS.
¿Cómo podemos evitarlo?. Usando lo que yo creo que se conoce como código pegamento -Glue Software-. La verdad es que no tengo ni idea si es eso del código pegamento. Se que existe algo que llaman código pegamento, pero nunca lo he visto "en acción", pero lo que vamos a hacer responde muy bien a esa descripción.
Para evitar la dependencia, hacemos nuestro GPS con su interface ObservadorDePosicion y su patrón observador. Al MAPA le ponemos un método tomaPosición(). Ambos módulos son totalmente independientes, ni MAPA implementa ObservadorDePosicion ni GPS ve a MAPA para nada. Para comunicarlos únicamente tenemos que hacer una clase PEGAMENTO en nuestro proyecto que reciba tanto a GPS como a MAPA. La clase PEGAMENTO se suscribe a GPS implementando su interface ObservadorDePosicion y cuando reciba una posición, llama al método tomaPoscion() de MAPA. Es más, incluso puede traducir la posición en el formato que la reciba del GPS para adaptarla al formato que necesite el MAPA.
El resultado son dos módulos, GPS y MAPA, totalmente independientes, que ni siquiera tienen que estar de acuerdo en el formato en que se pasan el dato Posición. En el proyecto se hace una clase PEGAMENTO, únicamente válida para ese proyecto y bastante sencilla de hacer.
Imagina ahora un proyecto más grande, con varios módulos. Pueden hacerse los módulos totalmente independientes entre ellos y perfectamente reutilizables en cualquier otro proyecto ellos solos. Dentro del proyecto, cada asociación entre dos módulos se establecería haciendo una clase PEGAMENTO. Habría tantas clases PEGAMENTO como asociaciones entre módulos.
Lo más divertido sería el main(), que quedaría algo parecido a esto.
Modulo1 m1 = new Modulo1();
Modulo2 m2 = new Modulo2();
Modulo3 m3 = new Modulo3();
…
Pegamento1Con2 p12 = new Pegamento1Con2(m1,m2);
Pegamento1Con3 p13 = new Pegamento1Con3(m1,m3);
Pegamento2Con3 p23 = new Pegamento2Con3(m2,m3);
…
En fin, todo ventajas. Módulos completamente independientes que se pueden desarrollar por separado, de forma aislada, probar aislados e incluso instanciar sueltos. Un montón de clases Pegamento que representan claramente una asociación. Casi, casi es como coger un diagrama UML y por cada paquete/módulo hacer una librería y por cada línea de asociación una clase Pegamento.
Obviamente, esto tan "complejo", vale para módulos de cierto nivel. Si vamos a hacer una librería matemática, no vamos a andar poniendo un ObservadorResultadoOperacionSeno …