MOTORES DE PERSISTENCIA. VERSION PARA IMPRIMIR. (Versión original en http://espanol.aurumsol.com/articulos/art3/art3-1.html) Dr. Vicent-Ramon Palasí Lallana. Gerente General de Aurum Solutions. http://www.aurumsol.com Agosto 2003 Es generalmente sabido que una aplicación informática consta de dos componentes principales que colaboran para llevar a cabo la funcionalidad que el usuario desea. El primero de estos componentes es la base de datos, que guarda la información necesaria para operar la aplicación, en forma de datos en disco. El segundo de estos componentes es el programa propiamente dicho, que recupera esos datos de la base de datos, realiza los cálculos necesarios y presenta los resultados deseados al usuario. Figura 1. Arquitectura de una aplicación informática Para que estos dos componentes puedan funcionar juntos deben poder comunicarse intercambiando datos, como se observa en la figura 1. En otras palabras, deben ser compatibles. Sin embargo, durante los últimos treinta años la evolución de estos dos componentes ha sido divergente, de forma que cada vez se ha hecho más difícil que colaboren en una misma aplicación. Así, desde los años 70 a la actualidad, las bases de datos utilizan un modelo teórico llamado “relacional”, que se ha convertido en un estándar y que es utilizado en la práctica totalidad de aplicaciones de software. En cambio, los programas han usado, desde los años 80, un modelo llamado “orientado a objetos”, que difiere en mucho del modelo relacional y que se ha extendido cada vez más. Es por ello que aparece un conflicto a la hora de reunir estos dos componentes en una aplicación, ya que cada uno responde a diferente modelo y forma de operar. Cada componente maneja los datos con un formato diferente. Metafóricamente, podríamos afirmar que el programa y la base de datos hablan idiomas diferentes y, por lo tanto, la comunicación entre ellos resulta difícil. Este artículo comienza con una descripción de los dos modelos mencionados y de las diferencias que dificultan su combinación en una sola aplicación. A continuación, se exploran las diferentes soluciones a este problema y se acaba concluyendo que la mejor manera de resolverlo es usando un motor de persistencia. El artículo finaliza indicando los nombres de los motores de persistencia más usados, con el fin de que el lector pueda elegir el que más se adapta a sus necesidades. 1. MODELO ORIENTADO A OBJETOS. El modelo orientado a objetos es el modelo teórico que usa la mayoría de los programas actuales. La programación orientada a objetos hunde sus raíces en los años sesenta (en los que aparecieron los primeros lenguajes de este tipo, llamados “Simula I” y “Simula 67”, desarrollados en el Centro Noruego de Computación, en Oslo). En los primeros 70, aparece “Smalltalk”, un lenguaje fundamental en la historia de la orientación a objetos. Sin embargo, no es hasta la segunda mitad de los años 80 cuando la orientación de objetos se generaliza, convirtiéndose en el estándar predominante en los años 90, de la mano de lenguajes como C++ y Java. El triunfo de la programación orientada a objetos ha sido impulsado por la enorme difusión de otras tecnologías (como la interfaz gráfica o las arquitecturas distribuidas) que son más fáciles de implementar mediante este tipo de desarrollo que mediante una programación tradicional. Hoy en día, la práctica totalidad de los lenguajes de programación que surgen son orientados a objetos y esta tecnología se ha convertido en el estándar actual de programación que, a su vez, está generando nuevos desarrollos muy prometedores para el futuro (como, por ejemplo, la programación orientada a aspectos). La idea de la orientación a objetos es modelar los programas de una forma parecida a cómo percibimos la realidad. Para la mente humana, el universo está compuesto por una serie de “objetos” (en el sentido más amplio de la palabra, incluyendo seres vivos, ideas, etc.). Cada objeto tiene unas características que lo diferencian de los demás y, con cada objeto, se pueden realizar unas acciones que son propias y específicas del mismo. Así, por ejemplo, un determinado auto tiene unas características (color rojo, caja de cambios automática, diesel, etc.) y puede realizar unas determinadas acciones (acelerar, frenar, etc.). La programación orientada a objetos intenta modelar estos objetos reales con estructuras de programa, llamadas “objetos de software” o, simplemente, “objetos”. Cada uno de estos objetos de software, está compuesto por una serie de características (llamadas “atributos”) y una serie de acciones (llamadas “métodos”), al igual que un objeto de la vida real. Una representación gráfica de un objeto de software se muestra en la figura 2. Figura 2. Representación gráfica de un objeto de software La forma de programar estos objetos de software es similar a la forma en la que se comportan los objetos en la realidad. Así, por ejemplo, en la vida real un auto contiene piezas. Análogamente, en el programa, un objeto de software “Auto” contiene objetos “Pieza”, como podemos observar en la figura 3. Figura 3. El objeto "Auto" incluye objetos "Pieza" Es importante remarcar que el modelo orientado a objetos es un modelo que incluye tanto la parte estática de un objeto (los “atributos” del mismo, es decir, sus características) como su parte dinámica (los “métodos”, es decir, sus acciones). Usando una terminología bien conocida en desarrollo, incluye tanto los “datos” como los “procesos”. En resumen, la programación orientada a objetos se basa en la realidad. Su mayor ventaja es que simplifica el mantenimiento de los programas y hace posible programar y mantener hasta los programas más enormes al dividirlos en partes más pequeñas, es decir, en objetos. Como consecuencia, produce reducciones de costos y mayor calidad del código y se ha convertido en el estándar actual de programación. 2. MODELO RELACIONAL. Muy ajeno a la revolución que supuso la orientación a objetos, el área de las bases de datos sigue fiel a un modelo antiguo pero que ha probado su eficacia, el llamado “modelo relacional”. El modelo relacional se basa en un artículo publicado por E.F.Codd en 1970. Las primeras bases de datos relacionales comerciales aparecen en la segunda mitad de los años setenta. Desde entonces, el modelo relacional se convierte en un estándar prácticamente universal para el acceso a datos, dominando totalmente el área de las bases de datos hasta la actualidad. El modelo relacional es muy diferente del modelo orientado a objetos. Por una parte, el modelo relacional sólo se ocupa de la parte estática de la aplicación (de los “datos”) y no de la parte dinámica (“los procesos”). Usando el ejemplo anterior, en el modelo relacional, sólo me interesan las características del auto (su color, su tipo de caja de cambios, etc) y no las acciones que puedo hacer con él (acelerar, frenar, etc.) . Este énfasis en los datos es lógico en un modelo cuyo objetivo es modelar la parte estática de la aplicación, es decir, la base de datos. Hay otras diferencias entre los dos modelos. Por ejemplo, la forma en la que el modelo relacional trata los datos es muy diferente a cómo lo hace el modelo orientado a objetos. Mientras en este último, los datos son modelados en forma de objetos, en el modelo relacional son modelados como registros, los cuales son una serie de datos pertenecientes a una misma entidad de la vida real. Un registro difiere de un objeto en que sólo modela datos y que éstos no tienen estructura. La representación gráfica de un registro aparece en la figura 4. Figura 4. Representación gráfica de un registro de datos Los registros similares se agrupan en tablas. Podemos imaginarnos las tablas como listados de datos parecidos a los listados de impresión que hay en las empresas (de empleados, de facturas, etc.). En esta comparación, cada registro sería una línea del listado. Usando el ejemplo anterior, cada registro contendría los datos de un determinado auto (color rojo, caja de cambios automática, diesel, etc.) y las tablas no serían más que listas de autos con todos sus datos, como se observa en la figura 5. Figura 5. Los registros de las piezas están separados de los registros del auto El modelo relacional no refleja la estructura de la realidad. Como hemos dicho, si un auto contiene piezas, un objeto de software “Auto” contiene objetos “Pieza”. Sin embargo, en el modelo relacional, los registros de los autos y piezas están por separado (esto se muestra en la figura 5) y se relacionan por un mecanismo implícito llamado “clave foránea”. El programador debe saber que hay una relación entre los autos y las piezas y debe programar de acuerdo a ello. Sin embargo, el modelo no refleja explícitamente esta relación y, en general, la estructura de la realidad, al contrario del modelo orientado a objetos. 3. APLICACIONES TRADICIONALES. Como conclusión de lo que se ha dicho hasta ahora, una aplicación está formada por un programa y una base de datos que se comunican entre sí. El programa suele estar diseñado según el modelo orientado a objetos y, por lo tanto, trabaja con datos en formato de objetos. Por el contrario, la base de datos está diseñada según el modelo relacional y, por lo tanto, trabaja con datos en formato de registros. Esto introduce una dificultad importante, porque los dos formatos de datos (objetos y registros) son incompatibles entre sí. Así, cuando el programa quiere guardar o recuperar los datos en disco (para que no se pierdan entre ejecuciones), lo hace n forma de objetos, pues es el formato de datos que conoce. Sin embargo, la base de datos no puede guardar o recuperar objetos, pues está diseñada para guardar o recuperar registros (y no objetos), que es el formato de datos que ella reconoce. Esto se muestra en la figura 6. Resumiendo, los formatos de datos que utilizan el programa y la base de datos son incompatibles entre sí. Podemos decir que el programa y la aplicación hablan “idiomas diferentes” y, por lo tanto, debemos encontrar una solución para que se comuniquen. Figura 6. El programa y la base de datos usan diferentes formatos de datos La solución más obvia a este problema es hacer que uno de los componentes hable el idioma del otro. Es decir, que un componente use el formato de datos del otro. Así, la primera opción que examinamos en este artículo es la de que el programa esté diseñado para tratar con datos relacionales, la cual se refleja en la figura 7. En esta opción, tanto el programa como la base de datos hablan un mismo idioma: el relacional y utilizan como formato de datos el de registro. Por lo tanto, la comunicación es posible. Figura 7. Arquitectura de una aplicación tradicional Ésta era la forma de programar universalmente adoptada antes de la aparición de la orientación a objetos y sigue siendo la arquitectura dominante en El Salvador. Aún entre las empresas que utilizan lenguajes orientados a objetos, la mayoría programa sin tener en cuenta la orientación a objetos a la hora de usar los datos, los cuales se gestionan de forma relacional. El problema de esta arquitectura es que se desaprovechan las grandes ventajas de flexibilidad, facilidad de mantenimiento y facilidad de gestión de sistemas complejos que da la programación orientada a objetos. Asimismo, el código que opera con datos relacionales suele ser complejo, difícil de mantener y de ampliar y muy dependiente de la estructura de los datos. 4. BASES DE DATOS ORIENTADAS A OBJETOS. Como hemos visto en el apartado anterior, la opción consistente en que toda la aplicación use un mismo modelo teórico relacional no es la más adecuada. Examinemos ahora la opción en que toda la aplicación tenga un único modelo teórico, pero que éste sea el de orientación a objetos. Esta opción, que se refleja en la figura 8, implica que el formato de datos que usa toda la aplicación es el formato de objetos. Figura 8. Arquitectura de una aplicación con base de datos orientada a objetos Para un programa resulta natural trabajar con objetos. Sin embargo, esto es imposible para las bases de datos tradicionales, basadas en el modelo relacional. Para resolver este problema han aparecido las bases de datos orientadas a objetos. Al contrario de sus homólogas relacionales, que trabajan con registros, las bases de datos orientadas a objetos guardan y recuperan objetos. Por lo tanto, la comunicación de este tipo de base de datos con un programa orientado a objetos es posible. Aunque, sobre el papel, ésta es la mejor opción para implementar una aplicación de base de datos, en la práctica presenta una serie de problemas importantes, debido a las características actuales de las bases de datos orientadas a objetos. Éstas no están tan maduras como sus homólogas relacionales y, por lo tanto, no gozan de la abundancia de herramientas, la fiabilidad, facilidad de administración y rendimiento de estas últimas. Lo que es peor, las bases de datos orientadas a objetos frecuentemente son incompatibles entre ellas. Esto hace imposible migrar una aplicación desde una base de datos orientada a objetos a otra, lo que nos obliga a depender de un único proveedor (fenómeno conocido como “vendor lock-in”), con todas las incoveniencias que esto supone (obligación de aceptar los aumentos de precio del proveedor, falta de soporte si el proveedor sale del mercado, etc.). Como conclusión, aunque ésta pueda ser la opción preferible en un futuro, en el que las bases de datos orientadas a objetos alcancen una madurez y estandarización suficientes, en el presente resulta arriesgado aplicarla. 5. MOTORES DE PERSISTENCIA. Hemos visto que las opciones que se basan en imponer un único modelo teórico (un único formato de datos) a toda la aplicación padecen de graves inconvenientes. En el caso de que toda la aplicación siga el modelo relacional, perdemos las ventajas de la orientación a objetos. En el caso de que toda la aplicación siga el modelo orientado a objetos, tenemos que las bases de datos que debemos usar están inmaduras y tienen un bajo nivel de estandarización. Examinemos ahora la opción de que el programa sea orientado a objetos y la base de datos sea relacional, lo que, en principio, constituye la opción más natural. Sin embargo, plantea el problema de cómo hacemos que dos componentes con formatos de datos muy diferentes puedan comunicarse y trabajar conjuntamente. Siguiendo la metáfora anterior, se trata de hacer que dos personas que hablan idiomas diferentes se comprendan. La solución es la misma que se daría en la vida real. Se debe encontrar un traductor que sepa traducir de cada idioma al otro. De esta forma, las dos personas se entenderán sin necesidad de que uno hable el idioma del otro. En el mundo de la programación este traductor no es más que un componente de software (concretamente, una capa de programación), al que se le dan los nombres de “capa de persistencia”, “capa de datos”, “correspondencia O/R” (“OR mapping”) o “motor de persistencia”. El motor de persistencia traduce entre los dos formatos de datos: de registros a objetos y de objetos a registros. La situación se ejemplifica en la figura 9. Cuando el programa quiere grabar un objeto llama al motor de persistencia, que traduce el objeto a registros y llama a la base de datos para que guarde estos registros. De la misma manera, cuando el programa quiere recuperar un objeto, la base de datos recupera los registros correspondientes, los cuales son traducidos en formato de objeto por el motor de persistencia. Figura 9. Arquitectura de una aplicación con motor de persistencia El programa sólo ve que puede guardar objetos y recuperar objetos, como si estuviera programado para una base de datos orientada a objetos. La base de datos sólo ve que guarda registros y recupera registros, como si el programa estuviera dirigiéndose a ella de forma relacional. Es decir, cada uno de los dos componentes trabaja con el formato de datos (el “idioma”) que le resulta más natural y es el motor de persistencia el que actúa de traductor entre los dos modelos, permitiendo que los dos componentes se comuniquen y trabajen conjuntamente. Esta solución goza de las mejores ventajas de los dos modelos. Por una parte, podemos programar con orientación a objetos, aprovechando las ventajas de flexibilidad, mantenimiento y reusabilidad. Por otra parte, podemos usar una base de datos relacional, aprovechándonos de su madurez y su estandarización así como de las herramientas relacionales que hay para ella. Se calcula que un motor de persistencia puede reducir el código de una aplicación en un 40%, haciéndola menos costosa de desarrollar. Además, el código que se obtiene programando de esta manera es más limpio y sencillo y, por lo tanto, más fácil de mantener y más robusto. Por añadidura, el motor de persistencia no sólo simplifica la programación, sino que permite hacer ciertas optimizaciones de rendimiento que serían difíciles de programar por nosotros mismos. Como conclusión, ésta es la mejor opción en la actualidad para implementar una aplicación de software. 6. OPCIONES PARA MOTORES DE PERSISTENCIA. Una ventaja del motor de persistencia es que es el mismo para todas las aplicaciones. De esta forma sólo debe programarse una vez y puede usarse para todas las aplicaciones que se desarrollen en nuestra empresa. Sin embargo, un motor de persistencia es difícil de programar y de mantener, por lo que necesita un gran esfuerzo en costo y tiempo de desarrollo. Es por ello que hay dos opciones a la hora de usar un motor de persistencia: Programarlo dentro de nuestra empresa. Como se ha dicho, esto no es lo más recomendable, por la complejidad y costo que introduce esta opción. Utilizar un motor que ya esté programado, comprándolo a un vendedor o bien usando un motor gratuito de código abierto. Se recomienda fuertemente la segunda opción, que es la menos costosa y la menos propensa a fallos. Se debe escoger un motor de persistencia de los que están programados, estudiarlo y aplicarlo a todas las aplicaciones de una misma empresa. A continuación, explicamos algunos de los motores de persistencia más importantes para la plataforma Java y para la plataforma .NET, con el fin de que el lector pueda comenzar una investigación que le lleve a escoger el que más se ajuste a sus necesidades. En cuanto a la plataforma Java, los servidores de aplicaciones basados en la especificación EJB (“Enterprise JavaBeans”), incorporan un motor de persistencia a través del mecanismo conocido como “entity beans”. Sin embargo, los “entity beans” no son un mecanismo de persistencia totalmente recomendable, pues no permiten implementar algunas características de la programación orientada a objetos (por ejemplo, herencia) y además, obligan a una forma de programar diferente a los objetos normales de Java (o POJOs, por “Plain Old Java Objects”) . Hay motores de persistencia más completos que no tienen este tipo de inconvenientes que se acaba de mencionar. Entre los de código abierto podemos destacar: Hibernate, Castor, Torque, OJB y Cayenne. Entre los comerciales, podemos destacar TopLink, Cocobase y FastObjects. En los últimos años se ha creado una especificación llamada JDO, para estandarizar la forma de programar en Java con esos motores de persistencia. Ejemplos de motores de persistencia que cumplen el estándar JDO son Kodo, JDO Genie, LiDo, Exadel JDO, IntelliBO, JRelay JDO (todos ellos comerciales), Speedo JDO, TJDO y XORM (de código abierto). La plataforma .NET, por su relativa novedad, está más inmadura que la plataforma Java. Además, al ser una plataforma propietaria, cuesta más encontrar proyectos de código abierto para ella. Por todo ello que no hay tanta variedad de motores de persistencia en esta plataforma. Recientemente, Microsoft ha anunciado un motor de persistencia llamado Objectspaces para .NET 2004. Mientras tanto, se puede usar ORM.NET, que es un motor de persistencia comercial para .NET. Compruebe la calidad de nuestro desarrollo offshore. Aurum Solutions tiene experiencia en desarrollo offshore en J2EE y .NET de alta calidad y reducidos costos para empresas europeas y norteamericanas. Conozca nuestro desarrollo offshore haciendo clic aquí o en la página Web http://espanol.aurumsol.com/offshore.html. Cursos de Aurum Solutions relacionados con el tema de este artículo: “Persistencia para Java”. “Java Data Objects (JDO)”. “Enterprise Javabeans”. “Persistencia para .NET”. Nota de copyright: Este documento puede ser impreso, copiado y utilizado en cualquier forma que se considere conveniente, siempre que se respete su integridad, el nombre de su autor y el enlace http://espanol.aurumsol.com a la empresa Aurum Solutions, S.A. de C.V. |