Modelos dinýmicos.
miércoles, febrero 8, 2006 at 1:00AM Modelos dinámicos.
Fecha de creación: 15.12.2005
Revisión 1.0.1 (15.12.2005)
Alberto Molpeceres
alberto DOT molpeceres AT linkingpaths DOT com
|
Este trabajo se ha publicado también en Sólo Programadores nº 134. Febrero 2006.
Introducción
Estamos acostumbrados a realizar nuestras aplicaciones sobre la base de modelos de objetos representativos. Si estamos realizando una aplicación de gestión para una empresa de alquiler de coches lo más normal es que estemos manejando una clase llamada Coche, otra Cliente, otra Alquiler, etc. ¿Qué problema hay con ello?. Obviamente ninguno.
¿Pero qué sucede si en lugar de realizar una aplicación para una empresa concreta queremos realizar un producto para todas las empresas de alquiler de coches?. Podemos pensar que todas las empresas trabajan de forma similar, con el mismo modelo de objetos, con los mismos atributos. O podemos pensar que si no lo hacen, deberían hacerlo, y que son ellos los que deben adaptarse a nuestro modelo si quieren utilizar la aplicación. Aunque es muy probable que al final optemos por adaptar la aplicación para cada una de las empresas, añadiendo atributos a nuestro modelo, modificando la interfaz de usuario para añadir estos atributos, etc.
¿Todo bien?. Quizás. Si trabajamos explotando al máximo las posibilidades de nuestro sistema de gestión de versiones concurrentes, posiblemente no tengamos demasiados problemas. Pero si no lo hacemos... ¿qué ocurre si hemos detectado un fallo en nuestro sistema de persistencia y tenemos que corregir la aplicación de todos nuestros clientes?. ¿O si queremos añadir un nuevo atributo a nuestra clase Coche para almacenar si el coche tiene limitador de velocidad?. Tendremos que modificar la clase Coche de cada una de nuestras versiones, modificar la base de datos, la interface de usuario, etc.
Se empieza a complicar, ¿no?. ¿Y si pudiéramos tener un código genérico para la persistencia y la interface de usuario que se adaptase automáticamente al modelo de nuestra aplicación?. ¿No sería genial?. Podríamos ofrecer a todos y cada uno de nuestros clientes un modelo de datos totalmente personalizado a sus necesidades sin tener que crear versiones especiales de partes comunes como son la persistencia y la interface de usuario.
¿Interesado?. Pues todo esto es posible gracias a los modelos dinámicos de objetos.
La teoría.
Pero todo esto no es nuevo, aunque pueda parecerlo. Uno de los primeros documentos escritos disponibles en la red es el Dynamic Object Models [1] de Ralph Johnson, uno de los miembros de The Gang of Four [2]. El concepto entero de los modelos dinámicos se basa en la existencia de dos tipos de clases: la de datos, con la información que nos interesa, y la de metadatos, que definen la estructura de dichos datos.

