Administración del Conocimiento – UML Simulation

Ejemplos de Código de una OODBMS (GemStone/S)

Posted in OODBMS - Base de Objetos, POO, UML by smalltalkuy on febrero 17, 2010

Ejemplos de Código de una OODBMS (GemStone/S)

Supongamos que tenemos el siguiente modelo UML plasmado en GemStone/S para lograr la persistencia, en lugar de usar una RDBMS como (Oracle u otra).

En la figura anterior vemos el modelo UML que estamos usando, el asunto aquí no es discutir el modelo, sino como logramos la persistencia de este modelo en una OODBMS como GemStone/S.

Básicamente el modelo tiene SoftwareFactory como clase central, se intenta llevar un registro de tareas de diferentes SoftwareFactory con muchos proyectos. En modelo es bastante sencillo, es simplemente la escusa para poder hablar de una OODBMS como GemStone/S.

Como podemos ver unaSoftwareFactory tiene muchos Proyectos (Project). Tenemos que unProyecto tiene varios Equipos (Team), y que un mismo Equipo (Team) puede estar en más de un proyecto. Cada Equipo (Team) tiene roles (con fecha inicio y fecha fin).

Cada Equipo (Team) y cada Rol tiene tareas a realizar respectivamente Tareas de Equipo (TeamTask) y Tareas de Rol (RolTask), cada Rol tiene asociado unaPersona (Person)….. a grandes rasgos el sistema es algo asi, con muchas…muchas… mejoras para hacerle…

Instalar el Modelo

Primero se crea el modelo UML dentro de GemStone/S, recordar que GemStone/S es un backend !!!

Para conectarme a el se usa cualquier interfase disponible para GemStone/S (Visual Works, Visual Age, Dolphin, Squeak, Seaside – cliente web). Estos son algunos Smalltalk que se pueden conectar a GemStone/S – que es otro Smalltalk pero es una OODBMS.

El modelo se crea dentro de Smalltalk con la clases, los atributos (variables de instancia), las relaciones, etc. La lista de clases quedaría como se muestra en la siguiente figura sacada de Dolphin Smalltalk.

Aquí vemos la lista de clases, esta lista se compila dentro GemStone/S de forma directa y tenemos nuestro sistema de control de tareas para N SoftwareFactories en una OODBMS.

Ahora bien como lograremos hacer persistente todos los objetos que queremos manejar ?

Supongamos que queremos crear una SofwareFactory llamada «Traditional» (si hay alguna empresa llamada así no son ellos).

Recordemos: unaSoftware tiene nombre y descripción, y puede tener proyectos.

Código GemStone/S

System beginTransaction. «comezamos una transacción»

traditional := SoftwareFactory new name: ‘Traditional’; description: ‘Just another SF’; yourself. «creamos una fábrica»

factories := UserGlobals at: #Factories put: OrderedCollection new. «creamos una colección para guardas nuestras fábricas»

factories add: traditional. «agregamos a la coleccion de fabricas la recien creada [traditional]»

System commitTransaction. «confirmamos la transacción»

Ahora nuestra nueva fabrica puede ser accedida y modificada por todos los usuarios conectados a GemStone/S, ya sea una conexión web o un cliente desktop. Acá vemos el código pero este código esta en una aplicación web o una desktop.

Agregar una proyecto a una Fabrica

System beginTransaction. «comezamos una transacción»

factories := UserGlobals at: #Factories. «obtenemos la colección de fábricas»

traditional := factories detect: [:each | each name = ‘Traditional’] ifNone: [Error signal: ‘no se encontro’]. «de todas las fabricas seleccionamos por su nombre la que recién agregamos, si no esta devolvemos un error»

traditional addProject: (Proyect new name: ‘Sistema global de información del estado’). «agregamos un proyecto a nuestra fábrica»

System commitTransaction«confirmamos la transacción»

Como vemos la capacidad de consultar al repositorio del sistema depende de dos cosas, la primera es la jerarquía de clases de la clase Collection (para poder realizar consultas), y la segunda y muy importante como esta diseñado nuestro sistema.

La jerarquía Collection

La clase SoftwareFactory tiene una colección de Proyectos (Project), esta colección es en realidad una instancia de la clase OrderedCollection de GemStone/S – pudimos haber elegido otra. Como se hace esto:

Como se ve en la imagen el método #initialize de SoftwareFactory pone en la variable <project> una OrderedCollection.

Cada instancia de SoftwareFactory tiene una colección en la variable <project>.

OrderedCollection soporta mensajes como: #add: #remove: #includes: #detect:ifNone: (el del ejemplo) #select: #reject: #anySatisfy: #allSatisfy: #addAll:

Todos estos métodos pueden ser usados para consultar/modificar los proyectos de la fábrica, claro que estos están embebidos como comportamiento dentro de las clases.

Ejemplos:

– Obtener los roles de los usuarios en un proyecto ? código… (más abajo)

– De todos los proyectos de una fabrica quiero saber cuales tiene más de x roles ? código…

System beginTransaction. «comezamos una transacción»

factories := UserGlobals at: #Factories«obtenemos la colección de fábricas»

«aquí usamos el métodos #detect:ifNone:«

traditional := factories detect[:each | each name ‘Traditional’] ifNone[Error signal: ‘no se encontro].

traditional proyectosConMasRolesQue: 8. «este es un método embebido en la clase SoftwareFactory – ver figura con el código»

System commitTransaction. «confirmamos la transacción»

Como vemos la clase SoftwareFactory tiene el método proyectosConMasRolesQue: cuyo código es el siguiente:

Como vemos los que hace la clase SoftwareFactory es recorrer la variable <project> que es una OrderedCollection, y seleccionar los objetos que dan <true> (si) al evaluar el método #tieneMasRolesQue:. O sea, que a cada Proyecto de la colección se le envía el mensaje #tieneMasRolesQue: y si responde <true> (si) es seleccionado.  El mensaje #tieneMasRolesQue: tiene el siguiente código:

Lo que hace la clase Proyecto es obtener todos sus roles, es decir, ir a todos sus equipos y obtener los roles de cada equipo y ver si ese número es mayor que <anInteger>. Ahora veremos el código de #getAllRols


Como se ve, se recorre la variable <team> que es una colección de Equipos (Team), y de cada equipo se obtiene la variable <rol> que es una colección de Roles. El mensaje #addAll: agrega una colección a otra, en nuestro caso usamos <todosLosRoles> para ir guardando los roles.

Otro ejemplo:

– Obtener los roles de los usuarios en un proyecto ? código…

Con el método #rolOf: de la clase Project (Proyecto) obtenemos los roles de <aPerson> en ese proyecto.

El método #getAllRols obtiene todos los roles de un Proyecto (ver ejemplo anterior), como cada Rol tiene una sola Persona asociada, para todos los Roles compara la Persona asociada a ese Rol con la Persona <aPerson> pasada como parámetro (ver imagen). En GemStone/S el comparador == compara por identidad del objeto (oop – object oriented pointer), cada objeto persistente tiene su propia oop.

Conclusiones

La manipulación de objetos dentro de una OODBMS depende directamente de dos cosas:

Diseño de nuestro modelo del objetos (o de clases UML)

Como vimos en el ejemplo anterior el diseño de clases, si quisiéramos conectar la clase SoftwareFactory con Rol tendríamos que cambiar el modelo, y habría que ajustar el comportamiento (los métodos). Por lo que nuestro diseño influye como se realizan las búsquedas en nuestro sistema.

Jerarquia de clases de Collection que tenga la OODBMS en particular

Las clases que ofrece una OODBMS nos afectara la forma de crear, manipular, conectar y consultar los objetos. Cuando más rica sea la OODBMS más liberad para escoger como conectar y consultar nuestro objetos tendremos.

Cada OODBMS tiene su jerarquia de clases particular, GemStone/S tiene ya 25 años por lo que esta jerarquía esta bastante evolucionada. Todas las clases cumplen ciertos protocolos, veremos ejemplos sencillos de estos mensajes.

Incluye colecciones como: OrderedCollection (del ejemplo), Dictionary, Set, SortedCollection, Array, LookupTable, RcQueue, RcSet, etc.

Mensajes generales a colecciones

aCollection add: anObject – «agrega un objeto a una colección»

aCollection remove: anObject – «remueve un objeto de una colección»

aCollection includes: anObject – «indica si incluye el objeto <anObject>»

aCollection detect: aBlock ifNone: exeptionBlock – «selecciona un unico objeto que cumple la condicion pasada como parametro <aBlock> si no encuentra ninguno evalúa el parametro <exeptionBlock>»

aCollection detect: [:each | each nombre = ‘Pedro’] ifNone: [Error signal: ‘No existe Pedro’].

aCollection select: aBlock  – «selecciona todos los objetos que cumplen la condición <aBlock>»

aCollection select: [:each | each edad > 18] «el mensaje #reject: es lo mismo pero rechaza en lugar de seleccionar»

aCollection anySatisfy: aBlock – «devuelve true o false – indica si alguna instancia de la colección cumple con la condición <aBlock>»

aColleciton do: aBlock – «para cada elemento de la colección evalúa <aBlock>»

aCollection do: [:each | each calcularCostos]