Está en la página 1de 10

Clase 19.

Modelos conceptuales

La misma notación de modelado de objetos que hemos utilizado para describir la estructura
de la pila en programas que se están ejecutando –es decir, qué objetos hay y cómo se hallan
relacionados por campos– puede emplearse de un modo más abstracto para describir el
estado espacial de un sistema o del entorno en el que éste opera. Denominaremos a estos
modelos "modelos conceptuales", aunque el libro de texto se refiere a ellos como "modelos
de datos". Ya hemos construido algunos de estos modelos en los ejemplos preparatorios del
ejercicio 4, y también al describir mediante la notación de modelado de objetos la
estructura del sistema de metro de Boston.

La notación en sí es sumamente sencilla, y los modelos se interpretan fácilmente una vez


dejemos de lado el enfoque orientado a la implementación y sustituyamos los objetos de
Java por entidades reales, los campos por relaciones, etc. Tras esta clase, el estudiante
estará en disposición de leer modelos conceptuales sin ningún tipo de problema.

Escribirlos, en cambio, requiere una mayor práctica, ya que implica crear las abstracciones
apropiadas, al igual que cuando se diseña la interfaz de un tipo de datos abstractos.
Construir correctamente las abstracciones es una tarea difícil, aunque la dificultad no tiene
que ver con el modelado de objetos en particular, sino con el hecho de que siempre resulta
complicado captar la esencia de un problema y articularlo de un modo conciso.

Una vez hayamos superado este obstáculo y construido un modelo conceptual, nos
hallaremos ya encaminados hacia la solución del problema. Como se suele decir, describir
un problema con exactitud es el primer paso para solucionarlo, y en el campo del desarrollo
de software una descripción exacta supone haber recorrido más de la mitad del camino.

No espere ser capaz de crear modelos conceptuales sin la práctica necesaria. Poner en
práctica sus habilidades de modelado le resultará muy entretenido y a medida que las
perfeccione descubrirá que se va convirtiendo en un diseñador más competente. Al ir
ganando claridad en sus estructuras conceptuales, las estructuras de su código se harán a su
vez más simples y más nítidas, y la codificación resultará más productiva.

En la clase propiamente dicha trataremos de dar una idea de cómo los modelos se crean
incrementalmente. En estas notas de clase, en cambio, los modelos se muestran en su forma
final.

19.1 Átomos, conjuntos y relaciones

Las estructuras de los modelos se pueden construir a partir de conjuntos, relaciones y


átomos. Un átomo es una partícula elemental que se caracteriza por ser:

· indivisible: no se puede descomponer en partes más pequeñas;


· invariable: sus propiedades no se alteran con el paso del tiempo; y
· no interpretable: carece de propiedades internas, al contrario de lo que, por ejemplo,
ocurre con los números.

Aparte de estas partículas elementales, muy pocas cosas en el mundo físico tienen
estructura atómica. Sin embargo, nada nos impide modelarlas de este modo; de hecho, el
modelado que proponemos no incluye ninguna idea de composición. Así, para modelar una
parte x formada por las partes y y z, consideraremos que tanto x como y y z son atómicas y
representaremos las restricciones mediante una relación explícita entre ellas.

Un conjunto es una suma de átomos no sujeta a las nociones de orden o cuenta de


repetición. Por su parte, una relación es una estructura que crea correspondencias entre los
átomos. Desde el punto de vista matemático, consiste en un conjunto de pares, cada uno de
ellos formado por dos átomos y dispuestos en un orden determinado. Podemos imaginar
una relación como una tabla de dos columnas en la que cada entrada es un átomo. El orden
en el que se hallan dispuestas las columnas es importante, mientras que el orden de las filas
no lo es. Cada fila debe tener una entrada en cada columna.

Resulta conveniente definir algunos de los operadores de conjuntos y relaciones. En


principio, nos servirán para explicar los modelos gráficos, aunque también pueden
utilizarse para escribir reglas más expresivas.

Dados dos conjuntos s y t, podemos tomar su suma (s+t), su intersección (s&t) o su


diferencia (s-t). Así, escribiremos no s para decir que una expresión indica un conjunto
vacío, y some s si lo que indica es un conjunto no vacío. Si lo que deseamos decir es que
cada miembro de s es a la vez miembro de t, escribiremos s in t; y s = t cuando cada
elemento de s sea un elemento de t y viceversa.

Dados un conjunto s y una relación r, escribiremos s.r para la imagen de s vinculada a la


relación r: el conjunto de elementos al que r asocia los elementos de s, lo que podemos
definir formalmente como:
s.r = {y | some x: s | (x,y) in r}
Dada una relación r, escribiremos ~r para indicar el intercambio de r: la relación de imagen
invertida, definida como:
~r = {(y,x) | (x,y) in r}