El objeto entity es el que representa nuestro objeto, que tendrá una definición de los campos que contiene a través del EntityType, parte de los metadatos. Estos EntityType tendrán definidos los campos del objeto en forma de distintos PropertyType, también parte de los metadatos. La relación que nos queda sería la de Entity-Property-PropertyType, que indica a que propiedad corresponde cada uno de los valores que almacena nuestro Entity.
Estas clases son siempre iguales, lo que cambiará serán sus valores, que determinarán si estamos hablando de un coche con siete propiedades o de un usuario con tres propiedades completamente distintas.
Por ejemplo:
Nuestro VW Golf (instancia de Entity), estará relacionado con la definición de un "coche" (instancia de EntityType). El coche podrá almacenar varias propiedades, como son "marca" y "modelo" (instancias de PropertyType). Nuestro VW Golf tendrá finalmente dos valores, "Volkswagen" y "Golf TDI" (instancias de Property) que están relacionadas respectivamente con las instancias de "marca" y "modelo" que hemos declarado antes.
Si mañana añadimos una nueva propiedad, como pueda ser "cilindrada", no tendremos que tocar esas clases, sólo la definición de nuestro EntityType (que normalmente se hará en un fichero externo). ¿Y si queremos usar nuestro código de altas-bajas-modificaciones para manipular libros en lugar de coches?. Lo mismo, sólo tendremos que cambiar la definición de los EntityType (y sus PropertyType) en un fichero externo, sin tocar el código de nuestra aplicación en lo que al modelo se refiere.
Posibles implementaciones.
Una vez has llegado aquí, es de imaginar que lo siguiente que querrás saber es como utilizar esta idea en tus aplicaciones, ¿no?. Veámos dos posibles aplicaciones de este concepto que nos ocupa, con dos tecnologías que estamos acostumbrados a utilizar de forma cotidiana: XML y sistemas de gestión de bases de datos relacionales (SGBDR), aunque hay muchas otras formas de interpretarlo.
XML.
Aunque el uso más común que le damos al XML es el de ficheros de configuración y el de formato de importación y exportación (lo que podría incluir a los servicios web si consideramos la idea de forma amplia), otro posible uso del XML sería el de representar modelos dinámicos de objetos. A fin de cuentas, al trabajar con árboles DOM, tenemos un objeto Node que representa a la raíz, y podremos añadirle atributos y componerlo con otros nodos sin tener que cambiar nada de la implementación. ¿Y cuales son los metadatos?. Respuesta sencilla: la DTD o el XMLSchema que lo definen. Utilizando un árbol XML (o porción de él) en nuestra aplicación podemos añadir nodos hijos o atributos de forma muy sencilla, sin tener que cambiar el nuestro código genérico.
¿Problemas?. Bueno, es posible que la DTD o el Schema no sean suficientemente potentes para hacer algunas tareas, pero nada que no podamos extender fácilmente en el propio XML por medio de atributos, o bien creando otro XML que defina en mayor profundidad esos metadatos, como por ejemplo para indicar si un campo es visible o no para un determinado rol. Todas las opciones tienen un coste.
SGBDR.
Pero sin duda alguna, la mayor fuente y destino de los datos que manejan nuestras aplicaciones son los SGBDR, de modo que veremos como aplicar a estas fuentes de datos el concepto de los modelos dinámicos. A día de hoy existen distintos proyectos libres desarrollados en Java para cumplir manipular modelos dinámicos desde SGBDR, de modo que no tendremos que reinventar nada.
Existen tres proyectos principalmente:
Object RElational Ooze (OREO) [4]. Aunque es el primer framework que desarrolló esta idea (1999), se puede decir que OREO esta prácticamente abandonado. Quizás debido a su ambición, que trataba de acceder de forma transparente a distintas fuentes de datos (SGBD, LDAP, ficheros XML o planos, etc) al estilo de los Service Data Objects (SDO, JSR XXX [3]) que ahora promueven BEA Systems e IBM. En todo caso, es un framework más que estable, que entre otros ha sido usado en los últimos cuatro años (y en estos momento sigue usando) por el portal javaHispano[8].
Entity Engine de OpenForBusiness (EE) [5]. El proyecto OpenForBusiness trataba de crear una plataforma web para comercio electrónico que se pudiera adaptar a todo tipo de negocio en base a configuración. El proyecto definía una serie de módulos (escaparate de productos, carrito de la compra, noticias, etc.) que se podían adaptar a los distintos modelos de datos a través de su motor de persistencia, el llamado Entity Engine, de forma muy similar a la propuesta del proyecto Canyamo[2].
LicurgoSQL [6]. Licurgo nace como una implementación del mencionado JSR XXXX, Service Data Objects[3]. De creadores hispanos y albergado en javaHispano.net[7], nace con la idea de superar algunas limitaciones del mencionado OREO y nos permite, entre muchas otras cosas, la configuración automática de la mayor parte de nuestros metadatos directamente desde el SGBDR. Aunque la implementación de SDO aún no está disponible, la parte de acceso a SGBDR es totalmente funcional y ya utilizada en distintos proyectos.
Modelos dinámicos en Licurgo.
En Licurgo los metadatos de nuestro modelo se basan en primera instancia en un documento XML que los describe. En este XML podemos definir cada objeto de nuestro modelo por completo, si bien lo más cómodo para nosotros será que coja toda la información posible de la base de datos directamente.
Aunque sólo veremos las posibilidades de Licurgo relevantes para nuestro ejemplo (no veremos como realizar consultas en sus diversas posibilidades, relaciones, transacciones, etc.), vamos a ver un ejemplo de tratamiento automático de una tabla (simplificada) en la que recogemos los coches de una empresa de alquiler:
create table coches (
id int(11) not null,
matricula varchar(10) not null,
marca varchar(50) not null,
modelo varchar(50) not null,
primary key (id)
);
El descriptor XML para acceder a esa tabla tendría la siguiente forma:
<dataobjects>
<dataobject name="coches"
datasource="mibasededatos"
primary-key="id"
>
</dataobject>
</dataobjects>
Sencillo y autoexplicativo. En la base de datos mibasededatos (queda fuera del alcance de este artículo la definición de la base de datos, consultad la página del proyecto[6]), tenemos una tabla coches, cuya clave primaria es id. El resto de la meta información (campos, tipos, tamaños máximos, etc.) se configurará automáticamente desde la base de datos.
Para crear un objeto, popular sus valores y guardarlo en la base de datos nuestro código sería:
DataSource ds = datasourceRegistry.get("midatasource");
DataObject dao = ds.createObject("coches");
dao.set("marca", "Volkswagen");
//resto de campos...
ds.save(dao);
Si este código lo abstrajéramos, para recoger todos los parámetros que nos llegan y modificásemos nuestro objeto en función de los mismos tras comprobar que existe una propiedad con dicho nombre, tendríamos:
public void setValues(DataObject dao, Map parametros){
//recogemos el "EntityType" de nuestro dao
Type type = dao.getType();
Iterator i = parametros.keySet().iterator();
while (i.hasNext()){
String key = (String)i.next();
//comprobamos que la propiedad actual existe,
//y en su caso fijamos el valor
if (type.getProperty(key) != null){
dao.set(key, parámetros.get(key));
}
}
}
Como veis, de esta forma, nos daría igual hablar de coches que de noticias o perfiles de usuario. Nos daría igual añadir o eliminar un atributo de la tabla en la base de datos, nuestro código seguiría funcionando. De esta forma, escribiendo acciones genéricas en nuestro framework favorito (Struts, Spring o Swing por citar algunos) e indicándoles el objeto que queremos tratar (coches en este ejemplo), podremos realizar operaciones de CRUD (altas-bajas-modificaciones-y-consultas en cristiano) sobre cualquier tipo de modelo o aplicación con el mismo código.
¿Limitaciones?.
Las dos herramientas que hemos comentado se centran sobre todo en la adaptación del modelo a las necesidades de la aplicación. En su forma básica no entran, al menos no de momento, en la generación de la interface de usuario. Para tener una aplicación totalmente configurable y adaptable deberíamos realizar nosotros mismos la lógica necesaria para la generación de esa interface de usuario a partir de nuestro modelo.
No es un trabajo demasiado grande, aunque nos puede obligar a crear nueva metainformación de nuestro modelo para obtener resultados satisfactorios (por ejemplo que campos son visibles para un rol determinado). En el caso de generar una aplicación web a partir de un modelo en XML puede ser tan sencillo como escribir una o varias hojas de estilo XSL, pero en el caso de generar una aplicación Swing puede requerir inicialmente algo más de nuestra parte.
Conclusiones.
Como podemos ver, los modelos dinámicos de objetos pueden ofrecernos una flexiblidad extrema a la hora de crear nuestras aplicaciones. Así pues, los deberíamos utilizar cuando queramos aprovecharnos de esta flexibilidad, como por ejemplo en el caso de modelos muy cambiantes, ya sea por tener que adaptarlo o por la propia naturaleza del dominio de la aplicación en cuestión.
Pero esta flexibilidad viene a un precio, de modo que tendremos que valorar cuando nos compensa. Y no nos referimos a términos de rendimiento, ya que no nos supondrá una penalización apreciable salvo en entornos muy concretos, pero si puede hacer que nuestra aplicación sea menos legible al tratar con objetos y métodos genéricos en muchos casos.
¿Modelos dinámicos?: tu decides.
Referencias
- [1] Dynamic Object Models, Ralph Johson 1995. http://st-www.cs.uiuc.edu/users/johnson/DOM.html
- [2] Web de Canyamo. http://www.canyamo.org
- [3] JSR 235: Service Data Objects. http://www.jcp.org?jsr=235
- [4] Página del proyecto OREO. http://sourceforge.net/projects/oreo
- [5] Web de OpenForBusiness. http://www.ofbiz.org
- [6] Web de LicurgoSQL. http://licurgo.sourceforge.net
- [7] javaHispano.net. http://www.javahispano.net
- [8] javaHispano.org. http://www.javahispano.org
|
j2ee 

Reader Comments