Por último, escribiremos +r para indicar el cierre transitivo de r: se trata de la relación que
asocia x a y, cuando existe alguna secuencia finita de átomos z1, z2, …, zn tal que
(x,z1) in r (z1,z2) in
r (z2,z3) in r
(zn,y) in r

y *r para indicar el cierre transitivo reflexivo de r, un cierre básicamente igual que el


transitivo, pero que además relaciona cada átomo consigo mismo. El cierre transitivo
tomaría la imagen a partir de una, dos, tres o más aplicaciones de la relación, mientras que
el cierre transitivo reflexivo no incluiría ninguna aplicación.

Veamos algunos ejemplos. Supongamos que tenemos un conjunto de gente llamado Person
que existe actualmente o existió en un momento dado, los conjuntos Man y Woman de
personas de sexo masculino o femenino, la relación parents que asocia a una persona con
sus padres, y la relación spouse que asocia a una persona con su cónyuge.
Interprete cada una de las siguientes afirmaciones. ¿Cuáles son válidas en el mundo real?
no (Man & Woman)
Man + Woman = Person
all p: Person | some p.spouse => p.spouse.spouse = p all p:
Person | some p.spouse
all p: Person | some p.parents
no p: Person | p.spouse = p
all p: Person | p.sisters = {q: Woman | p.parents = q.parents} all
p: Person | p.siblings = p.parents.~parents
Hasta aquí, hemos mostrado observaciones elementales relativas al mundo real y a
definiciones de términos. Las que planteamos a continuación, en cambio, se adentran en
terrenos más problemáticos:
no p: Person | some (p.parents & p.spouse.parents)
Man.spouse in Woman
some adam: Person | all p: Person | adam in p.*parents all
p: Man | no q, r: p.spouse | q != r
Suponiendo que el estudiante es capaz de comprender la notación lógica básica, hemos
introducido la definición de hermana (sister)
¿Cómo se escribirían las siguientes frases según esta notación?:
Todo el mundo tiene una madre
Nadie tiene dos madres
Los primos son personas que tienen un abuelo en común

La primera afirmación ilustra un punto interesante e importante: es muy cómodo dar por
supuesto que el significado de un término es siempre el más obvio, pero resulta muy
peligroso cuando hablamos de desarrollo de software. En este campo, la ambigüedad y la
indefinición en el significado de los términos son una fuente constante de problemas. Si los
desarrolladores entienden los requisitos de maneras distintas, acabarán implementando
módulos incompatibles entre sí, o que no sirvan para satisfacer las necesidades del cliente.
Por lo tanto, es necesario tener cuidado a la hora de expresar lo que significa cada conjunto
y cada relación. En este caso concreto, se debe precisar el significado del término mother.
¿Se trata de la madre legal o de la madre biológica? ¿O el término se refiere a algo distinto?
Al construir un modelo conceptual en el que se emplean términos que no se hallan
definidos en el contexto en el que estamos trabajando, se debe elaborar un glosario. Así, en
este ejemplo, escribiríamos en el glosario:
mother: (p,q) in mother significa que la persona q es la madre biológica de la persona p.

19.2 Notación gráfica


No es necesario volver a explicar detalladamente la notación gráfica, que ya vimos en la
clase de modelado de objetos. En esta clase nos limitaremos a reinterpretar la notación de
un modo más abstracto.

Fijémonos en el modelo de objeto correspondiente al árbol de familia. Cada cuadro indica


un conjunto de átomos, no un conjunto de objetos de un programa de Java ni de una clase.
Las flechas con la punta abierta indican la relación entre un conjunto y otro. Se trata de una
asociación abstracta, no de un campo ni de una variable de instancia.

Obviamente, las consecuencias semánticas son distintas dependiendo de cuál sea el sentido
de la flecha: es muy diferente decir que p es el padre de q o decir lo contrario. Sin embargo,
en cualquier relación podemos utilizar por igual una relación diferente que sea su inversa:
hijos (children) en vez de padres (parents), por ejemplo. No existe una noción de
navegabilidad, ni tampoco la idea de que una relación pertenezca a un conjunto del mismo
modo que una variable de instancia pertenece a una clase.
La flecha de trazo grueso con la punta cerrada indica un subconjunto. Dos conjuntos que
comparten una flecha son disjuntos. Podemos rellenar la punta de la flecha para indicar que
los subconjuntos son también exhaustivos; es decir, que cada elemento que forma el
superconjunto forma parte de al menos uno de los subconjuntos. En el presente ejemplo,
hemos expresado que cada persona (Person) es un hombre (Man) o una mujer (Woman).

Los conjuntos que no tienen superconjuntos se conocen como dominios (domains), y se


supone que son disjuntos. Por ejemplo, no hay átomos que sean a la vez una persona y un
nombre.

No insistiremos en esta clase sobre los indicadores de multiplicidad y mutabilidad, ya que


se hallan ampliamente explicados en el libro de texto del curso.

19.3 Relaciones ternarias

Ocurre en ocasiones que deseamos describir relaciones que comprendan no dos conjuntos,
sino tres. Supongamos, por ejemplo, que deseamos registrar el hecho de que una persona
recibe un salario por trabajar en una empresa. Como las personas pueden trabajar para
varias empresas y obtener un salario distinto en cada una de ellas, no nos basta con asociar
el salario a la persona.

La forma más sencilla de resolver esta cuestión suele ser crear un nuevo dominio. En este
caso, podríamos introducir Job (trabajo) y diseñar un modelo de objetos que muestre la
relación jobs entre Person y Job, una relación salary (salario) que vaya de Job a Salary, y
una relación company (empresa) desde Job a Company.

Esta solución funciona cuando el dominio introducido se corresponde a un conjunto natural


de átomos; se trata de una noción ya comprendida en el dominio del problema.

Otra posibilidad consiste en introducir una relación indexada. Si marcamos la flecha que va
de A a B con la etiqueta r[Index], estamos diciendo que existe una relación r[i] desde A a B
para cada átomo i del conjunto Index. Así, por ejemplo, para modelar nombres en un
sistema de archivos podemos tener una relación indexada obj[Dir] desde Name hasta
FileSystemObject (FSO), ya que conceptualmente existe una relación de nombres separada
para cada directorio del sistema de archivos.

Por último, podemos diseñar el modelo de objetos diciendo que es una proyección: muestra
las relaciones correspondientes a un átomo determinado en un dominio. Por ejemplo, al
diseñar un procesador de texto, habría una relación ternaria format (formato) que asocie un
StyleName (nombre de estilo) a un Format en una Stylesheet (hoja de estilo) determinada.
Nos puede interesar diseñar un modelo que únicamente tenga en cuenta una sola hoja de
estilo, de modo que la relación pase a ser binaria.

19.4 Tres ejemplos

Veamos a continuación tres ejemplos de modelos conceptuales, todos ellos sencillos pero
no triviales. Confiamos en que sirvan para demostrar lo útil que resulta la creación de
modelos, por muy pequeños que sean. Cuando esté usted trabajando en su proyecto de fin
de curso, o en posteriores desarrollos que desee realizar, deberá ser capaz de crear modelos
conceptuales según los vaya necesitando. No es preciso que tenga un único modelo
comprensivo; resulta más conveniente diseñar varios modelos de pequeño tamaño y a
continuación decidir cuáles sería necesario integrar. Hasta que adquiera la suficiente
experiencia en la creación de modelos conceptuales, pensará probablemente que una noción
conceptual es obvia y no descubrirá que no lo es hasta que haya profundizado en el código.
Por ello le interesa experimentar con otros modelos que crea que le van a ser útiles al
principio y, en caso de toparse con dificultades a la hora de codificar, volver atrás y diseñar
algunos modelos.

19.4.1 Tipos de Java

Nuestro primer modelo muestra las relaciones entre los objetos y las variables y sus tipos
en Java. Entender este modelo es esencial para poder comprender el lanzamiento dinámico
y las conversiones forzosas (casts) de tipos.

Existen tres dominios:


· Object: conjuntos de objetos de instancia existentes en la pila en tiempo de ejecución.
· Var: conjunto de variables que reúne objetos según su valor y que comprende variables de
instancia, argumentos de métodos, variables estáticas y variables locales.
Type: conjunto de tipos de objetos definidos por clases e interfaces.
Dejaremos de lado referencias nulas y tipos primitivos como int.

El dominio Type se halla clasificado por clases, clases abstractas e interfaces. El conjunto
ObjectClass es de un solo objeto (singleton) y se halla formado únicamente por la clase
llamada Object.

Hay cuatro relaciones:


· holds: asocia una variable al objeto con el que mantiene una referencia;
· otype: asocia un objeto a su tipo; el tipo adquirido por el hecho de haber sido creado por el
constructor de una clase.;
· vtype: asocia una variable a su tipo declarado;
· subs: asocia un tipo a sus subtipos inmediatos. Los subtipos de una clase son las clases
que la extienden, mientras que los subtipos de una interfaz son las interfaces que la
extienden y las clases que la implementan.

Las siguientes son algunas restricciones que no se pueden expresar gráficamente:


En primer lugar, la propiedad de seguridad de los tipos esenciales: el tipo de un objeto
mantenido en una variable se halla en el conjunto de subtipos directos o indirectos del tipo
de la variable.:
all v: Var | v.holds.otype in v.vtype.*sub

Algunas propiedades de la jerarquía de tipos en Java: que cada tipo es un subtipo directo o
indirecto de la clase Object; que una clase puede ser el subtipo de otra clase como máximo;
y que ningún tipo puede directa o indirectamente ser subtipo de sí mismo:
Type in ObjectClass.*sub

all c: Class | no c1, c2: Class | c1 != c2 && c in c1.sub && c in c2.sub


no t: Type | t in t.+sub

• Que las interfaces y las clases abstractas no pueden ser


instanciadas:

no o: Object | o.otype in (AbstractClass + Interface)

19.4.2 Meta-modelo
Nuestro siguiente modelo es un meta-modelo de notación de modelado gráfico de objetos.
Este meta-modelo deberá ser auto explicativo. Una restricción será, por ejemplo:

• Un conjunto box no puede tener un subconjunto arrow para sí mismo:


no a: SubsetArrow | a.parent in a.children

Existen muy pocas restricciones aparte de las que exigen que la jerarquía de subconjuntos
sea un árbol; lo que dota de flexibilidad a la notación. Las restricciones suelen ser útiles a la
hora de definir nuevos conjuntos y nuevas relaciones. Supongamos, por ejemplo, que
queremos clasificar aquellos arcos de relación que representen relaciones homogéneas:
relaciones que vinculan objetos en un único dominio. ¿Podríamos definir esta noción como
un nuevo conjunto? (Pista: posiblemente será más sencillo comenzar definiendo una
relación super de SetBox a SetBox, a continuación un conjunto DomainBox, y
posteriormente definir el conjunto HomoArrow en función de ello).

19.4.3 Numeración

Nuestro tercer modelo describe parte de la aplicación Tagger, sobre la que trató la clase
anterior. Esta aplicación muestra la información que se almacena en la stylesheet para
numerar párrafos, pero no nos dice cómo funciona la asignación de numeración a los
mismos párrafos. Esta función puede también añadirse, aunque ello resulta un tanto más
complicado.

Tenemos los siguientes dominios:


· Style: conjunto de nombres de estilo de párrafo;
· CounterType: conjunto de tipos de contadores (p.ej., arábigo, alfabético, latino).
· CounterValue: conjunto de valores que puede tener un contador (como 1, 2, 3; ó a, b, c).

Y tenemos las siguientes relaciones:


type: asocia un nombre de estilo con su tipo de contador (CounterType) declarado;
·initial: asocia un nombre de estilo con su valor de contador (CounterValue) inicial
declarado;
values: asocia un nombre de estilo con su valor de contador (CounterValue) inicial
declarado;
follows: asocia un valor de contador (CounterValue) con el valor que le sigue;
parent: asocia un nombre de estilo con su estilo padre; section, por ejemplo, podría ser el
padre de subsection.

Téngase en cuenta que un estilo no puede tener más de un padre. Sí se permite que dos
estilos tengan un mismo padre, ya que ello hace posible numerar de forma independiente,
por ejemplo, cifras y subsecciones dentro de una sección.

Veamos algunas restricciones:


• El valor inicial de un contador de estilo debe hallarse en el conjunto dado por su
CounterType. En la aplicación Tagger, esta regla viene reforzada por la sintaxis: la
declaración (p.ej., <counter:a> determina ambos al mismo tiempo).
all s: Style | s.initial in s.type.values

• Un estilo no puede ser su propio padre


no s: Style | s = s.parent

Y veamos también algunas definiciones:

• Los hijos de un estilo son aquellos estilos de los que éste es padre:

all s: Style | s.children = s.~parent

• La raíz de un estilo es el antecesor que no tiene padre:

all s: Style | s.root = {r:s.*parent | no r.parent}

19.5 Conclusión

El libro de texto del curso ofrece una descripción más detallada de la notación gráfica.
También resulta útil el apartado Material de Clase del curso 6.170 del año pasado, hay en él
un archivo PDF con una lista de contenidos que puede consultarse en la Web:
http://sdg.lcs.mit.edu/~dnj/publications.html#fall00-lectures

En esta dirección encontrará una clase sobre modelado conceptual con una mayor variedad
de casos prácticos.

La notación textual se conoce con el nombre de Alloy y ha sido diseñada por el Software
Design Group del MIT. Hemos creado también un analizador automático para Alloy capaz
de realizar simulaciones y comprobaciones. Si desea saber más sobre él, diríjase a la página
de publicaciones mencionada: en ella encontrará material que describe el lenguaje utilizado,
ilustrándolo con ejemplos prácticos.

También podría gustarte