Animación Automática de Especificaciones OASIS utilizando

Transcripción

Animación Automática de Especificaciones OASIS utilizando
Animación Automática de Especificaciones OASIS
utilizando
Programación Lógica Concurrente
Patricio Orlando Letelier Torres
Departamento de Sistemas Informáticos y Computación
Universidad Politécnica de Valencia
Memoria para optar al Grado de Doctor en Informática
Dirigida por el Prof. Dr. Isidro Ramos Salavert
ii
Abstract
El modelo conceptual expresa los requisitos funcionales de un sistema
de información. Errores u omisiones en el modelo conceptual tienen por
lo general graves consecuencias en el resto del proceso de desarrollo de
software. Por esto, la validación temprana de requisitos es una actividad
de reconocida importancia. En este sentido, los enfoques más extendidos
incluyen técnicas semiformales y en particular prototipación. Sin embargo, el resultado obtenido está lejos de ser satisfactorio. La combinación
de técnicas formales con prototipación abre nuevas perspectivas, en especial la prototipación basada en especificaciones formales ejecutables y
denominada animación de especificaciones. El desafío en este caso está en
la capacidad para obtener código ejecutable a partir de una especificación,
más aún si se pretende conseguir la generación automática de dicho código. Precisamente una de las ventajas de un enfoque formal es el ofrecer un
marco más apropiado para establecer un proceso de traducción desde una
especificación hacia un programa. En este trabajo de Tesis se establecen
las bases para animación automática de especificaciones OASIS utilizando como entorno de implementación Programación Lógica Concurrente.
El trabajo se orienta a la construcción de un ambiente para validación
temprana de especificaciones OASIS mediante animación automática.
Agradecimientos
Ni el resultado ni el recuerdo de mi dedicación a este trabajo serían
los mismos sin la positiva participación directa o indirecta de muchas
personas. En especial quisiera agradecer a las siguientes personas:
A mi director Isidro Ramos por la confianza depositada en mí y por
algunos oportunos golpes en la espalda que han mantenido la motivación.
A Pedro Sánchez por ser el socio perfecto con quien he podido mezclar
agradablemente la amistad y el trabajo. Difícilmente podría haber disfrutado tanto un jamón y un vino hablando de OASIS.
A los miembros de nuestro grupo de investigación, en particular a
quienes animan las reuniones de grupo en cuyos debates este trabajo ha
encontrado una fuente de inspiración.
Índice general
1. Introducción
1.1. Motivación . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3. Estructura de la Tesis . . . . . . . . . . . . . . . . . . . . . . .
1
1
2
3
2. Antecedentes
2.1. Contexto del trabajo . . . . . . . . . . .
2.1.1. Ingeniería de requisitos . . . . .
2.1.2. Modelado conceptual orientado a
2.1.3. Métodos formales y OASIS . . .
2.1.4. Validación y verificación . . . . .
2.1.5. Prototipación y animación . . . .
2.1.6. Programación automática . . . .
2.2. Descripción del trabajo de Tesis . . . . .
2.3. Trabajos relacionados . . . . . . . . . .
. . . .
. . . .
objeto
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
8
9
11
13
14
16
18
3. OASIS
3.1. Plantilla o tipo . . . . . . . . . . . . .
3.2. Ciclo de vida de un objeto . . . . . . .
3.3. OASIS expresado en Lógica Dinámica
3.4. Semántica de OASIS . . . . . . . . . .
3.5. Concurrencia en OASIS . . . . . . . .
3.6. Conclusiones del capítulo . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
24
24
26
28
29
29
4. Perspectiva cliente
4.1. Repetición de disparos en OASIS 2.2 .
4.2. Incorporando la perspectiva cliente . .
4.2.1. Identificación de objetos . . . .
4.2.2. Referencias a cliente y servidor
4.2.3. Acciones . . . . . . . . . . . . .
4.2.4. Control de disparos . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
32
34
35
36
38
41
iii
iv
ÍNDICE GENERAL
4.3. Conclusiones del capítulo . . . . . . . . . . . . . . . . . . . . .
5. Especificaciones de proceso
5.1. Procesos en OASIS 2.2 . . . . . . . . . . . . . . . . .
5.2. Procesos en OASIS 3.0 . . . . . . . . . . . . . . . . .
5.2.1. Procesos como fórmulas en Lógica Dinámica
5.3. Un ejemplo más extenso . . . . . . . . . . . . . . . .
5.4. Aspectos adicionales . . . . . . . . . . . . . . . . . .
5.5. Conclusiones del capítulo . . . . . . . . . . . . . . .
.
.
.
.
.
.
6. Interacción entre objetos
6.1. Comunicación entre objetos en OASIS 2.2 . . . . . . .
6.1.1. Disparos . . . . . . . . . . . . . . . . . . . . . .
6.1.2. Eventos compartidos . . . . . . . . . . . . . . .
6.1.3. Comparación entre OASIS 2.2 y TROLL . . . .
6.2. Un nuevo esquema de comunicación . . . . . . . . . .
6.2.1. Mecanismos de comunicación . . . . . . . . . .
6.2.2. Comentarios adicionales . . . . . . . . . . . . .
6.3. Arquitecturas software en el marco de OASIS . . . . .
6.3.1. Componentes y conectores en OASIS . . . . . .
6.3.2. Un ejemplo aplicando arquitecturas software en
6.4. Conclusiones del capítulo . . . . . . . . . . . . . . . .
.
.
.
.
.
.
47
48
49
54
58
63
66
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
OASIS
. . . . .
69
69
69
70
72
75
76
79
80
81
83
85
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7. Un ejemplo en OASIS 3.0
87
8. Un modelo de ejecución para OASIS
8.1. El modelo de ACTORS . . . . . . . . . . . . . . . . . .
8.2. Un modelo abstracto para animación en OASIS . . . . .
8.2.1. Alcance del modelo . . . . . . . . . . . . . . . . .
8.2.2. Aspectos básicos . . . . . . . . . . . . . . . . . .
8.2.3. Concurrencia intra-objeto . . . . . . . . . . . . .
8.2.4. Conflicto entre acciones . . . . . . . . . . . . . .
8.2.5. Clasificación de acciones en el buzón . . . . . . .
8.2.6. Comunicación self . . . . . . . . . . . . . . . . .
8.2.7. Modelando el comportamiento interno del objeto
8.2.8. El modelo de ejecución en funcionamiento . . . .
8.3. Conclusiones del capítulo . . . . . . . . . . . . . . . . .
9. Programación Lógica Concurrente
9.1. Programación Lógica y PLC . . . .
9.2. Comunicación entre procesos . . .
9.3. Objetos y clases en PLC . . . . . .
9.4. Conclusiones del capítulo . . . . .
46
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
89
. 89
. 92
. 94
. 94
. 95
. 96
. 97
. 99
. 100
. 103
. 104
.
.
.
.
107
109
111
119
124
.
.
.
.
ÍNDICE GENERAL
10.PLC y OASIS
10.1. Representando una especificación OASIS en KL1
10.1.1. Clases y objetos . . . . . . . . . . . . . .
10.1.2. Comunicación entre objetos . . . . . . . .
10.1.3. Comportamiento del objeto . . . . . . . .
10.1.4. Creación y destrucción de objetos . . . .
10.1.5. Cambio de estado . . . . . . . . . . . . .
10.1.6. Permisos y prohibiciones . . . . . . . . . .
10.1.7. Obligaciones . . . . . . . . . . . . . . . .
10.2. Conclusiones del capítulo . . . . . . . . . . . . .
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
125
127
127
128
130
130
132
133
133
135
11.LUNA: Una herramienta basada en OASIS
11.1. Ambiente de especificación incremental y validación
11.2. Repositorio OASIS . . . . . . . . . . . . . . . . . . .
11.3. Entorno gráfico de especificación . . . . . . . . . . .
11.4. Traductor OASIS-PLC . . . . . . . . . . . . . . . . .
11.4.1. Alcance del prototipo generado . . . . . . . .
11.4.2. Plantillas para generación de código KL1 . .
11.5. Entorno de animación . . . . . . . . . . . . . . . . .
11.6. Proceso de especificación y validación . . . . . . . .
11.7. Conclusiones del capítulo . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
137
137
139
140
141
144
145
149
151
152
.
.
.
.
.
.
.
.
.
12.Conclusiones
155
12.1. Trabajo futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
12.2. Publicaciones impulsadas por esta Tesis . . . . . . . . . . . . . 157
A. Ejemplos en PARLOG
159
A.1. Pequeña biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . 159
A.2. Sistema de control de nivel . . . . . . . . . . . . . . . . . . . . 166
B. Repositorio OASIS
173
C. Plantillas para generar KL1
C.1. Cláusulas para predicados main y router . . . . . . . . . . . .
C.1.1. Ejemplo: Código generado para los predicados main y
router en el sistema bancario . . . . . . . . . . . . . . .
C.2. Cláusulas por cada clase . . . . . . . . . . . . . . . . . . . . . .
C.2.1. Cláusulas para el predicado c_clase . . . . . . . . . . .
C.2.2. Cláusulas para el predicado o_clase . . . . . . . . . . .
C.2.3. Ejemplo: Código generado para los predicado c_account
y o_account en el sistema bancario . . . . . . . . . . .
185
185
D. Una sesion con entrada por lotes
203
188
190
190
193
196
vi
ÍNDICE GENERAL
Índice de figuras
2.1. Paradigma de programación automática . . . . . . . . . . . . .
2.2. Modelado conceptual basado en OASIS . . . . . . . . . . . . .
14
17
3.1. Relación entre mundos, estados y pasos del objeto. . . . . . . .
28
4.1.
4.2.
4.3.
4.4.
Repetición de disparos . . . . . . . . . . . . . . . .
Perspectivas cliente y servidor de un objeto. . . . .
Parte del ciclo de vida de un objeto de la clase Y. .
Parte del ciclo de vida de un objeto de la clase X. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
34
39
43
45
5.1.
5.2.
5.3.
5.4.
5.5.
Grafo de transiciones del proceso P. . . . . . . . . .
Representación del proceso en su forma no canónica.
Representación del proceso en su forma canónica. . .
Grafo de transiciones para la operación CANCEL . .
Grafo de transiciones para el protocolo GETCHOC .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
52
53
54
60
60
6.1. Disparos en OASIS 2.2 . . . . . . . . . . . . . . . . . . . .
6.2. Interpretación de un disparo como el paso de un mensaje.
6.3. Eventos compartidos en OASIS 2.2 . . . . . . . . . . . . .
6.4. Un protocolo para implementar eventos compartidos. . . .
6.5. Caso de objetos relacionados estructuralmente. . . . . . .
6.6. Caso de objetos no relacionados estructuralmente. . . . .
6.7. Representación del mecanismo action sending. . . . . . . .
6.8. Representación del mecanismo action waiting. . . . . . . .
6.9. Representación del mecanismo action calling. . . . . . . .
6.10. Representación de una interacción call/return . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
70
71
71
73
74
74
76
77
78
80
8.1. Representación de aspectos básicos de un actor . . . . . . . . . 91
8.2. Entornos de programación para ejecución de especificaciones
OASIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
8.3. Ciclo de vida de un objeto . . . . . . . . . . . . . . . . . . . . . 95
8.4. Vida de un objeto en OASIS . . . . . . . . . . . . . . . . . . . 101
vii
viii
ÍNDICE DE FIGURAS
8.5. Ciclo de vida de una instancia de cuenta entre t1 y t5
. . . . . 103
9.1.
9.2.
9.3.
9.4.
Se produce una naranja, se consume una. . . . . . . . . . . . . 112
Se produce un número ilimitado de naranjas. . . . . . . . . . . 113
Se producen N naranjas. . . . . . . . . . . . . . . . . . . . . . . 114
El consumidor solicita ilimitadas naranjas, cada vez que se recibe
una se pide otra. . . . . . . . . . . . . . . . . . . . . . . . . . . 115
9.5. El consumidor solicita N naranjas. . . . . . . . . . . . . . . . . 116
9.6. Espera usando mensaje incompleto. . . . . . . . . . . . . . . . . 117
9.7. Más de un productor enviando mensajes a un mismo consumidor.118
9.8. Utilizando un merge sin límite de entradas. . . . . . . . . . . . 119
9.9. Diagrama de transición de estados para el proceso clase. . . . 123
9.10. Diagrama de transición de estados para el proceso objeto. . . . 124
10.1. Una situación de ejecución para el ejemplo bancario. . . . . . . 128
10.2. Esquema de comunicación entre objetos . . . . . . . . . . . . . 129
11.1. Ambiente para especificación y validación de especificaciones
OASIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
11.2. Entorno Gráfico de Especificación. . . . . . . . . . . . . . . . . 141
11.3. Especificación de una clase. . . . . . . . . . . . . . . . . . . . . 142
11.4. Subentorno para edición de Diagramas de Transición de Estados.143
11.5. Tres aspectos en el código KL1 de un prototipo. . . . . . . . . . 143
11.6. Un ejemplo de los pasos de generación automática . . . . . . . 147
11.7. Primera versión del Entorno de Animación . . . . . . . . . . . 148
11.8. Inicio de la sesión de animación . . . . . . . . . . . . . . . . . . 150
11.9. Construcción de acciones de creación de instancias . . . . . . . 151
11.10.Sesión de animación después de crear tres instancias . . . . . . 152
11.11.Acciones ejecutadas por el objeto account(101) . . . . . . . . 153
11.12.Estado actual del objeto account(101) . . . . . . . . . . . . . 153
A.1. Esquema de comunicación en la pequeña biblioteca . . . . . . . 160
A.2. Esquema del sistema de control de nivel. . . . . . . . . . . . . . 166
A.3. Esquema de implementación en PARLOG para el ejemplo. . . . 166
B.1.
B.2.
B.3.
B.4.
B.5.
B.6.
B.7.
B.8.
Paquete
Paquete
Paquete
Paquete
Paquete
Paquete
Paquete
Paquete
“esquema” . . . . . . . . . . . .
“clase” . . . . . . . . . . . . . .
“interfaz” . . . . . . . . . . . .
“atributo e identificador” . . .
“servicio, proceso y parámetro”
“evaluaciones” . . . . . . . . .
“derivaciones” . . . . . . . . . .
“precondiciones” . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
174
174
175
175
176
176
177
177
ÍNDICE DE FIGURAS
B.9. Paquete
B.10.Paquete
B.11.Paquete
B.12.Paquete
B.13.Paquete
B.14.Paquete
B.15.Paquete
B.16.Paquete
B.17.Paquete
B.18.Paquete
“disparos” . . . .
“procesos” . . . .
“cliente-servidor”
“acciones” . . . .
“relaciones” . . .
“agregacion” . .
“herencia” . . . .
“fórmula” . . . .
“ámbito fórmula”
“parámetros” . .
ix
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
178
178
179
179
180
180
181
182
182
183
x
ÍNDICE DE FIGURAS
Capítulo 1
Introducción
En este capítulo se presentan la motivación y los objetivos de esta Tesis.
Además, se indica la estructura de esta memoria, describiendo brevemente el
contenido de los capítulos posteriores.
1.1.
Motivación
La ingeniería de requisitos [75, 98, 16] es un campo de reconocida importancia en el ámbito teórico y práctico de la ingeniería del software. Las
mayores carencias (y desafíos) de la construcción de software se encuentran
en las primeras actividades del proceso. En ellas, la principal dificultad radica
en la distancia existente entre el espacio del problema (Universo de Discurso) y el espacio de la solución (el software construido). El modelo conceptual
establece el vínculo entre ambos expresando los requisitos funcionales del sistema y constituyendo la base para las tareas siguientes en el desarrollo del
sistema.
La construcción del modelo conceptual del sistema es un proceso de descubrimiento, no sólo para el analista, sino también para el usuario1 . La estrategia
que más se ajusta a esta situación es construir el modelo conceptual de forma
iterativa, con refinamientos sucesivos y mediante interacción entre el usuario
y el analista. En cada paso el analista debe verificar el modelo y validarlo
respecto de las necesidades del usuario. Finalmente, una vez alcanzada la conformidad de las partes involucradas, el modelo conceptual se utiliza como entrada para las fases posteriores del desarrollo. El impacto de una modificación
en el modelo conceptual, respecto de los resultados de las fases siguientes y
del producto final, es por lo general muy grande. Por lo tanto, la validación
temprana del modelo conceptual es importante. Las dificultades asociadas a
1
En inglés se utilizaría stakeholder, lo cual resulta más apropiado pues incluye a todos los
usuarios directos e indirectos del sistema.
1
2
CAPÍTULO 1. INTRODUCCIÓN
la tarea de validación del modelo conceptual constituyen la motivación para
desarrollar una propuesta basada en animación automática.
Este trabajo de Tesis se ha generado en el grupo de investigación en Modelado Conceptual Orientado a Objetos y Bases de Datos, perteneciente al
Departamento de Sistemas Informáticos y Computación de la Universidad
Politécnica de Valencia. Una de las principales actividades llevadas a cabo en
los últimos años por este grupo ha sido el desarrollo de OASIS (Open and
Active Specification of Information Systems) [69, 70, 56], un modelo formal
para la construcción de modelos conceptuales que sigue el paradigma orientado
a objeto. En la perspectiva de OASIS, un sistema de información es una sociedad de objetos autónomos y concurrentes que interactúan entre sí. En este
contexto, el propósito de este trabajo de Tesis ha sido estudiar la generación
automática de código que permita animar especificaciones OASIS. Se ha utilizado Programación Lógica Concurrente [85] como lenguaje a ser generado.
El programa obtenido automáticamente tiene la particularidad que su ejecución está orientada especialmente a ayudar en la validación de la especificación
OASIS asociada.
Todas las actividades asociadas al desarrollo de este trabajo se han enmarcado en dos proyectos de la Comisión Interministerial de Ciencia y Tecnología (CICYT): OASIS (1994-1997, TIC94-0557) y MENHIR [63] (19972000, TIC97-0593-C05-01). Este último es un proyecto coordinado en el cual
participan además grupos de investigación de las Universidades de Granada,
Murcia, Sevilla y Valladolid.
1.2.
Objetivos
El objetivo global de este trabajo de Tesis es establecer las bases teóricas y prácticas para la animación automática de especificaciones OASIS en
un entorno de programación concurrente. Se pretende conseguir una versión
preliminar de un ambiente en el cual, partiendo de un modelo conceptual en
OASIS, se obtenga de forma automática un prototipo que ayude a la validación
de requisitos. Para la implementación del prototipo se ha usado Programación
Lógica Concurrente, utilizando los lenguajes PARLOG [12] y KL1 [14].
Los objetivos específicos de esta Tesis son:
Extender y completar OASIS 2.2 [70] para que constituya un marco
formal apropiado a partir del cual pueda establecerse un trabajo de prototipación2 automática. El trabajo asociado se ha enmarcado dentro del
2
Se usará “prototipación” y sus palabras derivadas para referirse al concepto del inglés
prototyping.
1.3. ESTRUCTURA DE LA TESIS
3
desarrollo de una nueva versión de OASIS (versión 3.0) [56] en la cual
se incluyen algunos de los resultados obtenidos en esta Tesis. Así, los
objetivos siguientes se establecen considerando OASIS 3.0.
Establecer un modelo abstracto de ejecución para especificaciones OASIS.
Establecer correspondencias entre conceptos OASIS y conceptos de Programación Lógica Concurrente, determinando pautas de traducción. Implementar3 dichas pautas en un programa traductor que genere automáticamente un programa lógico concurrente a partir del repositorio
de una especificación OASIS.
Construir una versión preliminar de un ambiente para animación automática de especificaciones OASIS y proponer un proceso de ingeniería
de requisitos basado en animación automática de modelos conceptuales.
1.3.
Estructura de la Tesis
La presentación de esta Tesis se ha organizado en los siguientes capítulos:
Capítulo 2: Antecedentes
Se presenta el contexto del trabajo de Tesis incluyendo una descripción de los aspectos de ingeniería del software involucrados.
Además se determina el alcance del trabajo, estableciendo la relación
entre los siguientes aspectos: animación automática de especificaciones OASIS, utilización de Programación Lógica Concurrente y
validación de especificaciones OASIS. Por último, se analiza el estado del arte comentando algunos trabajos relacionados.
Capítulo 3: OASIS
Se introduce OASIS 3.0 como lenguaje formal para el modelado
conceptual de sistemas de información. En esta Tesis se partió de
OASIS versión 2.2 pero muchos de los inconvenientes encontrados y
resueltos durante el desarrollo de este trabajo llevaron al establecimiento de OASIS versión 3.0. Así, en este capítulo se ha preferido
mostrar la versión 3.0, dejando para los tres capítulos siguientes la
discusión y propuestas de cambio relacionadas con animación de
especificaciones que fueron incluidas finalmente en la versión 3.0.
3
Se utilizará “implementar” y sus palabras derivadas para referirse al concepto del inglés
implement.
4
CAPÍTULO 1. INTRODUCCIÓN
Capítulo 4: Perspectiva cliente
En este capítulo se describen algunos inconvenientes de OASIS 2.2
ocasionados por no contar con la capacidad para expresar adecuadamente la perspectiva cliente de un objeto. Se plantea una
forma homogénea de incorporar este aspecto. Utilizando un nuevo concepto de acción, tanto los servicios provistos como los requeridos por un objeto son acontecimientos relevantes en su vida.
Para OASIS, la incorporación de la perspectiva cliente representa
una mejora en expresividad. En particular, para la animación de
especificaciones OASIS esto permitió disponer de un mecanismo
para controlar la repetición de un disparo.
Capítulo 5: Especificaciones de proceso
En OASIS 2.2 se dispone de dos formas para especificar el comportamiento: basándose en el estado del objeto o basándose en
secuencias acontecidas de acciones. En cada caso se utiliza una
formalización distinta; para el primer caso se usa una variante de
Lógica Dinámica (que incluye la representación de los operadores
deónticos de obligación, prohibición y permiso), para el segundo se
usa un Álgebra de Procesos para Objetos. La integración de estas
dos visiones del comportamiento con el propósito de animación significaba eludir un gran obstáculo. En este capítulo se establece un
nuevo enfoque para la especificación de procesos, basado también
en un Álgebra de Procesos y que permite una interpretación directa y sencilla en la variante de Lógica Dinámica utilizada. Así, en
términos de animación, todo el comportamiento de un objeto está
determinado por un conjunto de fórmulas en Lógica Dinámica. Esto simplifica el establecimiento de correspondencias entre OASIS
y el entorno de implementación.
Capítulo 6: Interacción entre objetos
La incorporación de la perspectiva cliente y de otros aspectos creó
la necesidad de revisar los mecanismos de comunicación ofrecidos
por OASIS 2.2. En este capítulo se describe la interacción entre objetos en OASIS 2.2 y se hace una comparación con TROLL (uno
de los lenguajes de especificación más próximos a OASIS). Se propone un nuevo esquema de interacción entre objetos, el cual finalmente ha sido incluido en OASIS 3.0. Adicionalmente, se analiza la
posibilidad de introducir en el futuro la filosofía de Arquitecturas
Software.
1.3. ESTRUCTURA DE LA TESIS
Capítulo 7: Un ejemplo en OASIS 3.0
Se presenta un ejemplo simple pero que incluye la funcionalidad cubierta por la versión actual del traductor OASIS-KL1. Este ejemplo
será utilizado en los capítulos posteriores.
Capítulo 8: Modelo de ejecución
Se establece un modelo abstracto de ejecución para especificaciones
OASIS 3.0. Este modelo de ejecución provee una interpretación
operacional para especificaciones OASIS, incluyendo el tratamiento
de la concurrencia.
Capítulo 9: Programación Lógica Concurrente
Se presenta el paradigma de Programación Lógica Concurrente el
cual será utilizado como entorno de implementación para la animación de especificaciones OASIS. Se describen las principales características de un lenguaje lógico concurrente. Particularmente se
presenta la comunicación entre procesos provista y cómo se pueden
modelar objetos y clases. Además, se analizan varios ejemplos desarrollados usando el lenguaje PARLOG.
Capítulo 10: OASIS y Programación Lógica Concurrente
En este capítulo se establecen correspondencias entre conceptos
de OASIS y elementos de la Programación Lógica Concurrente.
Mediante un ejemplo implementado en el lenguaje KL1 se ilustra
cómo los conceptos OASIS tienen una representación directa en un
programa lógico concurrente.
Capítulo 11: LUNA: Una herramienta basada en OASIS
Se presenta un ambiente para la especificación y validación de requisitos llamado LUNA. Se trata de un workbench compuesto por
tres herramientas, un repositorio OASIS y un traductor OASISKL1. Las herramientas son: asistente para construir escenarios,
entorno gráfico de especificación y entorno gráfico de animación.
Capítulo 12: Conclusiones
Se resumen los principales resultados y aportes de esta Tesis. Se
plantean las líneas de continuación que sería interesante abordar
para consolidar y extender el trabajo realizado.
5
6
CAPÍTULO 1. INTRODUCCIÓN
Apéndice A: Ejemplos en PARLOG
Se presentan dos ejemplos más extensos que ilustran algunos aspectos de la representación de clases y objetos en Programación
Lógica Concurrente.
Apéndice B: Repositorio OASIS
Se describe la estructura del repositorio utilizado para almacenar especificaciones OASIS.
Apéndice C: Plantillas para generar KL1
En este apéndice se muestran algunas plantillas utilizadas para construir
el traductor OASIS-KL1. Además se incluye parte del código generado para
el ejemplo del capítulo 7.
Apéndice D. Una sesión con entrada por lotes
Se muestra una sesión de animación en la cual todas las acciones son leídas
desde un fichero y el entorno de animación genera otro fichero con los resultados, incluyendo para cada objeto la secuencia de acciones acontecidas y los
correspondientes estados alcanzados.
Capítulo 2
Antecedentes
En este capítulo se describe el contexto en el cual se desenvuelve esta Tesis,
permitiendo enmarcar adecuadamente el trabajo desarrollado y establecer su
alcance. Adicionalmente se analizan de algunos trabajos relacionados ilustrando el estado del arte en dicho contexto.
2.1.
Contexto del trabajo
En este trabajo se conjugan varios aspectos de la ingeniería del software. A
continuación se hará una breve descripción de cada uno de ellos. Aunque existen relaciones de dependencia y solape entre dichos aspectos, su presentación
se orientará a una caracterización más o menos independiente que permita
en la sección siguiente precisar el trabajo desarrollado y los aportes que se
esperan conseguir.
2.1.1.
Ingeniería de requisitos
“Ingeniería de requisitos es el proceso para establecer los servicios que el
sistema debería proveer y las restricciones bajo las cuales debe operar” [91]. En
general dichos servicios y restricciones se denominan requisitos. Un requisito
funcional es aquel que describe un servicio o función del sistema, en cambio, un
requisito no-funcional es una restricción impuesta sobre el sistema o el proceso
de desarrollo.
Algunos problemas que afectan el éxito del proceso de ingeniería de requisitos son [17, 45]:
Es potencialmente imposible definir un conjunto completo de requisitos.
Se puede expresar con precisión un requisito conocido, pero no existe un
método que nos diga qué debería ser especificado.
7
8
CAPÍTULO 2. ANTECEDENTES
Es difícil obtener un conjunto consistente de requisitos. En sistemas
grandes hay diversidad de usuarios, conflicto entre restricciones organizacionales y de presupuesto con respecto a necesidades de usuarios
finales.
Los requisitos evolucionan constantemente, incluso durante el desarrollo
del sistema.
No existen métodos satisfactorios para abordar esta fase y consecuentemente las herramientas disponibles no ofrecen una adecuada integración
de técnicas1 .
Las barreras de comunicación entre los colectivos involucrados suelen ser
un gran problema.
Los requisitos pueden establecerse en tres niveles de abstracción [94]: requisitos organizacionales (relacionando al sistema con los objetivos y restricciones
del negocio), requisitos del dominio del problema (describiendo el sistema en
términos de las interacciones con su entorno) y requisitos del sistema (estableciendo la estructura y el comportamiento interno del sistema). En este
aspecto, nuestro interés se centra principalmente en el modelado de requisitos
del sistema.
2.1.2.
Modelado conceptual orientado a objeto
Un modelo conceptual de un sistema de información representa los requisitos del sistema, esencialmente los requisitos fincionales. El término conceptual se refiere al hecho que el modelo consiste en conceptos mediante los
cuales el usuario y el analista interpretan y observan el espacio del problema.
El modelado conceptual tiene sus raíces en el modelado semántico de datos
[92, 86, 40, 29]. Cuando se utiliza el enfoque orientado a objeto para el modelado conceptual los requisitos funcionales son encapsulados bajo el concepto de
objeto, incluyendo las perspectivas estática y dinámica del sistema estudiado.
Durante la fase de modelado conceptual se llevan a cabo esencialmente
cuatro tareas [20]:
1. Captura de requisitos: descubrir lo que el usuario quiere obtener como
sistema.
2. Modelado: describir el modelo conceptual del sistema.
1
En este aspecto la comunidad formada por quienes trabajamos en desarrollo de software
es una de las principales culpables. Frecuentemente los métodos y técnicas son reemplazados
considerándolos obsoletos sin llegar a consolidarse, aunque normalmente no se cuenta con la
suficiente evidencia de que dicho reemplazo es la alternativa más recomendable.
2.1. CONTEXTO DEL TRABAJO
9
3. Análisis: verificar que el modelo satisface ciertos criterios de calidad y
consistencia.
4. Validación: determinar si el modelo conceptual reúne los requisitos informales obtenidos del usuario.
Estas tareas se repiten hasta que en 4) se obtiene la conformidad del modelo
conceptual respecto de los requisitos informales del usuario.
En la actualidad el uso de escenarios [80] para capturar requisitos ha despertado gran interés, prueba de ello es la actividad impulsada por el proyecto ESPRIT llamado CREWS2 (C ooperative Requirements Engineering with
Scenarios). Un escenario es una descripción parcial del comportamiento de un
sistema y su ambiente en una determinada situación. Los escenarios describen
partes posiblemente solapadas del comportamiento de un sistema. Además de
ser útiles en la captura de requisitos, los escenarios constituyen un tipo de
casos de prueba, particularmente interesante para la validación del sistema.
Las técnicas para establecer escenarios, en cuanto a detalle y rigor varían
desde descripciones narrativas hasta representaciones basadas en notaciones
formales.
2.1.3.
Métodos formales y OASIS
Una manera de ayudar en la construcción de software más fiable es utilizar métodos formales [99, 66, 60, 27]. Los métodos formales ofrecen para
el desarrollo de software una mejora en la calidad del producto y reducción
de costos de construcción y mantenimiento. Sin embargo, la introducción de
métodos formales no ha sido inmediata y sólo en la actualidad comienzan tímidamente a ser introducidos en el entorno industrial de desarrollo de software
[15, 94]. Cuatro razones explican esta situación [39]: falsas expectativas o desconocimiento, carencia de estándares para métodos y su aplicación, falta de
herramientas integradas en entornos CASE3 y finalmente precaria preparación
entre sus usuarios potenciales.
La verificación y validación del modelo conceptual exigen disponer de algún
formalismo preciso y a la vez con la suficiente capacidad expresiva, necesaria
para capturar los aspectos de interés del problema. En la práctica, los requisitos del usuario son representados mayoritariamente usando modelos semiformales, incluidos en los enfoques más populares en la actualidad, entre ellos los métodos no orientados a objeto [41, 101] y los orientados a objeto
[81, 10, 42, 62, 87, 31]. Notacionalmente los métodos orientados a objeto más
conocidos han sido integrados en el Unified Modeling Languaje (UML) [78].
2
3
http://sunsite.informatik.rwth-aachen.de/CREWS/
Computer Aided Software Engineering.
10
CAPÍTULO 2. ANTECEDENTES
OASIS es un enfoque orientado a objeto y formal para la especificación
de modelos conceptuales de sistemas de información. En OASIS un sistema
de información es visto como una sociedad de objetos autónomos y concurrentes que se comunican entre sí a través de acciones. OASIS en su primera
versión [69] fue formalizado a través de Teorías de Primer Orden que evolucionan con el tiempo. Este enfoque lo situó históricamente en un entorno de
Programación Lógica complementado con un monitor para la gestión de la
perspectiva dinámica del sistema. A partir de la segunda versión [70] se cambió de marco formal y se trabajó en el contexto de una variante de Lógica
Dinámica [30] que permite representar los operadores de obligación, prohibición y permiso usados en Lógica Deóntica [2]. En este marco, OASIS tiene
una base formal más adecuada desde el punto de vista de su comprensión,
manteniendo sus buenas propiedades.
Otros enfoques formales con una motivación similar a la de OASIS son:
TROLL [43], LCM [22], ALBERT [19], OBLOG [67] y TESORO [93]. Sin
entrar en detalles de comparación, sólo se destacará que a diferencia de otros
enfoques formales, en OASIS desde sus primeras versiones se ha puesto especial
interés en tres aspectos esenciales que facilitan su integración en entornos
industriales de desarrollo de software:
Construcción de herramientas que soporten el proceso de modelado conceptual. Se ha construido un entorno CASE basado en la versión precedente de OASIS y adaptado a OO-METHOD [71].
Establecimiento de un método de desarrollo basado en OASIS, llamado
OO-METHOD [72].
Generación automática de código a partir de especificaciones OASIS, orientada tanto a la validación (interés de esta Tesis) como a la construcción
del producto final [73].
Por otra parte, si se compara el procedimiento seguido por las propuestas
semiformales para modelado orientado a objeto más populares respecto del enfoque que se ha seguido en el desarrollo de OASIS, se puede observar que son
contrapuestos. En OASIS un aspecto importante ha sido el reducir la notación
y técnicas a un conjunto pequeño y coherente, con la suficiente expresividad y
con un significado preciso, evitando así problemas de “interferencia semántica”
[67] entre los diferentes aspectos del lenguaje. Esta estrategia es opuesta a la
seguida en el desarrollo de UML, en el cual se han fundido varias notaciones
para posteriormente intentar establecer una interpretación y un método de
aplicación globales. En el caso de OASIS, después de establecer los conceptos
fundamentales es relativamente sencillo establecer una notación o buscar alguna entre las notaciones existentes y adaptarla, incluso se puede utilizar parte
de la notación de UML.
2.1. CONTEXTO DEL TRABAJO
2.1.4.
11
Validación y verificación
La noción de corrección para el software está inherentemente limitada. Para
abordar un sistema basado en computador debe comprenderse su hardware,
software y entorno, y cómo ellos interactúan. En la medida que los sistemas
de información a desarrollar son más complejos han quedado en evidencia
las deficiencias en su proceso de construcción. En particular es reconocida
la dificultad para verificar sistemas concurrentes y/o distribuidos. Cada vez
existe mayor preocupación respecto de los posibles daños por errores en sistemas de información, más aún cuando se trata de posibles problemas para
las personas (safety critical systems). Estos factores de complejidad se presentan frecuentemente en sistemas de tiempo real y/o empotrados. Se trata pues
de una cuestión de confiabilidad asociada a la calidad del producto software
construido. La validación y verificación del producto desempeñan un papel esencial para asegurar la calidad del software. La validación y verificación (V &
V) son las tareas encargadas de asegurar la calidad del producto de software
y se definen como [9]:
Validación: ¿Estamos construyendo el producto correcto?, es decir, comprobar que el sistema reúne las expectativas del usuario.
Verificación: ¿Estamos construyendo correctamente el producto?, es decir, comprobar que el sistema satisface su especificación.
Si la validación y verificación no son las adecuadas, los errores en los requisitos se propagarán hacia las fases posteriores. El costo de modificar un sistema
debido a un error en los requisitos es mucho mayor que el costo de reparar un
error de programación, puesto que existe un efecto de amplificación del impacto del error al pasar de una fase a otra. Así, mientras más tarde se corrija
un error más costoso resulta repararlo.
Las técnicas para validación y verificación pueden clasificarse en [91]:
Técnicas estáticas: se centran en el análisis y comprobación de la representación del sistema, incluyendo documentos, diagramas y código.
Técnicas dinámicas: implican ejecutar algún tipo de implementación del
sistema.
Podría parecer que sólo con las técnicas estáticas es suficiente pero esto
no tiene sentido puesto que las técnicas estáticas se orientan más bien a la
verificación, no pueden demostrar que el sistema satisface las expectativas del
usuario (validación). En este trabajo de Tesis el interés es utilizar técnicas
dinámicas para la validación del modelo conceptual.
12
CAPÍTULO 2. ANTECEDENTES
La prototipación y las pruebas de programas son técnicas dinámicas. En
ambos casos es importante tener presente la célebre frase de W. Dijkstra:
“las pruebas pueden demostrar la presencia de errores pero no su ausencia”.
En prototipación normalmente se cuenta con una implementación parcial (en
algún sentido) del sistema, en cambio las pruebas del programa se realizan
sobre todo o parte del producto ya construido. Las pruebas de programa son
útiles principalmente para la verificación del sistema. Dentro de los diferentes
tipos de pruebas, las pruebas de aceptación (pruebas alfa) y las pruebas beta
son las que más información aportan para la validación del sistema.
A continuación se presenta una clasificación de técnicas específicas para la
validación de modelos conceptuales [21]:
Técnicas de conversión: presentan el modelo conceptual en una forma
más fácil de comprender por el usuario.
Técnicas de comportamiento: presentan una ejecución de la especificación, lo que permite en un sentido amplio observar y experimentar
propiedades de la especificación. La prototipación se incluye en este
grupo.
Técnicas de análisis: se basan en el estudio de trazas posibles obtenidas
de la especificación y contrastadas con el comportamiento esperado. Para
obtener trazas de la especificación puede utilizarse una técnica de comportamiento.
En cualquier técnica de validación es necesario contrastar en algún sentido
la especificación con los requisitos informales del usuario. Lo más inmediato
es incluir al usuario en el proceso de validación y utilizar técnicas de conversión junto con técnicas de comportamiento. Sin embargo, este enfoque no
aprovecha necesariamente el trabajo previo a la construcción del modelo, es
decir, lo realizado durante la captura de requisitos. El problema principal es
que la captura de requisitos es una tarea muy informal. En este sentido, la
utilización de una técnica de escenarios para la captura de requisitos puede
ayudar en la validación del modelo conceptual. Se trata de comprobar que el
modelo al menos tiene la funcionalidad establecida por el conjunto de escenarios. Este enfoque podría enmarcarse dentro de las técnicas de análisis. Para
poder efectuar dicha comprobación es necesario que los escenarios y el modelo
conceptual sean comparables en algún sentido. De todas formas, es importante
considerar que el conjunto de escenarios puede que no represente por completo
a los requisitos del sistema.
2.1. CONTEXTO DEL TRABAJO
2.1.5.
13
Prototipación y animación
Las dificultades encontradas para validar con mayor precisión el modelo
conceptual del sistema han impulsado la utilización de técnicas de prototipación. La existencia de errores y omisiones constituye un riesgo significativo
en el modelado conceptual. Los objetivos de un prototipo pueden ser: determinar las interfaces, validar los requisitos funcionales y/o demostrar la factibilidad del sistema. Un argumento común contra la prototipación es su costo, el
cual puede ser considerable.
Normalmente, el prototipo exhibe sólo algunos aspectos del sistema, dejando de lado otros como eficiencia, seguridad, confiabilidad, etc. Un prototipo
puede orientarse a ilustrar detalles de ciertas partes de la funcionalidad total
(propotipado vertical) o mostrar toda la funcionalidad sin llegar a implementar
funciones específicas (prototipado horizontal). En la práctica ambos enfoques
se mezclan.
Por otra parte, los prototipos pueden clasificarse en prototipos desechables
y prototipos evolutivos. El objetivo de un prototipo desechable es capturar y
validar los requisitos del usuario, una vez cumplido este propósito el prototipo
es desechado. En este caso el prototipo es construido desde una especificación
obtenida experimentalmente y modificada hasta obtener la conformidad del
usuario. Con un prototipo evolutivo se pretende llegar a la versión definitiva
del producto mediante refinamientos sucesivos.
Algunas herramientas para construcción de prototipos son: lenguajes de
especificación ejecutables, lenguaje de muy alto nivel y generadores de aplicaciones en lenguajes de cuarta generación. La utilización de un lenguaje de
especificación ejecutable y formal resulta particularmente atractiva pues combina una especificación no ambigua con prototipación, sin haber costos adicionales una vez que la especificación ha sido escrita. La prototipación de una
especificación orientada a la validación de requisitos, se denomina “animación”
[33, 21, 89].
Desde el punto de vista de la validación de requisitos, con un prototipo podrían realizarse dos formas de validación: “validación dirigida” y “validación
exploratoria”. La validación dirigida utiliza el prototipo para recrear cada uno
de los escenarios establecidos. La validación exploratoria intenta descubrir un
comportamiento no deseable mediante simple interacción con el prototipo. La
prototipación tradicional permite sólo validación exploratoria pues generalmente el prototipo provee la interfaz del producto final, sin ofrecerse mecanismos que permitan concentrarse en acciones acontecidas o facilitar la observación del estado de los objetos. Para efectuar adecuadamente una validación
dirigida es conveniente disponer de un entorno de animación que interactúe
con el prototipo ofreciendo al analista una interfaz estándar y específicamente
diseñada para ayudar en este tipo de validación.
14
2.1.6.
CAPÍTULO 2. ANTECEDENTES
Programación automática
El paradigma de programación automática enunciado por Balzer [3, 4]
parece estar en su apogeo, aunque no siempre basado en métodos formales,
como se propuso originalmente, sino más bien en métodos semiformales. La
generación automática de código a partir de especificaciones (preferentemente
gráficas) es un tema actual de gran interés en ingeniería de software. La automatización de las fases del desarrollo ha determinado una tendencia histórica
en la evolución del proceso de desarrollo de software, según la cual actividades
realizadas inicialmente de manera informal son mas tarde formalizadas y finalmente automatizadas (con poca o ninguna intervención del desarrollador)
[16]. La generación de código a partir de modelos conceptuales no es más que
la continuación de dicha tendencia. El desarrollo de software se concentra cada
vez más en la parte más creativa e irreemplazable (no automatizable completamente) del proceso, es decir, el análisis y la especificación del sistema.
Para la mayoría de los métodos semiformales se han construido entornos
CASE que permiten llevar a la práctica su perspectiva de ingeniería del software. En ellos, la posibilidad de conseguir automáticamente código ejecutable
es una característica muy valorada. El resultado conseguido va desde plantillas de código y definiciones de bases de datos hasta aplicaciones completas
incluyendo el código compilado y la creación de la base de datos [79, 76]. Sin
embargo, el software obtenido sigue padeciendo los mismos defectos asociados
al proceso de desarrollo sin automatización. La razón es que en la mayoría de
los casos la manera de construir los sistemas no se cambia, sólo se automatizan
técnicas y procedimientos cuyo rigor es cuestionable.
Desiciones
Especificación
Informal
Especificación
Especificación
de alto nivel
(prototipo)
Desarrollo
Formal
Tranformación
Interactiva
Especificación
de bajo nivel
Transformación
Automática
Código
Fuente
Optimización
Validación de
Especificación
Mantenimiento
Figura 2.1: Paradigma de programación automática
La Figura 2.1 (extraída desde [4]) ilustra un paradigma ideal de programación automática. Se distinguen dos fases globales: especificación (incluyendo
2.1. CONTEXTO DEL TRABAJO
15
validación) y transformación. Las características principales de este paradigma son: la especificación es formal y ejecutable (constituye el primer prototipo
del sistema), la especificación es validada mediante prototipación, a través de
transformaciones formales la especificación se convierte en la implementación
del sistema, en el último paso de transformación se obtiene una implementación
en un lenguaje de programación determinado, las pruebas que verifican la correspondencia con la especificación no son necesarias, el mantenimiento se realiza sobre la especificación (no sobre el código fuente), la documentación es
generada automáticamente y el mantenimiento es realizado por repetición del
proceso (no mediante parches sobre la implementación).
La capacidad de ejecución de una especificación ha sido tema de debate,
contando con simpatizantes [24] y detractores [35]. Una de los aspectos más
cuestionados es la conveniencia de eliminar la mítica frontera entre especificar
el “qué” y el “cómo” [88] que históricamente ha diferenciado análisis respecto del diseño del sistema. Una especificación ejecutable tiene inevitablemente
que incorporar ciertos aspectos asociados comúnmente a decisiones de diseño.
Sin embargo, la falta de ejecutabilidad hace que una especificación de análisis requiera mucho trabajo para convertirla en una especificación de diseño.
En este sentido, el paradigma propuesto por Balzer es conciliador de ambas
posturas pues está basado en transformaciones sucesivas de la especificación
hasta obtener una implementación definitiva. Inicialmente la especificación es
informal y no ejecutable, a continuación pasa a ser formal y ejecutable, posteriormente mediante refinamientos formales sucesivos llega a ser el producto
final, manteniendo la equivalencia semánticamente respecto de la especificación
original.
En [5] se hace una clasificación del estado actual en generación automática de código a partir de modelos, estableciendo tres enfoques: estructural,
de comportamiento y de traducción. En el enfoque estructural la generación
de código es incompleta y se centra en los aspectos de estructura del código. Este enfoque es el que más se ajusta a la mayoría de las metodologías
orientadas a objeto en las cuales se hace un desarrollo incremental pasando
en forma gradual desde análisis a diseño y posteriormente a código. El enfoque de comportamiento se basa en añadir especificaciones de acciones a los
diagramas de transición de estado, lo cual asociado a los modelos de objetos y de comunicación permite generar código que puede ser ejecutado. Sin
embargo, el código generado no suele ser la versión definitiva. El enfoque de
traducción está basado en establecer un modelo de aplicación y uno de arquitectura, ambos independientes. El modelo de la aplicación determina para los
objetos su estructura, comportamiento y comunicación. El modelo de arquitectura es un conjunto de reglas que traducen los constructores del modelo
de aplicación en código fuente considerando aspectos específicos del entorno
de implementación. El enfoque de traducción es el que incluye mayor grado
16
CAPÍTULO 2. ANTECEDENTES
de automatización. Sin embargo, no es sencillo definir un modelo de arquitectura específico, existen muchos factores en un entorno de implementación que
hacen necesario combinar conocimientos técnicos de diversas áreas (lenguajes
de programación, sistemas operativos, redes, etc.).
2.2.
Descripción del trabajo de Tesis
De acuerdo con lo presentado en la sección anterior, este trabajo de Tesis
se sitúa en un marco que combina lo siguiente:
Utilización de OASIS como enfoque formal para el modelado conceptual
orientado a objeto.
Animación automática de especificaciones OASIS. A partir de una especificación OASIS se obtiene automáticamente un prototipo del sistema, orientado exclusivamente a la validación del modelo conceptual.
Es decir, se aborda sólo la primera fase del paradigma de programación
automática de Balzer.
Captura de requisitos usando alguna técnica de escenarios con el propósito de facilitar la comparación de los requisitos respecto del comportamiento exhibido por el prototipo.
Técnicas para la validación de modelos conceptuales, en particular se
trabajará con una técnica que según las clasificaciones mencionadas se
cataloga, por una parte como técnica dinámica y por otra, como una
técnica tanto de comportamiento como de análisis.
La Figura 2.2 ilustra un proceso de modelado conceptual en OASIS, orientado a la validación mediante animación de un prototipo generado automáticamente. En la captura de requisitos se considera la utilización de alguna
técnica para representación de escenarios. El analista extrae desde conjunto
de escenarios los elementos de especificación que conformarán la especificación
de requisitos. En este aspecto, es importante destacar que el determinar un
comportamiento general a partir de ejemplos no es una tarea sencilla y la calidad del resultado depende de la capacidad del analista. Para la representación
del modelo conceptual se utilizan técnicas principalmente gráficas que guardan
una correspondencia directa con elementos de una especificación OASIS. Así,
para el analista resulta implícita la utilización de OASIS, más aún si se utiliza
una notación gráfica basada, por ejemplo en UML y utilizando sólo los elementos de UML que sean útiles desde el punto de vista de OASIS. La verificación
de consistencia del modelo conceptual consiste en comprobar las restricciones
del modelo OASIS. Gracias a utilizar un modelo formal es posible realizar una
2.2. DESCRIPCIÓN DEL TRABAJO DE TESIS
Validación
mediante animación
Captura de
requisitos
?
17
Escenarios
Análisis y
Especificación
Mapade revisón de gestión
ISO 9001:1994 Claúsula 4.1
{Jefe deplanta}
Verificación de
consistencia
EtQ9000Maps 
Mapas de referencia:
1
Prepararel orden
del día
Acción
correctiva
2
{Secretaria}
Usuario
Registros
Distribuir el orden del
de calidad
día al equipo de
revisión de gestión
Definiciones:
Indicador- Una medida cuantitativa
del funcionamiento de un proceso de
sistema de calidad.
3
CAR - Solicitud de acción correctiva
{Equipo de revisión
de gestión}
Revisar las actas de las
reuniones anteriores
para resolver la CAR
Objetivo- Objetivo cuantitativopara
un proceso de sistema de calidad.
{Jefe de planta}
5
{Equipo de revisión
de gestión}
4
¿Requisito
Sí
Designa personal
pararesolver el
Requisitos:
Indicadores del sistema de calidad:
Los ejemplos incluyen:
- Pasos en la obtención de la
Certificación de calidad o formulación
de la misión
requisito anterior de
la CAR
anterior?
- Demanda de calidad
- Resumen del material no apto
- Resumen de las quejas del consumidor
No
{Equipo de revisión
de gestión}
6
7
Revisa los
- Resumen de la auditoría interna
- Resumen de las existencias
de material
- Entregaa tiempo
- Resumen de la acción correctiva
Registra elementos
del requisito anterior
indicadores del
sistema de calidad
y nombramientos en
lasactas de la
reunión
vs.objetivos
Traducción
automática
Mapasasociados:
{Secretaria}
Ninguno
9
{Equipo de revisión
de gestión}
8
¿Indicadores
en objetivo?
No
{Equipode revisión
de gestión}
Da prioridad a los
indicadores fuera del
objetivo
Sí
10
12
{Secretaria}
Elabora (CAR)basado
Hace constar los
{Jefe de calidad}
en las prioridades y
recursos por mapa de
indicadoresobjetivo
en las actas de la
reunión
acción correctiva
13
Dos veces al año, hace
{Secretaria}
11
constar la conclusión de
efectividad del sistema de
calidad en lasactas de a
l
Hace constar los
{Secretaria}
indicadores fuera del
objetivo y
reunión
nombramientos en las
actas de lareunión
Ayuda/Acerca
de EtQ 9000
Maps
A
Correspondencia
implícita
A
{Equipode revisión
de gestión}
15
14
{Directorde planta}
¿Resultaadecuada
la frecuencia de
reuniones para la
No
Establecer nueva
frecuencia
revisión de gestión?
Sí
16
{Equipo de revisión
de gestión}
Acordar lafecha y el
orden del día de la
próximareunión
17
{Secretaria}
Elaborar/distribuir
actas dela reunión
18
{Secretaria}
Archivar lasactas de la
reunión por mapa de
registrosde calidad
Requisitos
Modelo
OASIS
Prototipo
para
animación
Figura 2.2: Modelado conceptual basado en OASIS
verificación exhaustiva del modelo mediante técnicas estáticas. Mediante un
traductor, a partir del modelo conceptual OASIS se genera un prototipo orientado a la validación del modelo conceptual. El prototipo está codificado en un
lenguaje concurrente y con una base formal. El analista puede interactuar directa o indirectamente (por lotes) con el prototipo, introduciendo y observando
las acciones acontecidas y los estados alcanzados por los objetos del sistema.
La actividad de validación es llevada a cabo contrastando el comportamiento
esperado del prototipo (determinado por el conjunto de escenarios) respecto
del comportamiento exhibido por la animación de la especificación. Es importante que la representación de escenarios se aproxime a una descripción de
trazas de acciones y estados alcanzados, de esta forma el analista tendrá que
realizar menos esfuerzo para validar el comportamiento del prototipo respecto
del conjunto de escenarios. Si existe una compatibilidad adecuada entre ambas representaciones se puede establecer un apoyo automatizado para dicha
comparación.
La propuesta descrita tiene las particularidades siguientes:
El usuario no interviene directamente en la validación. El analista de
forma manual o con asistencia automática procede a la comparación de
los escenarios utilizando el prototipo. Sin embargo, no se descarta la
utilización de otras técnicas de validación, incluyendo por ejemplo prototipos orientados a la definición de las interfaces del sistema o técnicas
de conversión.
18
CAPÍTULO 2. ANTECEDENTES
Pueden realizarse dos formas de validación: “validación dirigida” y “validación exploratoria” (ambas descritas anteriormente).
La validación podría comenzar apenas se disponga de una versión del
modelo conceptual. Para la generación automática sólo debe verificarse
que el modelo conceptual sea consistente y completo (al menos de acuerdo con lo mínimo establecido para efectuar la generación automática del
prototipo). Del mismo modo, el modelo podría ser validado por partes,
generando prototipos para cada parte.
El prototipo es generado en un lenguaje que ofrece la posibilidad de
justificar las correspondencias entre el modelo conceptual y el prototipo
generado, es decir, es posible determinar en algún grado la equivalencia
funcional del prototipo respecto de la especificación OASIS. En este sentido, gracias a utilizar un lenguaje concurrente en la implementación es
posible prescindir de la incorporación de un monitor que controle la actividad de los objetos y obscurezca las correspondencias entre el modelo
conceptual y el prototipo.
Usando como marco de referencia el contexto planteado, el alcance de esta
Tesis se resume en el siguiente párrafo:
Se han establecido las bases teóricas y prácticas para la animación automática de especificaciones OASIS en un entorno de programación concurrente. Se ha construido una versión preliminar de un ambiente en el cual, a
partir de un modelo conceptual en OASIS, se obtiene de forma automática un
prototipo que ayuda a la validación de requisitos. Para la implementación del
prototipo se ha utilizado Programación Lógica Concurrente.
2.3.
Trabajos relacionados
La mayoría de las herramientas CASE comerciales4 incluyen en alguna
medida generación automática de código, principalmente en lenguajes imperativos y en especial C++. Resulta difícil establecer con precisión la calidad
del código generado automáticamente sin probar la herramienta. Como suele
suceder, existe una notable diferencia entre la información ofrecida por el
proveedor y las verdaderas cualidades de la herramienta. Además, por ser
un tema candente, las frecuentes nuevas versiones de las herramientas dejan
obsoleta cualquier comparación. Sin embargo, tomando como referencia la experiencia del autor en el uso de algunas herramientas CASE y mediante una
tarea de búsqueda en la Web, a continuación se presentan algunos comentarios
4
http://www.incose.org/tools/toolsbyname.html y
http://www.qucis.queensu.ca/Software-Engineering/tools.html
2.3. TRABAJOS RELACIONADOS
19
que reflejan el estado del arte desde la perspectiva de los propuestas existentes
en el ámbito académico y comercial.
Rational Rose de Rational5 (en la que participan Booch, Jacobson y Rumbaugh) genera plantillas de código muy elementales (siguiendo el enfoque estructural para la generación de código). Dos herramientas que usan el enfoque
de comportamiento para generación de código son: Rhapsody de I-Logix6 (relacionada con Harel) y ObjecTime7 (incluye ROOM, Real-Time Object-Oriented
Method). En estas herramientas es posible obtener prototipos ejecutables a
partir de los modelos establecidos.
Varias herramientas proveen un lenguaje de scripts mediante el cual se
puede adaptar la generación de código a distintos estilos y arquitecturas de
programación para una determinada configuración hardware-software (coincidiendo así con el enfoque de traducción para la generación de código). Así el
grado de automatización conseguido depende de la calidad del script utilizado.
Este es el caso de System Architect de Popkin Software & Systems8 que trae
predefinido un conjunto de scripts muy rudimentarios para generar código en
varios lenguajes, pero que tienen que ser modificados en gran medida para
obtener un resultado útil. En OBLOG9 se dispone de un editor de reglas de
traducción, sin embargo, el lenguaje utilizado no resulta muy amigable. En
BridgePoint de Project Techonology Inc.10 (relacionada con Shlaer y Mellor
y su propuesta metodológica) se ofrece como módulo adicional un conjunto
de arquitecturas (llamadas model compilers que incluyen reglas de traducción
y librerías) específicas para distintos entornos y usadas como entrada para
el proceso de generación de código. Un enfoque similar utiliza OO-METHOD
CASE, en el cual la traducción se orienta hacia un producto final considerando
una determinada arquitectura, pero sin posibilidades de ser modificada por el
usuario de la herramienta.
Por otra parte, y centrándose exclusivamente en la validación de requisitos
mediante animación de la especificación, pocas herramientas proporcionan una
ayuda de este tipo. Aunque algunas herramientas son capaces de generar un
prototipo ejecutable normalmente no se ofrecen facilidades específicas para la
validación utilizando dicho prototipo. La razón es que en la mayoría de los casos el objetivo perseguido es la generación del producto final, con lo cual el prototipo no está pensado para facilitar la validación de requisitos. Una excepción
la constituyen algunas herramientas cuyo ámbito de aplicación incluye sistemas
de tiempo real y sistemas empotrados. Entre ellas se puede incluir a Rhap5
http://www.rational.com
http://www.ilogix.com
7
http://www.objectime.com
8
http://www.popkin.com
9
http://www.oblog.pt
10
http://www.projtech.com
6
20
CAPÍTULO 2. ANTECEDENTES
sody, ObjecTime y BridgePoint (en OBLOG existe un módulo de animación
pero aún no está comercialmente disponible). En Rhapsody y ObjecTime (y
en OBLOG, pero aún en construcción) se incorpora una representación gráfica
en diagrama de secuencia en el cual se representan escenarios como secuencias de las interacciones entre objetos a través del tiempo. En este sentido,
Aonix11 proporciona un módulo llamado “Validator” que incorpora edición,
ejecución y evaluación de escenarios. En estos productos el proceso de validación se dirige a contrastar trazas obtenidas por ejecución del prototipo. En
ObjecTime se provee de un procedimiento para contrastar automáticamente
escenarios así especificados. En BridgePoint la validación se realiza monitoreando el prototipo en distintos niveles (acción, sentencia y componente) pero es
difícil determinar variaciones respecto al comportamiento esperado pues la interfaz y el enfoque seguido se acercan más a la funcionalidad de un depurador
de código fuente. Estas propuestas presentan el inconveniente de estar basadas
en modelos donde el comportamiento es especificado de forma imperativa con
lo cual la validación debe establecerse en un nivel de abstracción bastante más
bajo que el presente en el espacio del problema. El caso de OBLOG podría
ser una excepción puesto que se originó en un contexto formal y declarativo,
sin embargo, no se ha contado con información para poder constatar si dichas
características se mantienen en la versión comercial.
Desde la perspectiva de captura de requisitos usando técnicas para especificación de escenarios también existen trabajos relacionados. En [44] mediante
un algoritmo se sintetizan diagramas de estados a partir de escenarios. Los escenarios son introducidos en forma incremental, comprobando su consistencia
a través de animación de los diagramas de estados ya obtenidos. Un trabajo similar pero más orientado a la verificación del conjunto de escenarios se
presenta en [90], donde además se introducen de restricciones de tiempo asociadas a las transiciones del diagrama de estados. Otras propuestas también
orientadas a validación de requisitos usando escenarios son [61, 23]. En general
en los trabajos antes indicados el interés se centra en el proceso de captura de
requisitos mediante escenarios y la validación de los escenarios en sí mismos,
es decir, la posterior elaboración y validación del modelo conceptual asociado
quedan fuera de consideración.
En los últimos años se ha registrado gran interés en torno a la validación de
especificaciones formales mediante su animación [89]. Los trabajos más próximos al desarrollado en esta Tesis corresponden a propuestas para validación
mediante animación en lenguajes formales cercanos en motivación a OASIS,
por ejemplo los trabajos de animación en TROLL, en ALBERT y en TESORO.
En lo que respecta a TROLL, en [33] se establecieron los conceptos y una
arquitectura general para dar soporte de animación a una especificación en di11
http://www.aonix.com
2.3. TRABAJOS RELACIONADOS
21
cho lenguaje. Posteriormente, en [26] se bosqueja un ambiente para animación
de especificaciones TROLL ligth (un dialecto de TROLL). En [36] se describe
un prototipo muy preliminar de dicho ambiente, en el cual es posible explorar
el estado de objetos, introducir ocurrencias de eventos y visualizar cambios de
estado. Finalmente uno de los últimos trabajos de los que se tiene constancia
es [28], en el cual no parece haber adelantos significativos respecto de las publicaciones anteriores. En cuanto a ALBERT, en [21] se presenta el diseño (en
términos muy generales) de un ambiente para animación de especificaciones
ALBERT. En [37] se propone comprobar escenarios respecto de la animación
de una especificación ALBERT y se establece un proceso de validación basado en animación. En [38] se describe la funcionalidad y arquitectura para un
módulo de animación de especificaciones ALBERT, además se presenta un
prototipo muy rudimentario de una herramienta, donde la principal novedad
respecto a trabajos anteriores en ALBERT es el manejo de varias sesiones de
animación a la vez, posibilitando la validación cooperativa de escenarios. En
[34] se describe un método que integra captura de requisitos basada en escenarios junto con validación mediante animación. Finalmente, en TESORO se han
realizado algunos trabajos de prototipación pero orientados específicamente
al estudio de protocolos de comunicación [13]. En resumen, en los enfoques
cercanos a OASIS aunque existen precedentes en animación (automática en
algunos casos), aún no existen resultados consolidados en lo que se refiere a
herramientas disponibles, los entornos descritos son de carácter preliminar.
Al contrastar los resultados presentados con las arquitecturas y funcionalidad
preestablecidas en las publicaciones analizadas queda en evidencia que todavía
hay mucho trabajo por realizar. Además, es importante destacar que en las
publicaciones antes referenciadas no se proporcionan detalles del enfoque ni
modelo de implementación utilizado, en este aspecto sólo se indica su existencia utilizando términos como TROLL-Kernel o ALBERT-Core.
En el caso de OASIS se ha desarrollado una herramiena CASE (OOMETHOD CASE) basada en OO-METHOD. Sin embargo, tanto en OOMETHOD y como en el CASE asociado el esfuerzo se ha concentrado en la
obtención automática del producto final (y en lenguaje imperativos). De esta
forma, sólo es posible realizar validación exploratoria sobre el producto final.
Por lo tanto, además del trabajo desarrollado en esta Tesis, no existen precedentes en lo que respecta a técnicas específicas para la validación de modelos
conceptuales OASIS mediante animación automática. Con la realización de
esta Tesis, en este aspecto OASIS queda en una situación favorable respecto
de TROLL y ALBERT.
22
CAPÍTULO 2. ANTECEDENTES
Capítulo 3
OASIS
En este capítulo se presentan los conceptos básicos de OASIS, para mayores
detalles tanto de aspectos teóricos o del lenguaje asociado consultar en [56]. El
punto de partida para la realización de esta Tesis fue OASIS en su versión 2.2.
Sin embargo, en el desarrollo de este trabajo surgieron propuestas de mejoras
y extensiones que impulsaron en gran medida el establecimiento de la nueva
versión OASIS 3.0. Estos aspectos, como aportes adicionales, serán tratados en
mayor detalle en los siguientes capítulos donde se presentan: la incorporación
de la perspectiva cliente, la interpretación homogénea de las especificaciones
de procesos en el marco formal de la Lógica Dinámica utilizada y la interacción
entre objetos.
Una especificación OASIS es una presentación de una teoría en el sistema
formal usado, expresada como un conjunto estructurado de definiciones de
clase. Las clases pueden ser simples o complejas. Una clase compleja es aquella que en su definición utiliza la definición de otras clases (simples o complejas). Las clases complejas se definen utilizando operadores de clase. Estos son
agregación y herencia.
Una clase se compone de un nombre de clase, uno o más mecanismos de
identificación para instancias de la clase (objetos) y un tipo o plantilla que
comparten todas las instancias. La plantilla recoge las propiedades de estructura y de comportamiento compartidas por todos los objetos potenciales de
la clase considerada. Para una clase simple todas las propiedades quedan establecidas en su plantilla. Para una clase compleja, además de las propiedades
establecidas por su plantilla, existirán propiedades adicionales determinadas
por las relaciones entre clases que la definen.
23
24
3.1.
CAPÍTULO 3. OASIS
Plantilla o tipo
Definición 1 Plantilla o tipo. Una plantilla de clase está representada por
una tupla hAtributos, Eventos, F órmulas, P rocesosi.
Atributos es el alfabeto de atributos. ∀att ∈ Atributos, se tiene la función
att : sort de nombrado → sort de evaluación
Eventos es el alfabeto genérico de eventos. ∀e ∈ Eventos podemos
obtener e= θe siendo θ una substitución básica de los posibles parámetros del evento.
F órmulas es un conjunto de fórmulas en diversas lógicas según sea la
sección del lenguaje donde se utilizan.
P rocesos es el conjunto de especificaciones de proceso. Cada proceso se
especificará usando un cálculo de procesos basado en un subconjunto del
lenguaje propuesto en CCS [65]. Las especificaciones de proceso serán
divididas en operaciones y protocolos.
Definición 2 Servicio. Un servicio es un evento o una operación. En el
primer caso se trata de un servicio atómico e instantáneo. Una operación es
un servicio no atómico y que, en general, tiene duración.
Definición 3 Acción. Una acción es una tupla hCliente,Servidor,Servicioi,
que representa tanto la acción asociada a requerir el servicio en el objeto cliente
como la acción asociada a proveer el servicio en el objeto servidor.
El concepto de acción involucra tres elementos: un objeto cliente, uno o más
(en caso de broadcast) objetos servidores y el servicio requerido desde el cliente
al servidor (o servidores). En el objeto cliente ocurre la acción por solicitar
el servicio al objeto servidor. Para la misma acción en el objeto cliente, en el
objeto servidor ocurre la acción de proveer el servicio solicitado o la acción de
rechazar dicha solicitud.
Para cada clase, asumiremos la existencia implícita de un conjunto A de
acciones obtenido a partir de los servicios que los objetos de la clase pueden
requerir (cuando son clientes) o proveer (cuando son servidores). Al igual que
para los eventos, ∀a ∈ Acciones podemos obtener a= θa siendo θ una substitución básica de los posibles cliente, servidor y servicio.
3.2.
Ciclo de vida de un objeto
Un objeto tiene dos aspectos: estructura (determinada por sus atributos)
y comportamiento (aspecto asociado a las acciones que le acontecen).
3.2. CICLO DE VIDA DE UN OBJETO
25
Definición 4 Atributo. Un atributo es un par hnombre, sort de evaluacióni,
siendo nombre el identificador del atributo y sort de evaluación el nombre del
conjunto soporte (carrier) o valores que puede tomar dicho atributo.
Definición 5 Atributo evaluado. Un atributo evaluado es un par hnombre,
valori, siendo nombre el identificador usado para referirse al atributo y valor
∈ carrier(sort(nombre)). Si el valor de un atributo no cambia durante la vida
del objeto diremos que el atributo es constante, en caso contrario el atributo
es variable.
Definición 6 Estado del objeto. Llamaremos estado del objeto al conjunto
de sus atributos evaluados. Se expresa normalmente mediante Fbfs de una
lógica de primer orden.
Ejemplo 1 El estado de un objeto de la clase válvula podría ser:
abierta=true y caudal=50.
Ejemplo 2 El estado de un objeto de la clase coche podría ser:
matricula= A-6065-CK, velocidad=80 y
temperatura_del_motor=normal.
El estado permite caracterizar a un objeto en un instante determinado.
Sea Σ el conjunto de estados1 alcanzables por un objeto y σ ∈ Σ un estado en
particular. El estado de un objeto cambia por la ocurrencia de acciones2 . Los
cambios de estado son modelados por la siguiente relación:
efecto : A → (Σ → Σ)
Donde A es el conjunto de acciones instanciadas (a ∈ A) que le pueden
acontecer al objeto y ef ecto es la función cambio de estado atómico que produce la ocurrencia de una acción. En un mismo instante de tiempo, a un objeto
le puede acontecer más de una acción.
Definición 7 Conjunto consistente de acciones. Un conjunto de acciones M ⊆ A es consistente si a partir de un estado σ dado, el estado σ0
alcanzado por la ocurrencia de todas las acciones en M es siempre el mismo,
independiente del orden en el cual se ejecuten3 las acciones.
P
Los estados son fórmulas. El conjunto
corresponde a estructuras de interpretación
(mundos) de dichas fórmulas, aunque por sencillez hablaremos de estados.
2
Se considerará la frame assumption, es decir, supondremos que si no se especifica que
la modificación del valor de un atributo se debe a la ocurrencia de una determinada acción,
entonces dicho atributo no es modificado por dicha acción.
3
Se utilizará “ejecución de acción” como sinónimo de “ocurrencia de acción” para hacer
más intuitiva la presentación. Sin embargo, desde el punto de vista declarativo y formal,
“ocurrencia” es el término más adecuado.
1
26
CAPÍTULO 3. OASIS
Definición 8 Paso. Llamaremos paso a un conjunto consistente de acciones
que ocurren en un mismo instante de la vida del objeto.
Sea µ = {a1 , ..., an } ⊆ A un paso. La relación de accesibilidad entre estados
está determinada por µ, Rµ ⊆ Σ × Σ y se define como (siendo “◦” el símbolo
de composición funcional) :
def
Rµ (σ) ≡ efecto(a1 )(σ) ◦ ... ◦ efecto(an )(σ) = σ0
De acuerdo con la definición de conjunto consistente, el orden en el cual se
aplica la función efecto a las acciones no altera el estado siguiente alcanzado
por el objeto.
Definición 9 Vida o traza de un objeto. Llamaremos vida o traza de un
objeto a un prefijo finito de pasos que le acontecen al objeto. De esta forma,
la traza es una caracterización alternativa del estado del objeto en un instante
determinado.
A las vidas maximales las llamaremos ciclos de vida. En OASIS, el modelado del comportamiento puede realizarse desde dos perspectivas complementarias en cuanto a expresividad. En cada instante, para un objeto, las acciones
permitidas y las acciones obligatorias pueden ser establecidas de la siguiente
forma:
Considerando el estado del objeto en dicho instante. Las precondiciones
son fórmulas que permiten la ocurrencia de acciones sólo en ciertos estados del objeto. De forma análoga, los disparos son fórmulas que obligan
la ocurrencia de acciones en determinados estados del objeto.
Considerando las acciones ya acontecidas. Una especificación de proceso
determina un patrón de comportamiento para el objeto desde el punto
de vista de secuencias de pasos acontecidos, es decir, determina trazas
posibles. En OASIS se utilizan dos tipos de especificaciones de proceso:
protocols y operations. Un protocolo establece secuencias permitidas de
acciones. Una operación establece secuencias obligatorias de acciones.
3.3.
OASIS expresado en Lógica Dinámica
OASIS está basado en una variante de la Lógica Dinámica [30] que incorpora obligaciones, prohibiciones y permisos. Siendo a ∈ A, en OASIS se
utilizan los siguientes operadores:
O(a)
F (a)
P (a)
obligación de ocurrencia de a.
prohibición de ocurrencia de a.
permiso o habilitación de ocurrencia de a.
3.3. OASIS EXPRESADO EN LÓGICA DINÁMICA
27
La definición de dichos operadores en Lógica Dinámica es la siguiente [64]:
F (a) ⇔ [a] false
O(a) ⇔ [¬a] f alse
P (a) ⇔ ¬F (a)
“la ocurrencia de a está prohibida”.
“la ocurrencia de a es obligatoria”.
“a está permitida si y sólo si a no está
prohibida”.
Donde ¬a representa la no-ocurrencia de la acción a (es decir, que no
ocurre nada o que ocurre otra acción distinta de a). En estas fórmulas, false
es un átomo especial tal que no hay un estado que pueda hacerlo verdadero, es
decir, cuando no existe una relación de alcanzabilidad definida4 . Esta situación
podría representar un estado de violación del sistema. El significado intuitivo
de éstas fórmulas es: una acción está prohibida si su ocurrencia conduce a un
estado de violación. Una acción es obligatoria si su no-ocurrencia conduce a
un estado de violación.
La Lógica Dinámica es un formalismo natural para estudiar de forma simple y directa ciertas aserciones sobre programas. En Lógica Dinámica, la fórmula [a]φ se interpreta intuitivamente como “después de la ocurrencia de la
acción a, φ debe satisfacerse”, siendo a una acción y φ una Fbf de la lógica de
primer orden utilizada para caracterizar el estado.
Siendo ψ y φ Fbfs de primer orden que caracterizan el estado del objeto inmediatamente antes (y después, respectivamente) de la ocurrencia de la
acción a. Utilizaremos los siguientes tipos de fórmulas en Lógica Dinámica:
ψ → [a]f alse
ψ → [¬a]false
ψ → [a]φ
“la ocurrencia de a está prohibida en los estados
que satisfacen ψ”.
“la ocurrencia de a es obligatoria en los estados
que satisfacen ψ”.
“en los estados que satisfacen ψ, inmediatamente
después de la ocurrencia de la acción a,
φ debe satisfacerse”.
Estas fórmulas constituyen un sublenguaje del lenguaje de Lógica Dinámica propuesto y formalizado en [97].
4
En [64] Meyer utiliza la constante especial V (violation) en lugar de false para representar un mundo no válido o estado sub-ideal. Así, un objeto podría tener la posibilidad
de transitar entre mundos no válidos hasta alcanzar un mundo válido. En nuestro caso la
especificación OASIS establece sólo estados “ideales” con lo cual hemos preferido utilizar el
átomo false para reflejar este hecho.
28
CAPÍTULO 3. OASIS
MUNDOS
ESTADOS
PASOS
inexistencia → w1 → w2 → ... → wi ...
...
σ2
σi ...
σ1
...
µ0
µi ...
µ1
µ2
t0
t1
t2
ti
→ destrucción
tdestroy
Figura 3.1: Relación entre mundos, estados y pasos del objeto.
3.4.
Semántica de OASIS
La semántica de OASIS es dada en términos de una estructura de Kripke
(W, τ , ρ). W es el conjunto de todos los mundos5 posibles que un objeto puede
alcanzar. Sean F el conjunto de Fbf evaluadas sobre el estado (mundo asociado) en el cual se encuentra el objeto, A el conjunto de acciones de la signatura
del objeto y 2A , el conjunto de instantáneas (pasos instanciados) posibles. Las
funciones τ y ρ se definen como:
τ : F → 2W
ρ : 2A → (W → W )
La función τ asigna a una fórmula en Lógica de Predicados de Primer
Orden el conjunto de mundos en los cuales se satisface. La función ρ asigna a
cada paso una relación binaria entre mundos, la cual es la semántica declarativa
del lenguaje. Siendo µ ∈ 2A y w, w0 ∈ W , el significado buscado es: (w, w0 ) ∈
ρ(µ) si y sólo si la ocurrencia de µ conduce al objeto desde el mundo w al
mundo w0 .
Definición 10 Transición válida. Cada par (w, w0 ) ∈ ρ(µ) se denomina
transición válida.
La relación entre estados, mundos, pasos y la vida del objeto se representa
en la Figura 3.1. donde ti es el tiempo en el cual se produce el i-ésimo tick de
reloj para el objeto. Se supone que µi ocurre en ti exactamente.
Obviamente, se cumple que: |=wi σi , i = 1, ..., n. Así, la interpretación
de las diferentes fórmulas en Lógica Dinámica, usadas en la plantilla de clase
OASIS, es la siguiente:
1. Fórmulas del tipo ψ → [a]φ, en particular [a]φ, cuando ψ es true (cualquier
estado del objeto)
5
De acuerdo con lo dicho, los estados son aserciones (fórmulas), los mundos son estructuras
sobre las que dichas fórmulas son interpretadas.
3.5. CONCURRENCIA EN OASIS
29
Siendo w ∈ τ (ψ) el mundo actual, si a ocurre entonces el mundo alcanzado es w0 ∈ τ (φ) . Así, las evaluaciones establecen las
propiedades que deben satisfacerse en el mundo alcanzado como
efecto atómico de la ejecución de una acción. Dicho de otra forma:
|=w ψ y |=w0 φ.
2. Fórmulas de prohibición ¬φ → [a]false
Siendo w ∈ τ (φ) el mundo actual, si a ocurre, no existe por definición una transición válida. Es decir, una fórmula de prohibición
impide que una acción ocurra estando el objeto en ciertos estados,
aquellos donde |=w ¬φ.
3. Fórmulas de obligación φ → [¬a]false
Siendo w ∈ τ (φ) el mundo actual, si la acción a no ocurre, no existe
por definición un mundo válido alcanzable. Es decir, una obligación
fuerza a que la acción a ocurra cada vez que el estado del objeto
es tal que |=w φ.
3.5.
Concurrencia en OASIS
Como se estableció anteriormente, una especificación OASIS modela al sistema de información como una sociedad de objetos autónomos y concurrentes
que se comunican entre sí a través de acciones. Así, de forma natural la concurrencia en una especificación OASIS está presente en las siguientes formas:
Cada objeto tiene su propio hilo de ejecución.
Un objeto puede necesitar cumplir más de una obligación (ocurrencia
obligada de una acción) en el mismo instante. Sería una restricción bastante fuerte al modelado no permitir que en la especificación exista la
posibilidad que se produzcan dos obligaciones en el mismo instante.
Un objeto compuesto (por otros objetos) puede proveer o requerir más
de un servicio a la vez.
3.6.
Conclusiones del capítulo
En este capítulo se han presentado las características esenciales de OASIS,
incluyendo definiciones para los conceptos básicos y describiendo brevemente el
marco formal utilizado. OASIS, tal como es presentado en [56] puede ser visto
desde dos perspectivas: como la formalización de un conjunto de conceptos de
30
CAPÍTULO 3. OASIS
modelado y como un lenguaje de especificación basado en dicha formalización.
En este capítulo no se ha presentado OASIS como lenguaje sino sólo algunos de
sus conceptos y su formalización. Por ejemplo, no se ha incluido el tratamiento
de relaciones entre clases mediante especialización y agregación. Para más
detalles consultar [56]. En los capítulos siguientes se incluyen algunos ejemplos
utilizando la sintaxis de OASIS 3.0.
Capítulo 4
Perspectiva cliente
La perspectiva cliente de una objeto aparece como una capacidad expresiva adicional que permite representar el comportamiento activo del objeto
(comportamiento del objeto como cliente) en términos homogéneos respecto
del comportamiento pasivo (del objeto como servidor). Esto significa reconocer
y tratar los servicios que un objeto requiere como acontecimientos relevantes
en su vida, de la misma forma que lo son los servicios que el objeto provee.
En OASIS 2.2 no se da esta capacidad expresiva. Para sistemas en los cuales
no existen objetos activos o donde los únicos objetos activos son los usuarios
de la aplicación esto no presenta mayores inconvenientes, pero obviamente en
estas circunstancias quedan excluidos muchos otros sistemas.
Desde el punto de vista de la animación, la incorporación de la perspectiva
cliente se presentó como un problema a resolver. Para la animación de especificaciones OASIS se debía disponer de un modelo abstracto de ejecución que
estableciera la semántica operacional del modelo. Durante el establecimiento
de dicho modelo de ejecución se detectó que era imprescindible contar con
la capacidad para expresar la perspectiva cliente en una especificación. Esta
necesidad surgió cuando se intentaba dar una interpretación operacional para
los disparos. Cuando la condición de un disparo se satisfacía en el estado actual del objeto, éste tenía la obligación de efectuar el disparo para alcanzar
un estado siguiente válido (debía requerir un cierto servicio a otro objeto o
a sí mismo). Inmediatamente surgía la necesidad de controlar la repetición
del disparo, pues en cada estado alcanzado, si la condición de disparo aún se
cumplía, el disparo continuaba siendo una obligación. OASIS debía proveer un
mecanismo que permitiera controlar los disparos y de paso extender la expresividad del modelo en forma homogénea al resto de aspectos relacionados, es
decir, otras fórmulas y especificaciones de proceso de la plantilla de clase.
31
32
CAPÍTULO 4. PERSPECTIVA CLIENTE
4.1.
Repetición de disparos en OASIS 2.2
Analicemos la siguiente porción de una especificación OASIS 2.2 para la
clase socio.
class socio
identification
...
constant_attributes
...
variable_attributes
num_libros:nat;
notificado:boolean;
private_events
alta_socio new;
baja_socio destroy;
notificar;
shared_events
prestar with libro;
devolver with libro;
valuations
num_libros=N [prestar] num_libros=N+1;
num_libros=N [devolver] num_libros=N-1;
notificado=false [notificar] notificado=true;
triggers
self::notificar if num_libros=2 and notificado=false;
...
El disparo del evento notificar hacia el mismo objeto corresponde a requerir dicho evento a sí mismo. El primer inconveniente que se presenta es
distinguir entre el servicio requerido y el servicio provisto. En este caso, en el
cual el cliente y el servidor son el mismo objeto, el servicio solicitado forma
parte de la signatura del objeto, pero esto en general no sucede. Cuando se
produce un disparo se establece una relación entre dos acciones: la que ocurre
en el cliente por requerir y la que ocurre en el servidor por proveer o rechazar la solicitud de servicio. Es decir, en el ejemplo anterior una acción es
requerir el evento notificar y otra es proveer el evento notificar. Así, la
evaluación asociada a la ocurrencia del evento notificar se interpreta como
una evaluación por proveer dicho evento, no por requerirlo. Además, nótese
que el disparo, por la obligación que significa, se realizará en todos los estados
que satisfagan la condición de disparo. Es decir, en estados sucesivos en los
4.1. REPETICIÓN DE DISPAROS EN OASIS 2.2
33
que la condición de disparo se siga satisfaciendo, el disparo continuará realizándose. Este comportamiento puede ser el deseado en algún caso particular
pero en general se necesita un mecanismo que permita especificar con precisión cómo deben efectuarse los disparos. La solución dentro del contexto de
OASIS es clara, debe poderse introducir una condición adicional dentro de la
condición de disparo de manera que la realización del disparo pueda deshabilitarse. En el ejemplo planteado la condición que pretendía inhabilitar el disparo
era “notificado=false”. A continuación veremos por qué el comportamiento
deseado no se consigue.
Para poder apreciar el problema primero se describirán brevemente algunos
aspectos del modelo abstracto de ejecución para especificaciones OASIS, el cual
se presenta en detalle en el capítulo 8.
La vida del objeto se caracteriza por las acciones acontecidas en determinados instantes de tiempo y los correspondientes estados alcanzados. En cada
instante ti el objeto tiene un buzón, un conjunto de servicios para proveer,
el cual se denominará Mboxi . El estado del objeto permanece inalterado inmediatamente después de la ocurrencia de acciones en un instante y hasta el
instante siguiente (inclusive), es decir, en un intervalo (t i - t i+1 ] el estado se
mantiene constante pues no se procesan servicios. En el intervalo (t i - t i+1 ) el
objeto está realizando actividad interna y sólo en t i+1 el estado alcanzado está
disponible para procesar el siguiente buzón (Mboxi+1 ). Para representar gráficamente estas ideas se ha establecido una notación denominada Diagramas
de Vida del Objeto. Un Diagrama de Vida del Objeto permite apreciar las
acciones provistas y requeridas por un objeto y los cambios de estado alcanzados. La Figura 4.1 presenta un Diagrama de Vida del Objeto. En el capítulo
8 se muestra un ejemplo más completo respecto de la notación utilizada.
De acuerdo a lo explicado antes, a continuación se proporciona una interpretación operacional para la especificación del ejemplo. Como se indicó antes,
la evaluación asociada al evento notificar intenta deshabilitar la repetición
del disparo, sin embargo, en el mejor de los casos, el disparo se efectuaría dos
veces. Esto se ilustra en la Figura 4.1. Suponiendo que el objeto inicialmente
tiene un estado representado por {<num_libros,0>,<notificado,false>}
y que recibe dos solicitudes de servicio correspondientes a la ocurrencia del
evento prestar. En el estado alcanzado en el instante t2 se satisface la condición de disparo. Por tratarse de una obligación, en ese mismo instante se requiere el servicio notificar representado con la flecha inferior. Debe insistirse
en lo siguiente: requerir un servicio a sí mismo es sólo un caso particular, en
general dicha solicitud puede ir dirigida a otro objeto. Además, el disparo debe
hacerse efectivo en el instante en el cual el objeto alcanza el estado que valida
la condición de disparo, no antes. Así, en el mejor de los casos, la solicitud de
servicio hacia sí mismo será atendida en el instante inmediatamente siguiente
a la realización del disparo, con lo cual en al menos dos estados consecutivos
34
CAPÍTULO 4. PERSPECTIVA CLIENTE
se disparará el evento notificar (salvo que en t2 ocurra un evento devolver
o un nuevo prestar, lo cual no es controlado por la especificación ni por la
interpretación operacional asumida).
prestar1
prestar2
t0
t1
Estado1
notificar1
t2
t3
Estado2
num_libros=1
notificado=false
Estado3
num_libros=2
notificado=false
Estado4
num_libros=2
notificado=false
self::notificar1
num_libros=2
notificado=true
self::notificar
2
Figura 4.1: Repetición de disparos
La interpretación operacional que se ha propuesto está basada estrictamente en la semántica de la fórmula que establece la obligación asociada al
disparo ( φ[¬e]false). En cada estado en el que se satisfaga la fórmula φ el
evento e debe ocurrir en el cliente, independientemente de si el servicio es
provisto o rechazado en el servidor, es decir, se trata de una comunicación
asíncrona.
4.2.
Incorporando la perspectiva cliente
Según lo expuesto anteriormente, en OASIS 2.2 no existe una forma de
controlar el disparo de eventos en la especificación. La incorporación de la
perspectiva cliente resuelve este problema. Para una adecuada introducción de
este aspecto en OASIS, se han tenido en cuenta las siguientes consideraciones:
En un disparo si el servidor no es el mismo objeto, el servicio solicitado
no está en la signatura del objeto cliente.
Por el carácter asíncrono de los disparos es imprescindible hacer la distinción entre requerir el servicio (disparar en el cliente) y proveer el servicio
(atender en el servidor).
La expresividad adicional asociada a la perspectiva cliente es extensible
a todas las fórmulas y especificaciones de proceso.
4.2. INCORPORANDO LA PERSPECTIVA CLIENTE
35
Por otra parte, era importante mantener compatibilidad respecto de OASIS
2.2, de forma que la incorporación de la perspectiva cliente debía corresponder
a una extensión de la expresividad original. Un enfoque descartado por su
carácter revolucionario fue migrar hacia la línea de arquitecturas software o
componentes . En el capítulo 6 se presenta una propuesta en este sentido.
A continuación se introducen los elementos utilizados para modelar la perspectiva cliente en especificaciones OASIS.
4.2.1.
Identificación de objetos
Definición 11 Oid (object identifier). Cada objeto posee un oid. El oid
establece la identidad del objeto y tiene las siguientes características:
Constituye un identificador único y global para cada objeto dentro del
sistema.
Es determinado en el momento de la creación del objeto.
Es independiente de la localización física del objeto, es decir, provee
completa independencia de localización.
Es independiente de las propiedades del objeto, lo cual implica independencia de valor y de estructura.
No cambia durante toda la vida del objeto. Además, un oid no se reutiliza
aunque el objeto deje de existir.
No se tiene ningún control sobre los oids y su manipulación resulta transparente.
Sin embargo, en el ámbito de la especificación y operación del sistema, es
preciso contar con algún medio para hacer referencia a un objeto en particular.
Definición 12 Mecanismo de identificación. Siendo Oids el conjunto de
oids de objetos del sistema, C una clase y Oidsc el conjunto de oids de objetos
de la clase C, entonces Oidsc ⊆ Oids. Además, siendo Att el conjunto de
atributos de la clase C y Attcons ⊆ Att un conjunto de atributos constantes
de la clase C, si {att1 , att2 , ..., attn } ⊆ Attcons y los sorts respectivos son
s1 , s2 , ..., sn entonces puede existir un mecanismo de identificación, la función:
id : s1 × s2 × ... × sn → Oidsc
La función id establece una correspondencia entre una tupla de valores de
atributos constantes y el oid de un objeto de la clase C, con oid ∈ Oidsc . La
tupla representa el concepto de clave candidata.
36
CAPÍTULO 4. PERSPECTIVA CLIENTE
Definición 13 Valor de un mecanismo de identificación. Siendo id un
mecanismo de identificación, entonces llamamos valor de un mecanismo de
identificación a id. Así, id = θ id y θ es una sustitución básica de los valores
de atributos constantes que definen al mecanismo de identificación.
Los mecanismos de identificación no son redundantes y permiten hacer
referencia a objetos en el ámbito del problema, utilizando propiedades del
objeto. Sin embargo, internamente la referencia e identificación del objeto son
mediante su oid.
Un objeto puede tener más de un mecanismo de identificación aunque cada
vez que se hace referencia a un objeto se utiliza sólo uno de ellos.
A partir de este punto se introducirán parcialmente aspectos de la sintaxis de OASIS para hacer más sencilla y precisa la exposición de los cambios
introducidos.
Sintaxis
<def_identificador>
::=
<id_identificador> ’:’ (<lista_id_atributo>)
Cada atributo que define el mecanismo de identificación (en la lista
<id_atributo>) es un atributo constante.
Ejemplo 3 Una definición de tres mecanismos de identificación para los objetos de la clase despacho en un edificio.
ocupante:(nombre);
nro_ext_telefonica:(nro_ext_telefonica);
ubicacion:(edificio, planta, puerta);
Cuando un mecanismo de identificación se define a base de sólo un atributo,
puede usarse para denotarlo el mismo nombre del atributo.
4.2.2.
Referencias a cliente y servidor
La necesidad de hacer referencia a otros objetos (de la clase que se está
especificando o de otra clase) está estrechamente ligada a la interacción entre
objetos. Este apartado se centra en mostrar cómo hacer referencia a objetos
en la especificación de una clase, sean clientes o servidores de las acciones que
acontecen.
4.2. INCORPORANDO LA PERSPECTIVA CLIENTE
37
Sintaxis
<ref_objeto>
<identificación>
::=
::=
|
|
|
<valor_atributo>
::=
self
<clase> [<identificación>]
’(everyone)’
’(someone)’
’(’<id_identificador>’,’
’[’<lista_valor_atributo>’]’ ’)’
<expresión> | ’_’
Observaciones
Cuando se desea hacer referencia al mismo objeto que se está especificando se utilizará la palabra reservada self.
Para hacer referencia a cada uno de los objetos de la clase se utiliza
(everyone).
Si se quiere referenciar a un objeto de una clase (sin especificar uno en
concreto) se utiliza (someone).
Para referirse a un conjunto de objetos que coinciden en alguno de los
valores de la lista de valores de atributo se indicará el mecanismo de
identificación y la lista de valores de atributos llevará los valores que
deben coincidir en las posiciones adecuadas. Se utiliza ’_’ para señalar
que se admite cualquier valor. Si todas las posiciones tienen un ’_’ el
efecto es el mismo que usar (everyone).
Ejemplo 4 El objeto de la clase despacho cuyo ocupante es Juan Pérez.
despacho(ocupante,[‘‘Juan Perez’’])
Ejemplo 5 El objeto de la clase despacho cuyo número de extensión telefónica
es 3571.
despacho(nro_ext_telefonica,[3571])
Ejemplo 6 El objeto de la clase despacho ubicado en el edificio EUI, tercera
planta y puerta A3.
despacho(ubicacion,[‘‘EUI’’,3,‘‘A3’’])
Ejemplo 7 Un objeto cualquiera de la clase despacho.
despacho(someone)
38
CAPÍTULO 4. PERSPECTIVA CLIENTE
Ejemplo 8 Cada uno de los objetos de la clase despacho.
despacho(everyone)
Ejemplo 9 Los objetos de la clase despacho ubicados en el edificio de la EUI.
despacho(ubicacion,[‘‘EUI’’,_,_])
4.2.3.
Acciones
El concepto de acción incluye tres elementos: referencia del cliente, referencia del servidor y descripción del servicio. Así, una acción está definida
por la tupla hCliente, Servidor, Servicioi. El cliente requiere un servicio a
un servidor que ofrece dicho servicio. El servicio puede ser un evento o una
operación (concepto que se presenta en el siguiente capítulo) . Las referencias
del cliente y del servidor se definen según lo explicado en el apartado anterior.
El servicio es un término instanciado mediante una sustitución de valores
adecuados en sus parámetros.
Ejemplo 10 Una acción cuyo cliente es un objeto de la clase usuario y cuyo
servidor es un objeto de la clase cuenta, siendo depósito(15000) el servicio
requerido.
<usuario(nombre,[‘‘Juan Perez’’]),
cuenta(numero,[100]),deposito(15000)>
Ejemplo 11 Una acción cuyo cliente y servidor es el mismo objeto, donde
pagar_comisión es el servicio requerido.
<self,self,pagar_comision>
Ejemplo 12 Una acción cuyo cliente es un objeto de la clase administrador y
cuyo servidor son todos los objetos de la clase artículo, siendo aumentar_precio(5) el servicio requerido.
<administrador(nombre,[‘‘Maria’’]),
articulo(everyone),aumentar_precio(5)>
Ejemplo 13 Una acción cuyo cliente es un objeto de la clase goloso y cuyo
servidor es un objeto de la clase máquina (máquina de chocolatinas), siendo
cancelar el servicio solicitado.
<goloso(nombre,[‘‘Juan Perez’’]),
4.2. INCORPORANDO LA PERSPECTIVA CLIENTE
Servicios
provistos
Objeto
39
Servicios
requeridos
acción
Objeto A
Objeto B
Figura 4.2: Perspectivas cliente y servidor de un objeto.
maquina(numero,[10]),cancelar>
Ejemplo 14 Una acción cuyo cliente es un objeto cualquiera de la clase
goloso y cuyo servidor es un objeto de la clase máquina (máquina de chocolatinas), siendo introducir_moneda el servicio solicitado.
<goloso(someone),maquina(numero,[10]),introducir_moneda>
Nótese que al establecer el servicio de una acción no se hace distinción
entre requerir un evento o requerir una operación. Esto constituye una ventaja
puesto que el cliente no tiene por qué saber detalles de implementación del
servicio que requiere.
La Figura 4.2 muestra cómo un objeto tiene una perspectiva cliente y una
perspectiva servidor según esté requiriendo u ofreciendo servicios, respectivamente. Modelar la perspectiva cliente significa tener la posibilidad de reflejar
en la especificación de la clase cliente el hecho de que “todo servicio requerido
también es un evento para el objeto cliente”. Ambas perspectivas son tratadas
uniformemente bajo la noción de acción antes descrita.
En la especificación de una clase, las acciones asociadas a servicios provistos o requeridos se incluyen en la definición de fórmulas (precondiciones,
evaluaciones y disparos) y de especificaciones de procesos.
Las acciones en su formato completo (hCliente, Servidor, Servicioi) pueden
dificultar la lectura y edición de la especificación. Para evitar este inconveniente se pueden utilizar las siguientes simplificaciones:
a) Cuando se trata de un servicio provisto por el objeto (el propio objeto
es el servidor) la acción se escribirá como Cliente:Servicio. Si el cliente
no es relevante se escribirá sólo Servicio.
40
CAPÍTULO 4. PERSPECTIVA CLIENTE
b) Cuando se trata de un servicio requerido por el objeto (el propio objeto
es el cliente) la acción se escribirá como Servidor::Servicio.
c) En el caso particular en el cual el cliente y el servidor son el mismo objeto
se debe diferenciar entre la acción de requerir el servicio y la acción de
proveerlo. En este caso se escribirá ::Servicio para representar la acción
por requerir y self :Servicio para representar la acción por proveer.
Sintaxis
<acción>
<cliente>
<servidor>
::=
::=
::=
[ <cliente> ] [ <servidor> ] <servicio>
<ref_objeto> ’:’
<ref_objeto> ’::’ | ’::’
Ejemplo 15 En la clase cuenta, una evaluación asociada a la acción cuyo
cliente es un objeto cualquiera y cuyo servidor es el propio objeto de la clase
cuenta, siendo el servicio depósito(Cantidad:int).
saldo=S [deposito(Cantidad)] saldo=S+Cantidad;
“Cuando saldo=S y ocurre la acción cuyo evento es deposito(Cantidad),
inmediatamente después se cumple que saldo=S+Cantidad”
Ejemplo 16 En la clase cuenta, una parte de una expresión de proceso (supondremos que se trata de una operación) en la cual el cliente y servidor de una
acción corresponden al objeto de la clase cuenta (la clase que se está especificando), siendo el servicio pagar_comisión.
... AJUSTAR4= ::pagar_comision.AJUSTAR5; ...
“Cuando el estado del proceso es AJUSTAR4, debe ocurrir la acción cuyo
cliente y servidor es el objeto de la clase especificada (cuenta). El evento de la
acción es pagar_comisión. Después de ocurrida la acción el estado del proceso
es AJUSTAR5”.
Ejemplo 17 En la clase administrador, una obligación de ejecutar la acción
cuyo cliente es un objeto de la clase administrador y cuyo servidor son todos los
objetos de la clase artículo, siendo el servicio aumentar_precio(Porcentaje:int).
ventas > 1000000
[¬articulo(everyone)::aumentar_precio(5)] false
“Al satisfacerse ventas > 1000000 debe ocurrir una acción cuyo cliente
es el objeto de la clase especificada (administrador), el servidor es cada objeto
de la clase artículo y el servicio es aumentar_precio(5)”.
4.2. INCORPORANDO LA PERSPECTIVA CLIENTE
41
Ejemplo 18 En la clase máquina, una precondición para una acción cuyo
cliente es el objeto de la clase goloso “Juan Pérez” y cuyo servidor es el mismo
objeto (máquina de chocolatinas), siendo chocolatina el servicio solicitado.
¬(numero_chocs>10)
[goloso(nombre,[‘‘Juan Perez’’]):chocolatina] false
“Se prohibe que cuando el número de chocolatinas (numero_chocs) es
menor que 10 acontezca el servicio chocolatina requerido por el objeto de la
clase goloso cuyo nombre es Juan Pérez”.
En la especificación de una clase, el servicio de una acción es siempre un
servicio de la clase servidora. Es decir, a menos que la clase servidora sea self,
dicho servicio no está en la signatura de la clase cliente. Sin embargo, en el
ámbito de una acción vista como una tupla hCliente, Servidor, Servicioi, tanto las acciones recibidas como las acciones enviadas pertenecen a la signatura
de la clase especificada.
4.2.4.
Control de disparos
En este apartado se muestra un ejemplo que ilustra cómo mediante la
incorporación de la perspectiva cliente es posible controlar la repetición de los
disparos, situación que motivó dicha incorporación.
Ejemplo 19 Las instancias de la clase Y tienen declarado un disparo hacia
la instancia de la clase Z identificada por “z1”. La condición de disparo es
“att1=2 and att2=false”. La especificación resumida de las clases Y y Z es la
siguiente :
class Y
identification
by_att0 (att0 );
constant_attributes
att0 :nat;
variable_attributes
att1 : nat ;
att2 : boolean(false);
private_events
...
e1 ;
valuations
att1 =N [e1 ] att1 =N+1 and att2 =false;
[Z(by_code,[(code,’’z1 ’’)])::e2 ] att1 =0 and att2 =true;
42
CAPÍTULO 4. PERSPECTIVA CLIENTE
triggers
Z(by_code,[(code,’’z1 ’’)])::e2 if att1 =2 and att2 =false;
...
class Z
identification
by_code(code);
constant_attributes
code: string;
...
events
e2 ;
...
Z(by_code,[(code,’’z1 ’’)]) es el término servidor para representar al
objeto de la clase Z usando el mecanismo de identificación by_code compuesto
por el atributo constante code, el cual debe tener el valor “z1 ”. Para facilitar la lectura del ejemplo, se hará referencia a Z(by_code,[(code,’’z1 ’’)])
usando sólo Z(’’z1 ’’).
Si en el instante ti se alcanza el estado Statei en el cual debe ocurrir el
disparo Z(’’z1 ’’)::e2 , entonces en Mboxi estará la acción Z(’’z1 ’’)::e2 ,
indicando la obligación del disparo. En este caso, aunque e2 no está en la
signatura del cliente podremos utilizar esta acción para reflejar el evento “disparar e2 ”. Posteriormente, en la evaluación “att2 =false [Z(’’z1 ’’)::e2 ]
att1 =0 and att2 =true” se consigue controlar la repetición del disparo. Como se observa en la especificación de Y, el evento e1 volverá a habilitar la
condición de disparo.
Suponiendo una ejecución para una instancia de la clase Y en la cual las
acciones llegan de acuerdo a la siguiente tabla :
Intervalo
(ti - ti+1]
(.. - t1]
(t1 - t2]
(t2 - t3]
(t3 - t4]
(t4 - t5]
(t5 - t6]
(t6 - ..
Acciones
Recibidas
e1
e1
Z(“z1”)::e2
e1
e1
Z(“z1”)::e2
...
El Diagrama de Vida del Objeto de la Figura 4.3 describe parte del ciclo
de vida de una instancia de la clase Y. Se ha considerado como estado inicial
{<att1 ,0>,<att2 ,false>}.
4.2. INCORPORANDO LA PERSPECTIVA CLIENTE
e1
e1
43
e1
e1
Mbox1
Mbox2
Mbox3
Mbox4
Mbox5
Mbox6
e1
e1
Z(“z 1”)::e 2
e1
e1
Z(“z 1”)::e 2
t1 att =1
t2
att1=0
1
att2=false
att2=false
t3
att1=2
att2=false
att1=0
att2=true
t4 att1=1
att2=false
t5 att1=2
t6 att1=0
att2=false
Z(“z 1”):e 2
att2=true
Z(“z 1”):e 2
Figura 4.3: Parte del ciclo de vida de un objeto de la clase Y.
La siguiente tabla resume el comportamiento del objeto mostrado en la
Figura 4.3.
i
Intervalo
(ti - ti+1]
(..
(t1
(t2
(t3
(t4
(t5
(t6
-
t1]
t2]
t3]
t4]
t5]
t6]
..
State
att1=0,
att1=1,
att1=2,
att1=0,
att1=1,
att1=2,
att1=0,
att2=false
att2=false
att2=false
att2=true
att2=false
att2=false
att2=true
Acciones
Acciones
Ejecutadas en
Disparadas en
ti+1
ti+1
e1
e1
Z(“z1”)::e2 Z(“z1”):e2
e1
e1
Z(“z1”)::e2 Z(“z1”):e2
...
...
Acciones
Recibidas
e1
e1
Z(“z1”)::e2
e1
e1
Z(“z1”)::e2
...
Existe un caso particular en el cual el servidor de un disparo es el mismo
objeto que requiere el servicio. Analicemos el siguiente caso: las instancias de
la clase X tienen declarado un disparo a self cada vez que se satisface la
fórmula “att1 =2 and att2 =false”. La especificación resumida de la clase X
es la siguiente:
class X
identification
by_att0 (att0 );
constant_attributes
att0 : nat;
variable_attributes
44
CAPÍTULO 4. PERSPECTIVA CLIENTE
att1 : nat(0);
att2 : boolean(false);
private_events
...
e1 ;
e2 ;
valuation
att1 =N [e1 ] att1 =N+1;
[self:e2 ] att1 =0 and att2 =false;
[::e2 ] att2 =true;
triggers
::e2 if att1 =2 and att2 =false;
...
Cada vez que un objeto de la clase X alcance un nuevo estado, tendrá en su
Mboxi las acciones correspondientes a los disparos que en ese estado satisfacen
su condición. Por lo tanto, en el instante ti donde se alcanza el estado Statei ,
en el cual deba lanzarse el disparo self::e2 , en Mboxi estará la acción
self::e2. Nótese que en la especificación existe una evaluación asociada a la
ocurrencia del disparo (::e2) y otra asociada a proveer el servicio requerido
en el disparo (self:e2). La acción de disparo ::e2 representa la obligación
para el objeto. La acción de servicio self:e2 representa la solicitud de un
servicio cuyo cliente es el mismo objeto.
Suponiendo una ejecución para una instancia de la clase X en la cual las
acciones llegan de acuerdo a la siguiente tabla:
Intervalo
(ti - ti+1]
(.. - t1]
(t1 - t2]
(t2 - t3]
(t3 - t4]
(t4 - t5]
(t5 - t6]
(t6 - ..
Acciones
Recibidas
e1
e1
::e2
self:e2
e1
...
En t3 la condición de disparo de la acción ::e2 se satisface, por lo tanto
en Mbox3 se introduce la obligación ::e2, la cual al ser ejecutada provocará
que efectivamente se requiera la acción self:e2, la cual se ha supuesto que
es recibida en el intervalo (t3 -t4 ]. El Diagrama de Vida del Objeto de la
Figura 4.4 describe la situación planteada. Se ha considerado el estado inicial
{<att1 ,0>,<att2 ,false>}.
4.2. INCORPORANDO LA PERSPECTIVA CLIENTE
e1
e1
45
e1
Mbox1
Mbox2
Mbox3
Mbox4
e1
e1
::e2
self:e 2
t1 att =1
t2
att1=0
1
att2=false
att2=false
t3
att1=2
att2=false
att1=2
att2=true
Mbox5
Mbox6
e1
t4 att1=0
att2=false
t5
t6
att1=0
att2=false
att1=1
att2=false
self:e 2
Figura 4.4: Parte del ciclo de vida de un objeto de la clase X.
La siguiente tabla resume el comportamiento del objeto mostrado en la
Figura 4.4.
i
Intervalo
(ti - ti+1]
(.. - t1]
(t1 - t2]
(t2 - t3]
(t3 - t4]
(t4 - t5]
(t5 - t6]
(t6 - ..
State
att1=0,
att1=1,
att1=2,
att1=2,
att1=0,
att1=0,
att1=1,
att2=false
att2=false
att2=false
att2=true
att2=false
att2=false
att2=false
Acciones
Ejecutadas en
ti+1
e1
e1
::e2
self:e2
e1
...
Acciones
Disparadas en
ti+1
self:e2
...
Acciones
Recibidas
e1
e1
::e2
self:e2
e1
...
El cambio de estado es instantáneo pero cada estado se mantiene al menos
hasta que se vuelvan a servir las acciones del buzón del siguiente instante. El
objeto automáticamente introduce en su buzón una acción asociada a requerir
un servicio cuando en el siguiente instante la condición de disparo se satisface,
tal como se ha representado en el intervalo (t2 - t3 ]. Dicha acción provoca
que el objeto efectivamente requiera al servidor el servicio involucrado en el
instante en el cual la condición de disparo se satisface. Independientemente y
en un instante posterior, el servicio requerido es provisto o rechazado por el
objeto servidor.
46
4.3.
CAPÍTULO 4. PERSPECTIVA CLIENTE
Conclusiones del capítulo
En este capítulo se ha establecido una extensión a OASIS 2.2 que permite
un tratamiento homogéneo de la perspectiva cliente y servidor de un objeto. La
propuesta presentada aumenta la capacidad expresiva de OASIS y soluciona
el problema de OASIS 2.2 para el control de los disparos.
Para cada clase, se asume la existencia implícita de un conjunto A de
acciones obtenido a partir de los servicios que los objetos de la clase pueden
requerir (cuando son clientes) o proveer (cuando son servidores). Es decir,
aunque en general el servicio no pertenece a la signatura de servicios del objeto
cliente, la acción por requerir cualquier servicio sí pertenece a su signatura.
El tratamiento de los disparos es sólo un aspecto del tratamiento de obligaciones. En el capítulo 8 se presenta el modelo abstracto de ejecución para
especificaciones OASIS que abarca obligaciones en el sentido más amplio.
La perspectiva cliente puede expresarse no sólo en disparos y evaluaciones.
De acuerdo a lo establecido anteriormente, podrían declararse clientes y servidores cada vez que se especifique un servicio tanto en fórmulas como en especificaciones de proceso. Sin embargo, a continuación se mencionan ciertas
consideraciones al respecto:
Las acciones que representan el requerir un servicio no deberían tener
precondiciones ni especificaciones de proceso que pudiesen impedir su
ejecución. Esto se debe a que dichas acciones son una obligación. Esto
estaría en conflicto con la prohibición que establezca una precondición
o especificación de proceso. Esta situación se resuelve con el siguiente
enfoque de modelado: las prohibiciones que se quieran establecer para
una obligación pueden ser especificadas como parte de la condición de
disparo o de la especificación de proceso correspondiente.
Declarar clientes y servidores asociados a los servicios crea dependencia
de la clase especificada respecto al contexto en el cual se especifica (el esquema conceptual). Esto tiene incidencia negativa en la reutilización de
la clase, lo cual sugiere reducir al mínimo las especificaciones de clientes
y servidores. En el caso de los servicios requeridos, con el enfoque propuesto siempre debe indicarse el objeto servidor, a menos que se trate del
mismo objeto. Respecto de los clientes, estos siempre podrían evitarse,
aún a coste de introducir nuevos servicios cuando se necesite diferenciar el mismo servicio para distintos clientes (por ejemplo porque tienen
distintas evaluaciones). De esta forma, desde el punto de vista de una
clase, el cliente de un servicio es quien tenga acceso a dicho servicio. Esta
relación de acceso puede definirse en OASIS mediante interfaces.
Capítulo 5
Especificaciones de proceso
En este capítulo se presenta una nueva propuesta para la especificación de
procesos en OASIS, en la cual la expresividad ofrecida es trasladable directamente a la variante de Lógica Dinámica utilizada en las otras secciones de la
plantilla de clase. Es decir, la formalización de las especificaciones de proceso puede ser establecida dentro de un marco formal homogéneo para toda la
plantilla de clase.
Una herramienta para el modelado conceptual debe combinar precisión y
expresividad. La expresividad no sólo involucra tener la posibilidad de definir
todos los aspectos de funcionalidad del sistema, sino que a la vez que éstos puedan ser definidos de forma natural tanto para el analista como para
el usuario. En la práctica el mejor resultado se obtiene combinando diversas
técnicas de especificación. Sin embargo, esto dificulta la integración y formalización de la especificación. Tradicionalmente en métodos orientados a objeto
suele utilizarse tres vistas del sistema: modelo de objetos, modelo dinámico y
modelo funcional [81]. En OASIS 2.2 el modelo dinámico incluye dos formas
complementarias de especificación de eventos permitidos y obligados en la vida de un objeto: a partir del estado (mediante disparos y precondiciones) y
en base a secuencias de eventos acontecidos (transacciones y procesos). En el
primer caso se trata de fórmulas en una variante de lógica dinámica y en el
otro se utiliza un álgebra de procesos.
En la construcción automática de prototipos para especificaciones OASIS
el disponer como entrada de una representación uniforme es muy importante
para facilitar el proceso de traducción y para garantizar la fidelidad respecto
de la especificación. Esto motivó la búsqueda de un formalismo homogéneo
para el modelo dinámico de OASIS. La idea era mantener la expresividad, es
decir, posibilitar la especificación a partir del estado y en base a secuencias
de eventos, pero proporcionando una interpretación equivalente que integre
ambas perspectivas en un formalismo común. Se ha distinguido entre procesos
47
48
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
que establecen obligaciones (operations) y procesos que establecen permisos
(protocols) proporcionando una semántica precisa en cada caso. Además, una
serie de inconvenientes presentes en OASIS 2.2 han sido solventados.
5.1.
Procesos en OASIS 2.2
En OASIS 2.2 cada clase tiene una especificación de proceso, construida
utilizando un Álgebra de Procesos para Objetos (APO) la cual es una extensión conservativa del Álgebra Básica de Procesos propuesta en [96]. Se han
detectado los siguientes inconvenientes en el enfoque utilizado en OASIS 2.2
para la especificación de procesos:
La formalización ofrecida no es uniforme respecto a la usada para el resto
de la plantilla de clase. En las secciones de evaluaciones, precondiciones
y disparos se utiliza una variante de Lógica Dinámica. En procesos se
utiliza la APO mencionada antes.
Los procesos de OASIS 2.2 determinan permisos para eventos e incluyen
sólo la perspectiva servidor del objeto. En el caso de transacciones, se
especifica explícitamente el agente de cada evento involucrado en la
transacción o se asume que es uno de los agentes del primer evento de
la transacción.
En general, es difícil establecer una especificación de proceso para una
clase, a menos que sea muy simple, esto sucede, por ejemplo, si el objeto
se crea y después puede proveer cualquier servicio hasta que es finalmente
destruido. Más difícil aún es establecer sólo una especificación de proceso
para la clase si se incluye la perspectiva cliente, pues entre las secuencias
permitidas deberían incluirse los disparos, los cuales se rigen por el estado
del objeto y no por secuencia de eventos. Además, en la práctica cuando
se trata de establecer secuencias permitidas de eventos, éstas no tienen
por qué involucrar a todos los eventos del objeto.
Una especificación de proceso no asociada a una clase en particular se
modela como transacción global. En estos casos, una solución más natural en el marco de OASIS es la definición de una clase agregada a la
medida de las necesidades de visibilidad que requiera el proceso. Así, sólo
en el caso extremo en que todas las clases del esquema estén involucradas
la definición del proceso se haría en la clase agregada que representa al
esquema conceptual.
5.2. PROCESOS EN OASIS 3.0
5.2.
49
Procesos en OASIS 3.0
Las ideas presentadas a continuación se han materializado en la versión
3.0 de OASIS. En este apartado se presenta un procedimiento automatizable
para interpretar las especificaciones de proceso como fórmulas en la variante
de Lógica Dinámica utilizada. Así, desde una perspectiva global, una especificación de clase OASIS puede ser vista como un conjunto de fórmulas en dicha
Lógica Dinámica. Estas fórmulas determinan permisos, obligaciones y cambios
de estado para los objetos de la clase. Además, la nueva propuesta incorpora la perspectiva cliente y permite definir sólo las especificaciones de proceso
necesarias, cada una incluyendo sólo las acciones que le son relevantes.
En OASIS 3.0, el modelado del comportamiento puede realizarse desde
dos perspectivas complementarias en cuanto a expresividad. En cada instante,
para un objeto, las acciones permitidas y las acciones obligatorias pueden ser
establecidas de la siguiente forma:
Considerando el estado del objeto en dicho instante. Las precondiciones
son fórmulas que permiten la ocurrencia de acciones sólo en ciertos estados del objeto. De forma análoga, los disparos son fórmulas que obligan
la ocurrencia de acciones en determinados estados del objeto. El formalismo utilizado en este caso es una variante de Lógica Dinámica que
incluye los operadores deónticos de permiso, prohibición y obligación.
Considerando las acciones ya acontecidas. Una especificación de proceso determina un patrón de comportamiento para el objeto, desde el
punto de vista de secuencias de pasos acontecidos, es decir, determina
trazas posibles. Para OASIS 3.0 se estableció la utilización de dos tipos
de especificaciones de proceso: protocolos y operaciones. Un protocolo establece secuencias permitidas de acciones. Una operación establece
secuencias obligatorias de acciones. Las especificaciones de proceso se expresan usando álgebra de procesos. Las propuestas más populares para
la especificación de secuencias de acciones están basadas en los statecharts [31] o alguna de sus derivaciones, tal como los objectcharts [11].
En comparación a los objectcharts, la expresividad lograda por las especificaciones de procesos en OASIS es similar.
Existen tres semánticas posibles que pueden ser asociadas a una especificación de proceso en OASIS 3.0:
(a) La semántica del lenguaje utilizado para su especificación. En OASIS, el
lenguaje utilizado para especificar procesos es un subconjunto de CCS
[65], compartiendo así una semántica basada en la noción de sistema de
transición etiquetado y todas las propiedades formales establecidas en
CCS.
50
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
(b) La semántica de permisos, es decir, una especificación de proceso establece secuencias de acciones que pueden ocurrir.
(c) La semántica de obligaciones, es decir, una especificación de proceso
establece secuencias de acciones que deben ocurrir.
Dichas secuencias de acciones vienen dadas por la relación de alcanzabilidad entre mundos en el modelo de Kripke asociado.
Un proceso en OASIS 3.0 tendrá siempre la semántica (a). Adicionalmente,
se asocia la semántica (b) ó (c) a un proceso, esto se declara de forma explícita.
Así, la sección operations se utiliza para especificar secuencias obligatorias
de acciones y la sección protocols para especificar secuencias permitidas de
acciones. Un caso particular de proceso de obligación es el que actúa como
una transacción, es decir, con la política del “todo o nada”. En este caso se
añade el calificativo de transaction para el proceso. Se asume por defecto que
el proceso no actúa como transacción.
Siguiendo el planteamiento y notación propuestos en CCS, la especificación
de un proceso R puede ser vista como un sistema de transiciones etiquetado
a
representado por (κR , AR , {→: a ∈ AR }), donde:
κR es el conjunto de constantes agente1 utilizados para definir el proceso
R.
AR es el conjunto de acciones usadas en la especificación del proceso R,
AR ⊆ A, siendo A el conjunto de acciones2 en la signatura de la clase.
a
→⊆ κR × κR es la relación de transición.
Para cada constante agente E ∈ κR se tiene una ecuación de definición
def
E ≡ Q, siendo Q una expresión construida usando los siguientes operadores
(siendo S ∈ κR y a, a1 y a2 acciones pertenecientes al conjunto AR ):
1. a.S, se denomina prefijo.
2. if C then a.S, se denomina condicional, siendo C una expresión boolean.
P
P
0
0
3.
i∈I Qi , donde Qi puede ser un prefijo o un condicional y
i∈I es la
0
suma de los Qi , con I como conjunto de indexación.
1
Un proceso de OASIS en CCS corresponde al concepto de agente. Un agente está representado por una constante agente (su nombre). En la definición de una constante agente se
pueden utilizar otras constantes agente, es decir, otros agentes.
2
Incluye tanto las acciones generadas desde otros objetos (o el mismo objeto) como las
acciones generadas por el propio objeto. Es decir, el objeto visto como cliente y servidor.
5.2. PROCESOS EN OASIS 3.0
51
Existe
P una constante adicional e implícita denotada por 0 y definida como
0 =
i∈I ai .Si , con I = ∅. Por lo tanto, desde 0 no existen transiciones
posibles. Extensiones del tipo if C then a1 .S1 else a2 .S2 pueden ser definidas
escribiéndolas como (if C then a1 .S1 ) + (if ¬C then a2 .S2 ).
Ejemplo 20 A continuación se especifica un proceso P y se detalla el sistema
de transiciones asociado.
P
P1
def
≡
def
≡
def
a.P1
b.P2 + e.P3
≡
c.P2 + b.P2 + d.P1
≡
0
κP
AP
a
→
=
=
=
b
=
=
{P, P1 , P2 , P3 }
{a, b, c, d, e}
{(P, P1 )}
d
=
=
P2
P3
→
c
→
→
e
→
def
{(P1 , P2 ), (P2 , P2 )}
{(P2 , P2 )}
{(P2 , P1 )}
{(P1 , P3 )}
Definición 14 Estado del proceso. Llamaremos estado del proceso a la constante agente que en un determinado instante representa al proceso.
Un proceso puede ser representado por un grafo de transiciones. La Figura
5.1 muestra el grafo de transiciones para el proceso P del ejemplo.
De acuerdo con el lenguaje que se ha definido para especificar procesos,
un estado de proceso coincide con una constante agente del proceso, y a su
vez, se corresponde con un nodo del grafo de transiciones del proceso. Esto es
relevante para establecer una formalización directa y sencilla para las especificaciones de proceso. Las especificaciones de proceso utilizadas corresponden a
una representación que se ha denominado “representación canónica” respecto
de otras en las cuales se deja mayor libertad para la construcción de expresiones agente, las cuales tienen su equivalente en la representación canónica.
Ejemplo 21 Una especificación de proceso para un cajero automático. Primero
se muestra una versión no canónica de la representación del proceso y a continuación la correspondiente especificación canónica tal como se entiende en
este trabajo.
52
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
P
a
P3
e
P1
b
d
P2
c
b
Figura 5.1: Grafo de transiciones del proceso P.
ATM1 = new_ATM.ATM2;
ATM2 = destroy_ATM.ATM5 + read_card.(cancel +
::check_card_w_bank(n,p).ATM3).::eject.::ready.ATM2;
ATM3 = bad_PIN_msg +
card_accepted.(cancel + issue_transaction(n,m).ATM4);
ATM4 = dispense_cash(m) + TA_failed_msg;
ATM5 = 0;
5.2. PROCESOS EN OASIS 3.0
53
ATM5
ATM1
new_ATM
destroy_ATM
ATM2
::ready
read_card
::eject
cancel
dispense_cash(m)
::check card w bank(n,p)
bad_PIN_msg
TA_failed_msg
ATM4
ATM3
cancel
card_accepted
issue_transaction(n,m)
Figura 5.2: Representación del proceso en su forma no canónica.
El grafo de transiciones asociados se muestra en la Figura 5.2. Como
se puede observar, existen nodos del grafo que no coinciden con constantes
agentes que definen el proceso. A continuación se presenta la misma especificación de proceso en su forma canónica.
ATM1
ATM2
ATM3
ATM4
ATM5
ATM6
ATM7
ATM8
ATM9
=
=
=
=
=
=
=
=
=
new_ATM. ATM2;
destroy_ATM.ATM9 + read_card. ATM3;
cancel.ATM7 + ::check_card_w_bank(n,p).ATM4;
bad_PIN_msg.ATM7 + card_accepted.ATM5;
cancel.ATM7 + issue_transaction(n,m).ATM6;
dispense_cash(m).ATM7 + TA_failed_msg.ATM7;
::eject.ATM8;
::ready.ATM2;
0;
El grafo de transiciones para esta nueva representación del proceso se muestra en la Figura 5.3. En este caso cada nodo del grafo coincide con una con-
54
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
stante agente de la definición del proceso.
ATM9
ATM1
new_ATM
destroy_ATM
ATM2
::ready
ATM8
read_card
::eject
ATM3
cancel
ATM7
dispense_cash(m)
::check_card_w_bank(n,p)
bad_PIN_msg
TA_failed_msg
ATM6
ATM4
cancel
card_accepted
ATM5
issue_transaction(n,m)
Figura 5.3: Representación del proceso en su forma canónica.
En la plantilla de clase OASIS 3.0, para cada proceso R existe implícitamente un atributo variable de sort κR con el mismo nombre del proceso.
Dicho atributo representa el estado del proceso (la constante agente o nodo
del grafo de transiciones asociado) en el cual se encuentra el proceso. Como
veremos, cuando el objeto está en el estado 0 en un determinado proceso, el
comportamiento del objeto no está siendo afectado por el proceso (el proceso
no determina ni permisos ni obligaciones para el objeto).
Nótese que un mismo estado del proceso puede estar asociado a más de un
estado del objeto (un σ distinto).
5.2.1.
Procesos como fórmulas en Lógica Dinámica
Como se ha expuesto, los operadores de la Lógica Deóntica que expresan
obligaciones, prohibiciones y permisos pueden ser vistos como una variante de
5.2. PROCESOS EN OASIS 3.0
55
Lógica Dinámica. Esto sugiere que los procesos de obligación y prohibición se
corresponden del mismo modo con fórmulas en Lógica Dinámica.
Una especificación de proceso determina una conducta particular del objeto. Diremos que un proceso afecta a un objeto si el objeto debe comportarse según la conducta establecida por dicho proceso. Comúnmente, el objeto
seguirá la conducta del proceso en partes de su vida. Un caso particular es un
proceso que afecta al objeto durante toda su existencia.
Un proceso que establece permisos se puede expresar como un conjunto de
fórmulas en Lógica Dinámica de la forma ¬φ → [a]f alse, del mismo modo que
se indicó para las fórmulas de precondiciones.
De forma análoga, un proceso que establece obligaciones se puede expresar
como un conjunto de fórmulas en Lógica Dinámica de la forma ψ → [¬a]f alse,
como se hace para las fórmulas de disparos.
Como veremos, en ambos casos se obtendrán adicionalmente fórmulas por
transición de estado del proceso. Estas fórmulas son del mismo tipo usado para
evaluaciones, es decir, ψ → [a]φ0 .
a
Sea R un proceso definido por el sistema de transiciones (κR , AR , {→: a ∈
a
a
AR }), E,E 0 ∈ κR . Si (E, E 0 ) ∈→, esto suele escribirse como E → E 0 y se dice
que a es una acción desde E.
Ejemplo 22 Utilizando el proceso P presentado en el ejemplo 20.
De acuerdo con el sistema de transiciones de P , se tiene que: a es
una acción desde P , b es una acción desde P1 y desde P2 , c es una
acción desde P2 , d es una acción desde P2 y e es una acción desde
P1 .
Definición 15 Predicado de ocurrencia de una acción en un estado
del proceso. Sea r el atributo variable asociado al estado del proceso R. Si
a es una acción desde un estado E del proceso, llamaremos predicado de
ocurrencia de a en E al predicado ((r = E) ∧ C) y lo denotaremos por ΩEa .
Siendo C la expresión boolean cuando la transición (E, E 0 ) tiene definida una
condición C. Si la transición no tiene condición el predicado de ocurrencia
de a en E es (r = E). Además, por defecto, si a no es una acción desde E,
entonces ΩEa ≡ false.
Ejemplo 23 Los predicados de ocurrencia de cada acción en cada estado del
proceso P son:
56
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
ΩP a
ΩP1 b
ΩP2 b
ΩP2 c
ΩP2 d
ΩP1 e
≡
≡
≡
≡
≡
≡
(p = P )
(p = P1 )
(p = P2 )
(p = P2 )
(p = P2 )
(p = P1 )
Para el resto de combinaciones entre estado del proceso y acciones, el
predicado de ocurrencia es f alse.
Definición 16 Predicado de ocurrencia de una acción en un proceso.
Ampliando el concepto anterior al proceso como un todo, llamaremos predicado de ocurrencia de a en R, denotado por ΩR∗ a , a la disyunción de
predicados de ocurrencia de a desde E, para cada constante agente E que
define al proceso R.
Ejemplo 24 Los predicados de ocurrencia en P para cada una de sus acciones, son:
ΩP ∗ a
ΩP ∗ b
ΩP ∗ c
ΩP ∗ d
ΩP ∗ e
≡
≡
≡
≡
≡
(p = P )
((p = P1 ) ∨ (p = P2 ))
(p = P2 )
(p = P2 )
(p = P1 )
El significado de ΩR∗ a es el siguiente: “ΩR∗ a se satisface si y sólo si el
proceso R está en algún estado de proceso E y algún ΩEa se satisface, es
decir, a es una acción desde E y además se cumple la condición C asociada
(si ésta existe)”.
a
Así, un proceso R, definido por el sistema de transiciones (κR , AR , {→:
a ∈ AR }), se corresponde con las fórmulas en Lógica Dinámica presentadas a
continuación.
Fórmulas por transiciones.
Efectúan la evolución del proceso de acuerdo a las transiciones definidas
a
y a la ocurrencia de acciones. Para cada a ∈ AR , y para cada (E, E 0 ) ∈→ se
0
obtiene la siguiente fórmula: ΩEa → [a](r = E ).
Ejemplo 25 Las fórmulas por transiciones para el proceso P son:
5.2. PROCESOS EN OASIS 3.0
(p = P )
(p = P1 )
(p = P2 )
(p = P2 )
(p = P2 )
(p = P1 )
→
→
→
→
→
→
57
[a](p = P1 )
[b](p = P2 )
[b](p = P2 )
[c](p = P2 )
[d](p = P1 )
[e](p = P3 )
Además, siendo anew la acción de creación para instancias de la clase,
entonces:
a) Si R es un proceso que establece obligaciones entonces, además, existirá
la fórmula:
[anew ](r = 0)
Es decir, asumimos que un proceso de obligación no afecta al objeto
desde el comienzo de su existencia.
b) Si R es un proceso que establece permisos, la fórmula adicional es:
[anew ](r = E1 )
E1 ∈ κR es la constante agente de inicio del proceso.
Es decir, asumimos que un proceso de permiso afecta al objeto
desde el comienzo de su existencia.
Fórmulas por Permisos (sólo si R es un proceso que establece permisos).
De acuerdo con el estado del proceso, una fórmula de permiso establece la
situación en la cual la ocurrencia de una acción se permite. Para cada a ∈ AR
se obtiene la siguiente fórmula: ¬ΩR∗ a → [a]f alse.
Ejemplo 26 Si en el ejemplo tratado, el proceso P fuera un proceso que establece secuencias de acciones permitidas, las fórmulas de permiso asociadas
serían:
¬(p = P )
¬((p = P1 ) ∨ (p = P2 ))
¬(p = P2 )
¬(p = P2 )
¬(p = P1 )
→
→
→
→
→
[a]false
[b]false
[c]f alse
[d]false
[e]false
58
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
Fórmulas por Obligaciones (sólo si R es un proceso que establece
obligaciones).
De acuerdo al estado del proceso, una fórmula de obligación establece la
situación en la cual la ocurrencia de una acción es obligatoria. Para cada
a ∈ AR se obtiene la siguiente fórmula: ΩR∗ a → [¬a]false.
Ejemplo 27 Si en el ejemplo tratado, el proceso P fuera un proceso que establece secuencias de acciones obligatorias, las fórmulas de obligación asociadas serían:
(p = P )
((p = P1 ) ∨ (p = P2 ))
(p = P2 )
(p = P2 )
(p = P1 )
5.3.
→
→
→
→
→
[¬a]false
[¬b]false
[¬c]f alse
[¬d]false
[¬e]false
Un ejemplo más extenso
Considerar la siguiente especificación OASIS 3.0 para una clase “Máquina
de venta de chocolatinas”. Se tiene la operación CANCEL que devuelve al
usuario las monedas introducidas. Además, el protocolo GETCHOC determina que sólo se aceptan hasta tres monedas, pudiendo obtener hasta tres
chocolatinas en una compra.
5.3. UN EJEMPLO MÁS EXTENSO
59
class vm
identification
number: (number);
constant attributes
number: nat.
variable attributes
num_chocs: nat;
credit: nat(0);
switch_on: bool(false);
events
set new;
coin_in;
coin_out;
choc;
light_empty;
operations
CANCEL:
CANCEL1= {credit>1}::coin_out.CANCEL1 +
{credit<=1}::coin_out;
triggers
::light_empty when {nchocs=0 and switch_on=false};
valuations
[coin_in] credit=credit+1;
[::coin_out] credit=credit-1;
[choc] nchocs=nchocs-1, credit=credit-1;
[::light_empty] switch_on=true;
preconditions
choc if {credit>0 and nchocs>0};
CANCEL if {credit>0};
protocols
GETCHOC:
GETCHOC1= coin_in.GETCHOC2;
GETCHOC2= choc.GETCHOC1 + coin_in.GETCHOC3 +
::coin_out.GETCHOC1;
GETCHOC3= choc.GETCHOC2 + coin_in.GETCHOC4 +
::coin_out.GETCHOC2;
GETCHOC4= choc.GETCHOC3 + ::coin_out.GETCHOC3;
end class
El sistema de transición de estados para la operación CANCEL es el siguiente:
κCANCEL = {CANCEL1, 0}
ACANCEL = {::coin_out}
coin_out
→ = {(CANCEL1,CANCEL1), (CANCEL1,0)}
60
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
CANCEL 1
::coin_out
0
::coin_out
Figura 5.4: Grafo de transiciones para la operación CANCEL
La figura 5.4 muestra el grafo de transiciones para la operación CANCEL.
El sistema de transición de estados para el protocolo GETCHOC es el
siguiente:
κGETCHOC = {GETCHOC1, GETCHOC2, GETCHOC3, GETCHOC4}
A GETCHOC = {coin_in, choc, ::coin_out}
coin_in
→ = {(GETCHOC1,GETCHOC2), (GETCHOC2,GETCHOC3),
(GETCHOC3,GETCHOC4)}
choc
→

= {(GETCHOC2,GETCHOC1), (GETCHOC3,GETCHOC2),
(GETCHOC2,GETCHOC3)}
coin_out
 → = {(GETCHOC2,GETCHOC1), (GETCHOC3,GETCHOC2),
(GETCHOC2,GETCHOC3)}
La figura 5.4 muestra el grafo de transiciones para el protocolo GETCHOC.
choc
GETCHOC1
coin_in
::coin_out
choc
choc
coin_in
GETCHOC2
GETCHOC3
::coin_out
coin_in
GETCHOC4
::coin_out
Figura 5.5: Grafo de transiciones para el protocolo GETCHOC
A continuación se presentan las fórmulas en Lógica Dinámica asociadas a
la clase vm
Fórmulas de cambio de estado
Evaluaciones explícitamente definidas
5.3. UN EJEMPLO MÁS EXTENSO
61
credit=N −→ [coin_in] credit=N+1
credit=N −→ [::coin_out] credit=N-1
nchocs=N ∧ credit=M −→ [choc] nchocs=N-1 ∧ credit=M-1
[::light_empty] switch_on=true
Evaluaciones por las transiciones del proceso GETCHOC
[set] getchoc=GETCHOC1
getchoc=GETCHOC1 −→ [coin_in] getchoc=GETCHOC2
getchoc=GETCHOC2 −→ [coin_in] getchoc=GETCHOC3
getchoc=GETCHOC3 −→ [coin_in] getchoc=GETCHOC4
getchoc=GETCHOC2 −→ [choc] getchoc=GETCHOC1
getchoc=GETCHOC3 −→ [choc] getchoc=GETCHOC2
getchoc=GETCHOC4 −→ [choc] getchoc=GETCHOC3
getchoc=GETCHOC2 −→ [::coin_out] getchoc=GETCHOC1
getchoc=GETCHOC3 −→ [::coin_out] getchoc=GETCHOC2
getchoc=GETCHOC4 −→ [::coin_out] getchoc=GETCHOC3
Evaluaciones por transiciones del proceso CANCEL
[set] cancel=0
[CANCEL] cancel=CANCEL1
cancel=CANCEL1 ∧ credit>1−→ [::coin_out] cancel=CANCEL1
cancel=CANCEL1 ∧ credit=1−→ [::coin_out] cancel=0
Fórmulas de prohibición
Fórmulas explícitamente definidas
q(nchocs>0 ∧ credit>0) −→ [choc] false
q(credit>0) −→ [CANCEL] false
Fórmulas por prohibiciones desde el proceso GETCHOC
q((getchoc=GETCHOC1) ∨ (getchoc=GETCHOC2) ∨ (getchoc=GETCHOC3))
−→ [coin_in] false
q((getchoc=GETCHOC2) ∨ (getchoc=GETCHOC3) ∨ (getchoc=GETCHOC4))
−→ [choc] false
q((getchoc=GETCHOC2) ∨ (getchoc=GETCHOC3) ∨ (getchoc=GETCHOC4))
−→ [::coin_out] false
62
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
Fórmulas de obligación
Fórmula explícitamente definida
nchocs=0 ∧ switch_on=false −→ [q::light_empty] false
Fórmula por la obligación desde el proceso CANCEL
(cancel=CANCEL1 ∧ credit>1) ∨ (cancel=CANCEL1 ∧ credit<=1)
−→ [q::coin_out] false
A continuación se presenta una especificación equivalente para la “Máquina
de venta de chocolatinas”, en la cual según la formalización presentada, las
especificaciones de proceso han sido interpretadas como fórmulas en la misma
variante de lógica dinámica utilizada para el resto de la plantilla.
class vm
identification
number: (number);
constant attributes
number: nat;
variable attributes
num_chocs: nat;
credit: nat;
# atributos variables usados para cambios en procesos #
cancel:nat;
getchoc:nat;
events
set new;
coin_in;
coin_out;
choc;
light_empty;
# el evento de inicio de la operacion CANCEL #
CANCEL;
triggers
::light_empty when {nchocs=0 and switch_on=false};
# disparo correspondientes a la operación CANCEL #
::coin_out when {(credit>1 and cancel=1)
or (credit<=1 and cancel=1)};
valuations
[coin_in] credit=credit+1;
[::coin_out] credit=credit-1;
[choc] nchocs=nchocs-1, credit=credit-1;
[::light_empty] switch_on=true;
# evaluaciones correspondientes a la operación CANCEL #
5.4. ASPECTOS ADICIONALES
63
[set] cancel=0;
[CANCEL] cancel=1;
{credit>1 and cancel=1} [::coin_out] cancel=1;
{credit<=1 and cancel=1} [::coin_out] cancel=0;
# evaluaciones correspondientes al protocolo GETCHOC #
[set] getchoc=1;
getchoc=1 [coin_in] getchoc=2;
getchoc=2 [coin_in] getchos=3;
getchoc=3 [coin_in] getchoc=4;
getchoc=2 [choc] getchoc=1;
getchoc=3 [choc] getchoc=2;
getchoc=4 [choc] getchoc=3;
getchoc=2 [::coin_out] getchoc=1;
getchoc=3 [::coin_out] getchoc=2;
getchoc=4 [::coin_out] getchoc=3;
preconditions
choc if {credit>0 and nchocs>0};
CANCEL if {credit>0};
# precondiciones correspondientes al protocolo GETCHOC #
coin_in if {getchoc=1 or getchoc=2 or getchoc=3};
choc if {getchoc=2 or getchoc=3 or getchoc=4};
coin_out if {getchoc=2 or getchoc=3 or getchoc=4};
end class
5.4.
Aspectos adicionales
Manteniendo el marco formal establecido, en este apartado se presentan
aspectos adicionales que extienden la capacidad expresiva que puede ser usada
en especificaciones de proceso.
Tratamiento de pasos y operaciones
Un paso es un conjunto consistente de acciones que acontecen en un instante dado en la vida de un objeto. Una acción está asociada a un servicio.
El servicio puede ser un evento o una operación. El evento no tiene duración,
es instantáneo. En cambio, una operación establece una secuencia obligatoria
de acciones y, en general, tiene una duración.
El cliente no tiene porqué conocer si un servicio corresponde a un evento
o una operación en el servidor. Por esto, en la acción acontecida en el cliente,
y que refleja la solicitud del servicio, no se hace referencia alguna que distinga
entre solicitar un evento o solicitar una operación.
En el servidor, el tratamiento para servir una operación es distinto al dado
cuando el servicio es un evento. Al proveer operaciones consideraremos lo
siguiente:
64
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
Se asume que las precondiciones o evaluaciones (si existen) asociadas a
una operación son precondiciones o evaluaciones para el evento de inicio
de la operación.
Para asegurar la correcta realización de una operación, mientras una operación esté en ejecución, no deben servirse otros eventos ni operaciones
que hagan incompatible el concepto de paso (conjunto consistente de
acciones) con la obligatoriedad de ejecución de las acciones de la operación3 .
Una operación puede ser vista como una secuencia de acciones (las que
determina su especificación) más dos acciones implícitas: la acción de inicio
de la operación y la acción de término de la operación. La acción de inicio
tiene siempre un evento requerido por un determinado cliente (quien solicita
la operación). La acción de término tiene siempre un evento requerido a sí
mismo, obligado e inmediatamente posterior a la ejecución de la última acción
ejecutada por la operación.
El mantener implícito las acciones de inicio y término de operación simplifica la especificación. Al mismo tiempo, apoya la idea de que tanto eventos
como operaciones sean tratados en la especificación bajo un concepto más
amplio; el concepto de servicio. A continuación, se abordará el tratamiento
de operaciones, sólo para mostrar la correspondencia con la formalización de
procesos ya realizada (en la que no se discutió el tratamiento de operaciones).
Sea op una operación definida para el objeto. Denotaremos por op• a la
acción de inicio de la operación y por op¯ a la acción de término de la operación.
Si existiera una precondición como: ¬φ → [op]f alse, se interpretaría implícitamente como una precondición para la acción de inicio de la operación, es
decir, ¬φ → [op• ]f alse. Del mismo modo, una evaluación del tipo ψ → [op]φ se
interpreta como una evaluación asociada a la acción de inicio de la operación,
es decir, ψ → [op• ]φ.
Según lo anterior, el tratamiento de operaciones se reduce a la ejecución
de las acciones de la operación más las dos acciones implícitas de inicio y fin
de la operación.
Queda por asegurar que al permitirse concurrencia intra-objeto (de eventos
y operaciones), las acciones de un paso sean siempre consistentes y a la vez se
cumpla la obligatoriedad de las acciones de una operación en ejecución.
3
El problema es análogo al de control de concurrencia de transacciones, ampliamente
tratado en bases de datos relacionales. Nótese que la definición previa de paso era aplicable
sólo para acciones ejecutadas en un mismo instante. Este concepto debe ser extendido para
considerar cierta duración asociada a la ejecución de una operación.
5.4. ASPECTOS ADICIONALES
65
La no-consistencia entre acciones es difícil de establecer. Sin embargo, la
consistencia se cumple siempre si las acciones no están en conflicto4 . El conjunto de atributos sobre el cual puede tener efecto una operación está determinado
por la unión de los conjuntos de atributos sobre los cuales tienen efecto las
acciones incluidas en la operación.
Asociado a cada operación, existe un atributo implícito del objeto que
determina en qué estado de la operación se encuentra el objeto. Si la operación
no está en ejecución entonces dicho atributo toma el valor 0. Siendo op el
atributo que registra el estado del proceso op, entonces existe una evaluación
implícita del tipo [op¯ ](op = 0). Esta evaluación hace que inmediatamente
después de ejecutarse la acción op¯ (acción de término del proceso), el proceso
op se encuentre en su estado de proceso 0, es decir, el proceso vuelve a una
situación de inactividad.
Por lo tanto, para asegurar que los eventos y operaciones (tratadas como
acciones) de un paso no estén en conflicto, además de verificar que no estén
en conflicto entre ellas, debe verificarse que no estén en conflicto con ninguna
operación en ejecución (cuyo valor de atributo asociado es diferente a 0).
Capacidad para especificar procesos anidados
Cuando las especificaciones de procesos son extensas (muchos estados de
proceso) es conveniente disponer de algún mecanismo de descomposición. Así,
un proceso puede ser descompuesto en subprocesos anidados5 especificados
separadamente. Esto a su vez promueve la reutilización de especificaciones de
subprocesos desde distintos procesos definidos en la plantilla de una clase.
Ejemplo 28 Consideremos la especificación de un proceso L. Por simplicidad, supondremos que las acciones a1 y a2 son acciones cuyo servicio es un
evento.
L
L1
L2
L3
def
≡
def
a1 .L1
≡
a2 .L1 + Q• .Q
≡
a1 .L3
def
def
≡
0
4
Dos acciones no están en conflicto si tienen efecto sobre conjuntos disjuntos de atributos.
Este criterio es bastante restringido respecto de la concurrencia intra-objeto. Sin embargo,
es fácil de determinar: basta con inspeccionar las evaluaciones asociadas a las acciones y
posibles derivaciones de atributos.
5
Por anidamiento entendemos la capacidad expresiva que permite que un proceso en su
definición haga referencia a otro proceso como una forma de transición compleja, definida
por otro proceso.
66
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
Q
Q1
Q2
def
≡
a2 .Q1 + a1 .Q2
def
Q¯ .L2
def
≡
≡
a1 .Q + a2 .Q2
Q• y Q¯ son dos acciones. Dichas acciones pueden verse como las acciones
de inicio y de término para un cierto proceso (Q), respectivamente.
Esto sugiere escribir L como:
def
L
L1
L2
L3
≡
a1 .L1
≡
a2 .L1 + q.L2
def
def
≡
def
≡
a1 .L3
0
Donde q es una acción que incluye al servicio no atómico Q. Así, el proceso
L es definido utilizando la especificación del proceso Q, reescrito como:
Q
Q1
Q2
def
≡
def
a2 .Q1 + a1 .Q2
≡
a1 .Q + a2 .Q2
≡
0
def
El proceso Q podría entonces ser utilizado en otras definiciones de proceso.
A su vez, el proceso Q también podría utilizar otras definiciones de proceso.
Así, la justificación de este anidamiento de especificaciones de proceso se
obtiene estableciendo la correspondencia de la especificación anidada con una
equivalente sin anidamiento.
5.5.
Conclusiones del capítulo
Se ha presentado una nueva propuesta para la especificación de procesos
en OASIS. Para la especificación de un proceso se utiliza un subconjunto de
CCS, asociándose una semántica adicional de obligación o permiso (prohibición) según se trate de una operación o un protocolo, respectivamente. De esta
forma, las especificaciones de proceso pueden ser directamente interpretadas
como un conjunto de fórmulas en la variante de Lógica Dinámica utilizada
en el resto de la plantilla de clase. Así, se dispone una representación homogénea para representar el comportamiento de los objetos de una clase. Esto
facilita la animación de especificaciones OASIS puesto que el proceso de traducción automática sólo debe tratar con una expresividad (la determinada
5.5. CONCLUSIONES DEL CAPÍTULO
67
por la variante de Lógica Dinámica usada), aunque en la especificación OASIS
la especificación del comportamiento se pueda hacer tanto desde el punto de
vista del estado del objeto como de las acciones acontecidas.
68
CAPÍTULO 5. ESPECIFICACIONES DE PROCESO
Capítulo 6
Interacción entre objetos
En este capítulo se introduce la noción de interacción entre objetos. En
OASIS, un sistema de información es una sociedad de objetos autónomos, concurrentes y que interactúan entre sí. La interacción entre objetos está basada
en comunicación. Para animar una especificación OASIS era necesario contar
con una interpretación operacional de la comunicación entre objetos determinada por una especificación. Además, la introducción de la perspectiva cliente
motivo un replanteamiento de los aspectos de comunicación en OASIS 2.2.
El capítulo está estructurado de la siguiente forma: Se presentan los mecanismos de comunicación disponibles en OASIS 2.2, realizando comparaciones
con el modelo usado por TROLL. Posteriormente se introduce un nuevo esquema de comunicación para OASIS, que extiende al usado por la versión 2.2
y que ha sido incorporado en OASIS 3.0. Finalmente se presenta un enfoque
alternativo más cercano a la filosofía de TROLL e inspirado en arquitecturas
software.
6.1.
Comunicación entre objetos en OASIS 2.2
En OASIS 2.2 para establecer comunicación entre objetos se dispone de
dos mecanismos de comunicación: disparos y eventos compartidos. En OASIS
2.2 al especificar la clase servidora es posible etiquetar los eventos con los
agentes que pueden requerir dichos eventos, usando la notación a:e, donde a
determina el objeto agente y e el evento solicitado.
6.1.1.
Disparos
En la Figura 6.1 se representa el mecanismo de disparos según el cual un
objeto de la clase C puede actuar como cliente requiriendo el servicio e a un
objeto de la clase S. Un caso particular de disparo es aquel en el cual en la
69
70
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
especificación de la clase del cliente no se declara el disparo, sin embargo, en
una fórmula o especificación de proceso de la clase del objeto servidor junto
al servicio provisto aparece una referencia de agente. En este caso se trata de
una relación cliente-servidor en la cual el cliente puede solicitar el servicio de
forma espontánea.
c
e
class C
...
triggers
S(s)::e if ...
...
e
s
class S
...
... c:e ...
...
Figura 6.1: Disparos en OASIS 2.2
La fórmula en lógica dinámica que rige los disparos en OASIS 2.2 es:
φ[¬e]f alse, que establece que cuando se satisface φ debe ocurrir e. El primer
inconveniente que aparece es que la fórmula de disparo forma parte de la especificación del cliente, por lo que e en general es un evento que no está en la
signatura del cliente sino en la del servidor. La incorporación de la perspectiva
cliente resuelve este problema. Además, la fórmula de disparo determina una
obligación sólo en el cliente, no en el servidor. Así, un disparo debería representar una comunicación asimétrica. Es decir, en un disparo la ocurrencia
del evento en el cliente debe ser una obligación, no así en el servidor, donde el
evento podría ser rechazado, por ejemplo por no satisfacerse una precondición.
La Figura 6.2 muestra como un disparo puede ser interpretado como el paso
de un mensaje un objeto cliente hacia un objeto servidor.
6.1.2.
Eventos compartidos
Un evento compartido es una comunicación simétrica y síncrona, todos los
objetos que comparten el evento juegan un papel de servidor. La ejecución del
evento compartido en cualquiera de los objetos que comparten dicho evento
sólo es posible si el evento ocurre en todos los participantes. El mecanismo
de comunicación por eventos compartidos corresponde a la abstracción de un
conjunto de comunicaciones. La aplicación principal de este mecanismo se centra en la sincronización entre las vidas de objetos agregados y las vidas de sus
componentes para todos aquellos eventos que sean relevantes. El disponer de
esta abstracción facilita la especificación de dicha sincronización permitiendo
abstraerse de detalles de implementación del protocolo de comunicación aso-
6.1. COMUNICACIÓN ENTRE OBJETOS EN OASIS 2.2
71
Cliente
Statei-1
ti
ti+1
Statei
Statei+1
e
e
Servidor
Statej-1
tj
Statej
tj+1
Statej+1
Figura 6.2: Interpretación de un disparo como el paso de un mensaje.
ciado. La Figura 6.3 muestra dos situaciones de compartición de eventos, a la
izquierda se trata de dos objetos pertenecientes a clases entre las cuales no
existe una relación estructural, en la parte derecha el objeto x es un agregado
cuyo componente es el objeto y. La ocurrencia del evento e debe ocurrir en
ambos objetos servidores o en ninguno de ellos.
e
c
x
e
e
c
e
x
e
e
y
y
Figura 6.3: Eventos compartidos en OASIS 2.2
En un nivel de implementación al establecer este mecanismo de comunicación para un entorno en el cual los objetos son autónomos y concurrentes es
necesario utilizar un protocolo de confirmación de dos fases. Así, un proceso
actuará como coordinador y se encargará de concertar a los participantes y
verificar si todos pueden proveer el servicio. Se realizaron varios experimentos para la implantación de este tipo de comunicación usando Programación
Lógica Concurrente (ver [46]). A continuación se muestra un protocolo para
este tipo de comunicación y en el cual uno de los propios objetos servidores
desempeña las tareas de coordinación. El protocolo se muestra en la Figura
72
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
6.4 y consta de los siguientes pasos:
1. El cliente requiere el evento compartido de uno de los servidores que
comparten dicho evento. Esta comunicación en el cliente corresponde
directamente a un disparo desde el cliente o puede tratarse de un evento
activo (requerido por el cliente sin que explícitamente se incluyan en la
especificación la causa de su ocurrencia).
2. El servidor que recibe la solicitud de servicio actúa de coordinador y
dispara el evento compartido al resto de servidores que comparten el
evento. Al mismo tiempo el servidor-coordinador verifica la admisibilidad
del evento según su estado. El servidor-coordinador queda a la espera de
la confirmación desde los otros objetos servidores.
3. Cada servidor (excepto el coordinador) verifica la admisibilidad del evento y dispara un evento hacia el coordinador, indicando si el evento sería
admitido o no. Si dicho servidor no admitiera el evento queda liberado
en cuanto a sincronización, sin embargo, si admitiera el evento, deberá
esperar a la confirmación desde el servidor-coordinador.
4. Con todas las confirmaciones recibidas (incluyendo la suya), el servidorcoordinador verifica si son todas positivas o existe alguna negativa. Si
todos admitieran el evento, el servidor-coordinador dispara al resto de
servidores la confirmación positiva. Si algún servidor no admitiera el
evento, para cada servidor que respondió afirmativamente (y que está
en espera) se dispara una confirmación negativa. Además, el servidorcoordinador dispara al cliente un evento que indica el éxito o fracaso de
su solicitud. La Figura 6.4 ilustra el protocolo en el caso de respuestas
afirmativas en todos los objetos servidores involucrados.
5. Si el evento es admitido por todos los objetos que lo comparten, en cada
servidor, incluyendo al coordinador, ocurre (se ejecuta) el evento.
En OASIS existen eventos compartidos implícitos producto de la necesaria
coordinación entre las vidas de un objeto agregado respecto de sus componentes, por ejemplo: crear (o destruir) un objeto agregado, destruir un objeto
componente, insertar un objeto componente, remover un objeto componente,
cualquier evento que modifique un atributo en el componente y que a su vez
dicho atributo esté siendo utilizado (mediante visibilidad) por el objeto agregado.
6.1.3.
Comparación entre OASIS 2.2 y TROLL
TROLL es quizás el lenguaje de especificación más cercano a OASIS. Resulta interesante analizar el enfoque seguido en TROLL para modelar interacción
6.1. COMUNICACIÓN ENTRE OBJETOS EN OASIS 2.2
73
client
server
1
verify(event)
no_error
answer_ok
conf_ok
client
event
server k
verify(event)
server
i
answer_ok
server
1
server k
conf_ok
server
i
verify(event)
verify(event)
answer_ok
server
n
conf_ok
server
n
Figura 6.4: Un protocolo para implementar eventos compartidos.
entre objetos antes de proponer un nuevo esquema de comunicación entre objetos para OASIS. A continuación se presentan comparaciones entre OASIS
2.2 y TROLL respecto de cómo se realiza la interacción entre objetos.
En OASIS 2.2 los disparos son un mecanismo de comunicación asíncrono
y los eventos compartidos representan comunicación síncrona pero sólo
entre objetos servidores. En TROLL el event calling, el único mecanismo
de comunicación ofrecido es siempre síncrono, la relación calling e1 >>
e2 entre los eventos e1 y e2 establece que cada vez que ocurre e1 , e2
también debe ocurrir (aunque e2 puede ocurrir sin que ocurra e1 ). En
TROLL la ocurrencia de e1 en general no es una obligación, pues está
supeditada a la ocurrencia de e2 .
En TROLL todos los eventos son locales al objeto y se declaran explícitamente, es decir, están en su signatura. Por lo tanto, la perspectiva
cliente está ya incorporada.
Las relaciones cliente-servidor en OASIS se establecen mediante disparos
declarados explícitamente en la clase cliente y/o mediante especificación
de agentes en la clase servidora. En TROLL, cuando se desea establecer
una comunicación cliente-servidor y los objetos involucrados tienen una
74
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
relación de agregado-componente existen dos situaciones: si se quiere
establecer una relación de causalidad desde el agregado hacia el componente se utiliza el apartado calling en la sección events tal como se
ilustra en la parte izquierda de la Figura 6.5, en cambio si el sentido de la
causalidad es desde el componente hacia el agregado se utiliza la sección
interactions tal como se muestra en la parte derecha de la Figura 6.5.
Cuando los objetos no están relacionados estructuralmente es necesario
utilizar un constructor adicional llamado relationships. En una relationship se establecen relaciones de event calling que sincronizan ejecuciones
de eventos en un cliente con ejecuciones de eventos en un servidor, esto
se ilustra en la Figura 6.6.
e’
X
e
Y
class X
components
Comp:Y
...
events
e’
calling
Comp(y).e
...
e’
X
e
Y
class X
components
Comp:Y
...
events
e’
interaction
Comp(y).e >> e’
...
Figura 6.5: Caso de objetos relacionados estructuralmente.
e’
A
object class A
...
events
e’
...
e
B
object class B
...
events
e
...
relationship AB between A Client, B Server
interaction
Client.e’ >> Server.e
...
Figura 6.6: Caso de objetos no relacionados estructuralmente.
Los eventos compartidos de OASIS 2.2 equivalen en TROLL a una especificación de event calling en los dos sentidos, es decir, e1 >> e2 y
e2 >> e1 .
El event calling de TROLL establece directamente la causalidad entre
eventos. Esto ocasiona inconvenientes difíciles de solucionar al establecer una interpretación operacional para la comunicación, que sea consistente respecto de la semántica de la especificación. Una propuesta de
6.2. UN NUEVO ESQUEMA DE COMUNICACIÓN
75
interacción entre objetos para TROLL [32] muestra las dificultades para
conseguir asegurar la terminación y no postergación indefinida al usar event calling. En OASIS no existe causalidad directa entre eventos.
Sin embargo, un evento puede provocar indirectamente un disparo si su
ocurrencia hace que se satisfaga una condición de disparo en el estado
alcanzado. Con esto se consigue en forma indirecta el efecto de causalidad entre eventos. Sin embargo, el enfoque de OASIS no presenta los
inconvenientes de TROLL al momento de establecer una interpretación
operacional para la comunicación entre objetos.
6.2.
Un nuevo esquema de comunicación
En esta sección se presenta un nuevo enfoque para la interacción entre
objetos. Basado en lo expuesto anteriormente se mejora el esquema para comunicación entre objetos provisto por OASIS 2.2. En esta sección cuando no
se haga una referencia explícita de la versión de OASIS, se debe entender que
se trata de OASIS 3.0, aunque en los ejemplos se ha preferido utilizar una
sintaxis más cercana al formalismo del modelo en lugar de la sintaxis concreta
de OASIS 3.0.
La incorporación de la perspectiva cliente y el concepto de operación llevan de forma natural hacia la noción de acción, en la cual se utiliza el término
servicio para referirse en forma genérica a evento y operación. Así, la formalización de OASIS está basada en la idea de ocurrencia de acciones en la vida de
los objetos. Se asume por defecto que por cada acción a en la signatura de la
clase, además existe ¬a representando la no-ocurrencia de dicha acción. En un
instante determinado, una acción ocurre en un objeto si se provee un servicio
o si se requiere un servicio de otro objeto (o a sí mismo). Del mismo modo,
la no-ocurrencia de una acción en un objeto acontece cuando no se provee un
servicio o cuando no se requiere un servicio en un cierto instante.
Una acción establece una comunicación entre un cliente y un servidor.
Siendo a la acción hCliente, Servidor, Servicioi, cada vez que en el objeto
Cliente se activa una obligación asociada a la fórmula φ[¬a]false, la acción a
debe acontecerle. Asociada a la ocurrencia de dicha acción en el cliente, en el
objeto Servidor ocurrirá a ó ¬a según las fórmulas de prohibición definidas
sobre a. Si en el servidor, para alguna de sus fórmulas ¬φ[a]false se cumple
que |=w ¬φ, entonces ocurre ¬a, en caso contrario (|=w φ) ocurre a, siendo w
el mundo en el que está el objeto. Nótese que la ocurrencia o no-ocurrencia de
acciones (tanto en el cliente como en el servidor) depende de sus respectivos
estados (mundos) en el instante de requerir y de proveer el servicio, respectivamente. El instante en el cual se provee el servicio es igual o posterior al
instante en el que se requiere el servicio.
76
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
Cliente
Servidor
ocurre a
ocurre a o -a
Figura 6.7: Representación del mecanismo action sending.
En OASIS se dispone de cuatro mecanismos de comunicación. Cada uno
de ellos está caracterizado por los siguientes aspectos:
Síncrono vs. asíncrono. La comunicación será síncrona si el cliente de la
acción a debe esperar hasta conocer si en el servidor ocurre a o ¬a. Un caso
especial de comunicación síncrona se produce cuando el servidor es el que debe
esperar a que en el cliente ocurra (se genere) una determinada acción (la solicitud de servicio hacia el servidor). Cuando la comunicación es síncrona existe
una acción indicando la ocurrencia o no-ocurrencia de la acción esperada. La
comunicación será asíncrona si no existe espera asociada.
Ocurrencia forzada vs. ocurrencia no forzada. La comunicación es de
ocurrencia forzada para una acción a si su ocurrencia debe producirse tanto
en el cliente como en el servidor, o en ninguno de ellos.
6.2.1.
Mecanismos de comunicación
Los mecanismos de comunicación disponibles en OASIS son: action sending, action waiting, action calling y action sharing, los cuales se describen a
continuación.
Action sending: asíncrono, ocurrencia no forzada. Este mecanismo se
basa en la noción de obligación en el cliente. Sucede cuando es obligatoria la
ocurrencia de una acción y el objeto en cuestión es el cliente de dicha acción.
La Figura 6.7 ilustra este mecanismo1 .
1
En todas las figuras mostradas en este apartado las líneas verticales representan el paso
del tiempo de arriba hacia abajo. Si la línea es continua indica que el objeto no está en
espera. Si la línea es punteada indica que el objeto está en espera.
6.2. UN NUEVO ESQUEMA DE COMUNICACIÓN
Servidor
77
Cliente
ocurre a
ocurre a
Figura 6.8: Representación del mecanismo action waiting.
Ejemplo 29 En la especificación del objeto controlador(número,[1]) se
tiene la siguiente fórmula de obligación:
nivel > max
[¬valvula(nombre,[‘‘entrada’’])::cerrar] false
Cuando se satisface nivel>max, al objeto cliente controlador debe acontecerle la acción:
<self,valvula(nombre,[‘‘entrada’’]),cerrar>
En un instante igual o posterior al actual, al objeto servidor valvula(nombre,[‘‘entrada’’])y de acuerdo con su estado, le acontecerá:
<controlador(número,[1]),
valvula(nombre,[‘‘entrada’’]),cerrar>
o simplemente no ocurre dicha acción por no ser admitida.
Action waiting: síncrono, ocurrencia forzada. Este mecanismo también
se asocia a la noción de obligación. A diferencia del action sending, el objeto
en el cual se obliga a que ocurra la acción no es el cliente de la acción sino el
servidor. Es decir, el servidor está obligado a esperar que ocurra la acción en
el cliente. La Figura 6.8 ilustra este mecanismo.
Ejemplo 30 En la especificación del objeto sensor(tipo,[‘‘nivel’’]) se
tiene la siguiente fórmula de obligación:
conectado=false
[¬controlador(someone):set(temperatura)] false
Cuando en dicho objeto se satisface conectado=false es obligatorio que
le acontezca la acción:
<controlador(someone),
78
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
Servidor
Cliente
Servidor
Cliente
ocurriría a?
ocurriría a?
ocurre -a
ocurre a
ocurre -a
ocurre a
(a)
(b)
Figura 6.9: Representación del mecanismo action calling.
sensor(tipo,[‘‘nivel’’]),set(temperatura)>
Por tratarse de una obligación sobre un servicio provisto, el objeto servidor
sensor esperará hasta que ocurra la acción asociada.
Al implantar este tipo de interacción existiría la posibilidad de establecer
un timeout por defecto, un tiempo máximo durante el cual la obligación puede
afectar al servidor, es decir, cuánto tiempo esperará el servidor para recibir
cierta solicitud de servicio desde un cliente. Una vez alcanzado el timeout, en
el servidor ocurriría ¬a. Manipulando directamente el tiempo en la fórmula
que define la obligación podría también especificarse un timeout arbitrario.
Por ejemplo, redefiniendo el caso anterior con un timeout de 10 segundos:
(currenttime2 -timeinicio) 6 10 and conectado=false
[¬controlador(someone):set(temperatura)] false
Siendo timeinicio un atributo de dominio time afectado por alguna evaluación asociada a una acción de obligación por satisfacerse conectado=false.
Del mismo modo, mediante las pertinentes evaluaciones y obligaciones podría representarse el hecho de alcanzar el timeout sin haberse cumplido la
obligación.
Action calling: síncrono, ocurrencia forzada. Este mecanismo establece
que una acción ocurre en el cliente y en el servidor o en ninguno de ellos. La
Figura 6.9 ilustra este mecanismo. En la imagen (a) la acción a ocurre en el
cliente y en el servidor, en la imagen (b) la acción a no ocurre en ninguno de
ellos.
2
Asumiremos que currenttime es un atributo de dominio time, implícito para cada objeto
y que representa la fecha y hora actual. Este atributo se ve afectado por cada tick del reloj.
6.2. UN NUEVO ESQUEMA DE COMUNICACIÓN
79
Ejemplo 31 En la especificación de la clase coche (clase agregada) se tiene
la siguiente interacción con su objeto componente de la clase motor:
arrancar ⇒ motor.encender
Así, una acción con el servicio arrancar sólo ocurre si también ocurre la
acción con el servicio encender en el objeto componente motor.
Action sharing: síncrono, ocurrencia forzada. Una interacción action
sharing se produce cuando acciones en distintos objetos y asociadas a proveer
un servicio deben ocurrir todas o ninguna de ellas. Esta comunicación implica
una sincronización entre objetos servidores.
Ejemplo 32 En la especificación de la clase préstamo se tiene la siguiente
interacción con sus componentes de la clase libro y de la clase socio:
prestamo.prestar(Fecha,Socio,Libro) ⇔
libro(codigo,[Libro]).ser_prestado(Fecha)
prestamo.prestar(Fecha,Socio,Libro) ⇔
socio(numero,[Socio]).obtener_libro
Así, una acción con el servicio prestar(Fecha,Socio,Libro) sólo ocurre
en el objeto préstamo si también ocurren las acciones con el servicio ser_prestado(Fecha)
en el objeto componente libro(código,[Libro]) y la acción obtener_libro
en el objeto componente socio(número,[Socio]), y viceversa. Como la comunicación action sharing es de ocurrencia forzada, para que cualquiera de
las tres acciones ocurra deben ocurrir también las otras dos restantes.
6.2.2.
Comentarios adicionales
Mediante la combinación de action sending y action waiting es posible
modelar cualquier interacción entre objetos pues ambas son primitivas elementales de comunicación. Sin embargo, para simplificar la especificación se
proporcionan los mecanismos action calling y action sharing que establecen
interacciones más complejas en un nivel adecuado de abstracción, resultando
especialmente útiles para comunicación síncrona y de ocurrencia forzada entre
un objeto agregado y sus objetos componentes.
Al especificar una interacción particular entre objetos, los mecanismos de
comunicación disponibles son distintos dependiendo de qué clase se está especificando: la clase del cliente o la clase del servidor. Si se está especificando
la clase del objeto cliente para una determinada acción, los mecanismos de
comunicación disponibles son: action sending y action calling. Si se está especificando la clase del objeto servidor para dicha acción, los mecanismos de
comunicación disponibles son: action waiting y action sharing.
80
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
Cliente
Servidor
ocurre request
ocurre request
ocurre reply
ocurre reply
Figura 6.10: Representación de una interacción call/return
Una interacción del tipo request/reply o call/return (Remote Procedure
Call en arquitecturas distribuidas) puede ser especificada combinando una
comunicación action sending con una action waiting, tal como se ilustra en la
Figura 6.10.
6.3.
Arquitecturas software en el marco de OASIS
Arquitecturas Software [25] es un interesante enfoque para la construcción
de sistemas de información. La clave de esta propuesta se resume en la idea razonable de no comenzar a construir un sistema desde cero, sino que aprovechar
componentes disponibles e integrarlos en el nuevo sistema. Esta filosofía puede
aplicarse a cualquier abstracción establecida de camino a la solución, es decir,
la especificación de requisitos, diseño o implementación. El enfoque de Arquitecturas Software es ortogonal al enfoque Orientado a Objetos, sin embargo,
constituyen una buena combinación que permite por un lado implementar de
forma más directa y natural la filosofía de Arquitecturas Software y a la vez
hacer más efectiva la tecnología Orientada a Objetos. Durante la elaboración
de un nuevo esquema de interacción entre objetos en OASIS, se analizó la
conveniencia de incorporar la filosofía de Arquitecturas Software. Este apartado describe las principales consideraciones asociadas. Finalmente, debido a la
magnitud del cambio involucrado se decidió postergar para una siguiente versión esta alternativa. Una restricción que estaba presente era el asegurar una
cierta continuidad y compatibilidad de la nueva propuesta respecto de la existente, intentando realizar mejoras basadas en extensiones. La introducción de
la perspectiva cliente constituía en sí misma un cambio considerable respecto a
la versión 2.2 de OASIS, añadir la filosofía de Arquitecturas Software equivalía
a introducir la perspectiva cliente y bastante más.
6.3. ARQUITECTURAS SOFTWARE EN EL MARCO DE OASIS
6.3.1.
81
Componentes y conectores en OASIS
Los conceptos clave en Arquitecturas Software son componentes y conectores. Los componentes disponen de puertos mediante los cuales pueden proveer
o requerir servicios. Los conectores establecen enlaces (attachements) entre los
puertos de componentes.
En OASIS 3.0 el concepto de componente podría coincidir naturalmente
con el de clase (sea una clase simple o compleja). En OASIS 3.0 el enlace entre
clases puede establecerse de tres formas: en interfaces, mediante relaciones
cliente-servidor explícitas en las acciones o por medio de agregaciones. Así, una
interfaz determina que servicios puede un objeto cliente requerir de un objeto
servidor. Alternativamente, en el cliente se especifica el servidor de una acción
y en el servidor se puede especificar el cliente de una acción. Por otra parte,
una agregación determina una relación estructural y de comportamiento entre
el objeto agregado y sus objetos componentes, particularmente respecto de los
servicios provisto y requeridos, una relación de agregación involucra enlaces
entre acciones en el agregado y acciones en sus componentes y viceversa.
Un primer problema a resolver para que una clase OASIS 3.0 coincida
con el concepto de componente es prescindir de la definición explícita de los
clientes y servidores de las acciones en la especificación de una clase. Es decir,
en una especificación de clase no indicar a qué objeto se le provee un servicio
ni a qué objeto se le requiere un servicio. En el caso de los clientes, siempre
es posible prescindir del cliente en una acción. Si no se especifica el cliente
significa que puede ser cualquier objeto que tenga acceso al servicio mediante
una especificación de interfaz. En el caso que interese establecer diferencias de
comportamiento para el mismo servicio pero solicitado por distintos clientes,
se sugiere reemplazar el servicio original por dos servicios distintos cuya accesibilidad queda determinada en interfaces diferentes. Prescindir de los servidores
es sólo posible cuando el servidor es el mismo objeto, es decir, cuando se trata
de acciones asociadas a proveer un servicio, pero cualquier acción asociada a
requerir un servicio debe incluir la declaración del objeto servidor.
Prescindir de la definición de clientes y servidores permitiría que una clase
OASIS pueda ser utilizada sin modificaciones en diferentes contextos, interactuando con otras clases. Es importante destacar que aunque en OASIS un
componente siempre estaría representado por una clase (simple o compleja), no
necesariamente todas las clases deben ser tratadas como componentes. Según
esto, un componente en OASIS podría contener clases que dependen del contexto del componente, aunque el componente como un todo no depende del
contexto. Sin embargo, dejar esta libertad en OASIS obligaría a introducir
en forma no homogénea el concepto de componente, complicando el modelo.
A continuación se propone un esquema de interacción para OASIS basado
en Arquitecturas Software, en el cual el concepto de componente se aplica
82
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
uniformemente a todas las clases.
El concepto de acción como tupla < Cliente, Servidor, Servicio > se reduciría a: acción asociada a Servicio provisto y acción asociada a Servicio
requerido. Si en una especificación de clase OASIS no se especifican ni clientes
ni servidores entonces toda acción de requerir un servicio debería estar explícitamente declarada como un servicio adicional en la signatura de la clase.
Estos servicios serían solicitados por el objeto a sí mismo mediante obligaciones (disparos u transiciones en una operación). Complementariamente, se
propone ampliar el mecanismo de interfaz, convirtiéndolo en el concepto de
conector, utilizado en Arquitecturas Software. Una interfaz en OASIS establece
relaciones de visibilidad y acceso de un cliente respecto de un servidor. Así, un
conector establecerá relaciones de ocurrencia entre acciones en el cliente (por
requerir un servicio) respecto de acciones en el servidor (por proveer un servicio). Estas relaciones de ocurrencia corresponden a los attachements definidos
entre puertos de componentes.
Un attachment se expresaría como: Acción_en_Cliente MC Acción_en_Servidor, donde MC es el mecanismo de comunicación utilizado. Los mecanismos de comunicación disponibles en OASIS se especificarían en cada attachement,
y serían:
Action waiting: Acción_en_Cliente ->? Acción_en_Servidor (el servidor está obligado a esperar hasta que el cliente solicite el servicio).
Action sending: Acción_en_Cliente -> Acción_en_Servidor (comunicación asíncrona, en el servidor puede ocurrir la Acción_en_Servidor
o una acción asociada a su rechazo)
Action calling: Acción_en_Cliente =>> Acción_en_Servidor (la acción ocurre en el cliente y en el servidor o en ninguno de los dos, el cliente
es el que genera la comunicación)
Un caso particular se presenta en el mecanismo action sharing
mediante el cual se establece un attachement entre objetos por
proveer un servicio, es decir, entre objetos actuando como servidores.
Action sharing: Acción_en_Servidor1 == Acción_en_Servidor2 (la
acción ocurre en todos los servidores que la comparten).
Cuestiones por resolver:
1. ¿Un conector debería ser tratado uniformemente como una clase?. La respuesta es NO. Aunque pareciera interesante llegar a establecer propiedades
de plantilla y relaciones de herencia o agregación entre conectores, aparecen los siguientes inconvenientes:
6.3. ARQUITECTURAS SOFTWARE EN EL MARCO DE OASIS
83
- Los attachements entre acciones del cliente y servidor es una sección de
especificación que no existe en una plantilla de clase OASIS y sólo sería
necesaria para clases que representaran a un conector.
- No tiene sentido hablar de instancias de conector, su creación o destrucción. Si un conector fuera relevante en cuanto a propiedades, debería
modelarse como una clase adicional, con sus respectivos conectores a las
clases que originalmente conectaba.
- No parece interesante pensar en reutilización de conectores pues precisamente son lo que determinan a un sistema en particular. Esto no
impide que los componentes que sean clases agregadas sean reutilizados
incluyendo todos los conectores internamente definidos.
2. ¿Cuántas clases pueden relacionarse usando el mismo conector? La respuesta no parece tan evidente. La cuestión habría que resolverla pensando en que tipo de relación de comunicación se desea modelar en un
conector. Por ejemplo, si sólo se trata de establecer attachements, una
alternativa extrema podría ser definir sólo un conector para todo el sistema. Si se trata de particularizar interacciones entre ciertos componentes sería recomendable establecer un conector para cada grupo de
participantes en una interacción de interés.
6.3.2.
Un ejemplo aplicando arquitecturas software en OASIS
A continuación se muestra el ejemplo de la máquina de venta de chocolatinas (presentado en el capítulo 5), el cual ha sido modificado (incluyendo
cambios sintácticos) para incorporar las ideas asociadas a Arquitecturas Software planteadas antes.
class vm
identification
number:(number);
constant attributes
number:nat;
variable attributes
num_chocs:nat;
credit:nat;
switch_on:bool(false);
events3
set new;
3
En la signatura de eventos se incluyen explícitamente como eventos adicionales los eventos asociados a requerir un servicio (para facilitar la lectura, estos se han prefijado con
“req_”. Es importante destacar que particularmente cuando un objeto puede requerir un
servicio a sí mismo existen dos eventos diferentes involucrados: el primero correspondiente a
84
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
get_coin;
give_choc;
give_coin;
light_empty;
req_give_choc;
req_give_coin;
req_light_empty;
operations
cancel_button:
S1 = {credit>1}req_give_coin.S1 + {credit<=1}req_give_coin;
choc_button:
S1 = req_give_choc;
triggers
req_light_empty when {nchocs=0 and switch_on=false};
valuations
[get_coin] credit=credit+1;
[req_give_coin] credit=credit-1;
[req_give_choc] nchocs=nchocs-1, credit=credit-1;
[req_light_empty] switch_on=true;
preconditions
choc_button if {credit>0 and nchocs>0};
cancel_button if {credit>0};
protocols
getchoc:
G1 = get_coin.G2;
G2 = get_coin.G3 + choc_button.G1 + cancel_button.G1;
G3 = get_coin.G4 + choc_button.G2 + cancel_button.G1;
G4 = choc_button.G3 + cancel_button.G1;
end class
class customer
identification
name:(name);
constant attributes
name:string;
events
birth new;
good_bye destroy;
req_put_coin;
req_push_cancel;
req_push_choc;
get_coin;
requerir el servicio y el segundo está asociado a proveer el servicio. Por esta razón, aunque
en el ejemplo los eventos give_choc, give_coin y light_empty no afectan al objeto, ellos
son requeridos cuando acontecen los correspondientes eventos prefijados con req_.
6.4. CONCLUSIONES DEL CAPÍTULO
85
get_choc;
end class
connector among vm, self 4
attachements
req_give_coin -> give_coin;
req_give_choc -> give_choc;
req_light_empty -> light_empty;
end connector
connector among customer alias C, vm alias VM
attachements
C:req_put_coin -> VM:get_coin;
C:req_push_choc -> VM:choc_button;
C:req_push_cancel -> VM:cancel_button;
VM:req_give_coin -> C:get_coin;
VM:req_give_choc -> C:get_choc;
end connector
6.4.
Conclusiones del capítulo
El nuevo esquema de comunicación propuesto constituye una mejora para
OASIS en términos de precisión y expresividad. Se han establecido cuatro
tipos de comunicación que permiten modelar directamente la mayoría de los
tipos de interacción más frecuentes entre objetos. Este esquema de comunicación ha sido adoptado en OASIS 3.0. Por otra parte, se presentaron las bases
para la incorporación de las ideas de Arquitecturas Software en el marco de
OASIS. Aunque este último enfoque resulta interesante se ha postergado su
incorporación en OASIS 3.0 para mantener la compatibilidad con OASIS 2.2.
4
Se trata de un conector de un objeto de la clase vm consigo mismo, representando la
comunicación self de los objetos de la clase vm.
86
CAPÍTULO 6. INTERACCIÓN ENTRE OBJETOS
Capítulo 7
Un ejemplo en OASIS 3.0
Se ha preferido poner en un capítulo separado el ejemplo que se utilizará
en los capítulos posteriores. Se trata de la especificación OASIS 3.0 para un
sistema bancario “de juguete”. Este ejemplo no incluye la expresividad abordada en todos los aspectos de OASIS abordados en este trabajo, sin embargo,
es representativo respecto de la animación automática implementada.
conceptual schema simple_banking_system
class account
identification
number:(number);
constant attributes
number:nat; name:string;
variable attributes
balance:int(0);
times:nat(0);
pin:nat(0);
rank:nat(0);
derived attributes
good_balance:bool;
derivations
good_balance:={balance>=100};
events
open new;
close destroy;
deposit(Amount:nat);
withdraw(Pin:nat,Amount:nat);
pay_commission;
change_pin(Pin:nat,NewPin:nat);
change_rank(Rank:nat);
valuations
[deposit(Amount)] balance:=balance+Amount, times:=times+1;
[withdraw(Pin,Amount)] balance:=balance-Amount, times:=times+1;
87
88
CAPÍTULO 7. UN EJEMPLO EN OASIS 3.0
[pay_commission] balance:=balance-1;
[::pay_commission] times:=0;
[change_pin(Pin,NewPin)] pin:=NewPin;
[change_rank(Rank)] rank:=Rank;
preconditions
withdraw(Pin,Amount) if {(pin=Pin and balance>=Amount)
or (pin=Pin and balance<Amount and rank=2)};
change_pin(Pin,NewPin) if {pin=Pin};
close if {balance=0};
triggers
::pay_commission when
{times>=5 and good_balance=false and rank=0};
end class
class customer
identification
name:(name);
constant attributes
name:string;
events
add new;
remove destroy;
end class
interface customer(someone) with account(someone)
services(deposit,withdraw,change_pin,change_rank);
end interface
interface account(someone) with self
services(pay_commission);
end interface
end conceptual schema
En este ejemplo hay dos clases: customer y account. Los objetos de ambas
clases son activos. Un objeto de la clase account está obligado a disparar a sí
mismo una acción con el evento pay_commission cada vez que la condición de
disparo se satisface. Aunque los objetos de la clase customer no tienen disparos
explícitamente definidos, ellos tienen una definición de interfaz con objetos
de la clase account permitiéndoles requerir acciones asociadas a los eventos
visibles según la interfaz. Por esto, los objetos de la clase customer también
son activos. Además, por defecto, existirá un objeto denominado root. Este
objeto será responsable de activar los eventos que no tienen un cliente explícito
en la especificación. En el ejemplo, el objeto root puede requerir acciones con
los eventos add y remove de la clase customer.
Capítulo 8
Un modelo de ejecución para
OASIS
En este capítulo se presenta un modelo de ejecución para la animación de
especificaciones OASIS 3.0. La estructura y el comportamiento de un objeto
están determinados por la clase de la cual es instancia y las relaciones que
ésta tenga con otras clases. En particular, tal como se estableció en el capítulo
anterior, el comportamiento de los objetos de una clase puede ser uniformemente expresado por un conjunto de fórmulas en la variante de lógica dinámica
usada por OASIS. Dichas fórmulas definen tres aspectos del comportamiento: obligaciones, permisos (prohibiciones) y cambios de estado. Así, el modelo
presentado permitirá animar las fórmulas que caracterizan el comportamiento
de un objeto, entendido como una entidad autónoma, independiente y en concurrencia con otros objetos. Se utilizará como punto de referencia el modelo
ACTORS [1].
8.1.
El modelo de ACTORS
ACTORS es un modelo de computación concurrente para sistemas distribuidos. ACTORS no es por naturaleza un modelo que usa el paradigma de
objetos, pero ofrece un marco útil para el diseño de un modelo de ejecución
asociado al enfoque orientado a objeto.
Los actores son agentes computacionales los cuales establecen correspondencias entre comunicación recibida respecto de una terna compuesta por:
Un conjunto finito de comunicaciones enviadas a otros agentes.
Un nuevo comportamiento que gobernará el procesamiento de la próxima
comunicación.
89
90
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
Un conjunto finito de nuevos actores creados.
Cada actor tiene un tiempo (reloj) local el cual permite ordenar linealmente las comunicaciones de acuerdo a cuándo éstas ocurren en el agente, o
alternativamente permite ordenar los estados del agente. Se asume en general
un entorno distribuido asincróno, desde el cual la necesidad de una interacción
sincróna puede ser derivada como un caso especial.
Cada actor posee un buzón que almacena las comunicaciones a ser procesadas. Cuando un actor Xn acepta la n-ésima comunicación almacenada en
el buzón, se crea un nuevo actor Xn+1 , resultante del reemplazo de comportamiento del actor anterior.
Todo el cómputo en un sistema de actores se produce en respuesta a comunicaciones. Las comunicaciones están contenidas en tareas. A medida que el
cómputo avanza, un actor evoluciona para incluir nuevas tareas y nuevos actores que son creados como resultado del procesamiento de tareas. Las tareas
ya procesadas y los actores que ya no serán útiles son eliminados del sistema.
La configuración de un sistemas de actores está definida por los actores que
contiene así como por las tareas no terminadas de procesar.
Una tarea consiste en: una etiqueta que la distingue de todas las otras
tareas del sistema, la dirección del buzón hacia el cual debe enviarse la comunicación y la comunicación en sí, incluyendo información para el actor receptor.
Hay tres formas en las cuales un actor, al aceptar una comunicación, puede
saber la dirección del buzón hacia el cual debe enviar una determinada comunicación: el actor lo sabía antes de recibir la comunicación, la dirección está
incluida en la información de la comunicación recibida o se trata del buzón de
un actor creado como resultado de la comunicación recibida.
La Figura 8.1 ilustra los aspectos básicos del modelo ACTORS. Partiendo
de la proximidad entre los conceptos de actor y de objeto (en OASIS) pueden
establecerse las siguientes correspondencias:
Concepto ACTORS
comunicación recibida
tarea
buzón
reemplazo del comportamiento
creación de actor
Concepto OASIS
acción asociada a proveer un servicio
acción asociada a requerir un servicio1
acciones de servicio en orden de llegada
cambio de estado
creación de un nuevo objeto
En el marco de OASIS es necesario además tener en cuenta las siguientes
consideraciones:
1
Se trata de una acción asociada a una obligación y en la cual el cliente es el propio
objeto.
8.1. EL MODELO DE ACTORS
1
91
n n+1
2
...
...
transición
(reemplazo)
Xn
tarea
producida
Xn+1
creación de un
nuevo actor
1
2
...
tarea
Y1
Figura 8.1: Representación de aspectos básicos de un actor
Tanto las acciones asociadas a proveer un servicio como las asociadas a
requerirlo deben ser tratadas uniformemente pues ambas pueden afectar
el estado del objeto. De esta forma la perspectiva servidor y la cliente
son tratadas de forma homogénea. Lo anterior determina que el buzón
incluya también las acciones asociadas a requerir un servicio.
En un mismo instante a un objeto le puede ocurrir más de una acción.
En OASIS un objeto cambia de estado por la ocurrencia de un paso
(conjunto consistente de acciones). Cada paso incluye al menos todas
las acciones asociadas a obligaciones y cuya condición se satisface en
el estado actual del objeto, además un paso podría incluir acciones de
servicio que no estén en conflicto entre ellas ni con las acciones por
obligación. Nótese que las obligaciones asociadas a requerir un servicio
ya han sido contempladas en el punto anterior. Sin embargo, aquellas
obligaciones que determinan una acción de proveer un servicio (cuando
el cliente de la acción es otro objeto) son acciones que puede que no
estén presentes en el buzón en el momento de generarse la obligación.
Esta situación es en sí el mecanismo de comunicación action waiting de
OASIS.
OASIS ofrece cuatro mecanismos de comunicación: action sending, action waiting, action calling y action sharing. El mecanismo action send-
92
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
ing, por tratarse de un mecanismo asíncrono, está directamente representado por el procesamiento de acciones de proveer servicio y de acciones
de requerir un servicio, de las cuales sólo son obligaciones las últimas. El
mecanismo action waiting, tal y como se indicó antes, implica una sincronización de espera pues el objeto está obligado a proveer un servicio
cuyo cliente es otro objeto. Los mecanismos primitivos de comunicación
son action sending y action waiting, de esta forma, los mecanismos action calling y action sharing pueden definirse usando los primeros.
La ocurrencia de acciones de servicio puede ser descartada en caso que
no se satisfagan los permisos definidos.
La creación de un objeto es una actividad reservada sólo a objetos especiales, aquellos que representan a una clase2 .
8.2.
Un modelo abstracto para animación en OASIS
El modelo abstracto de ejecución establece el vínculo entre la semántica
de una especificación OASIS y una implementación concreta en un entorno de
programación. El modelo debe ser descrito con suficiente precisión para evitar
ambigüedades en su implementación.
Establecer un modelo abstracto de ejecución implica separar las consideraciones que definen al modelo de otras propias de la implementación del
mismo en el entorno de programación utilizado. Sin embargo, respecto del enfoque de implementación esperado, el modelo abstracto de ejecución tendrá
una orientación a priori, la cual se establece a continuación.
En la Figura 8.2 se clasifican diferentes enfoques de implementación para
ejecución de especificaciones OASIS, desde la perspectiva del programa construido y dependiendo de si el entorno de programación es secuencial o concurrente. El eje horizontal mide el grado de secuencialidad/concurrencia ofrecida
por el entorno y utilizada en la implementación. El eje vertical mide el grado
de correspondencia entre los objetos de la especificación OASIS y su representación en el código del programa3 .
En un entorno de programación secuencial debe siempre implementarse un
monitor que simule la autonomía y concurrencia mediante la administración
de la actividad del sistema. El mínimo trabajo que podría implementarse para
2
Como veremos más adelante, las clases en tiempo de ejecución son objetos que sirven
acciones de creación de objetos (de dicha clase) y mantienen la asociación entre mecanismos
de identificación de cada objeto y el respectivo oid.
3
Debido a las diferencias de conceptos entre los diversos lenguajes orientados a objeto y
a su vez respecto de OASIS, no es imprescindible que el entorno de programación utilizado
sea orientado a objeto.
8.2. UN MODELO ABSTRACTO PARA ANIMACIÓN EN OASIS
+ OO
93
...
Monitor
...
Monitor
Monitor
...
...
- OO
BD
Secuencial
BD
Concurrente
Figura 8.2: Entornos de programación para ejecución de especificaciones OASIS
el monitor podría ser limitarlo a distribuir el hilo de ejecución entre los distintos objetos del sistema, manteniendo los aspectos de estructura y el resto
de aspectos de comportamiento encapsulados en las implementaciones de los
objetos. Esta situación se ilustra en el vértice superior izquierdo del gráfico
de la Figura 8.2. En otro extremo, el monitor podría simular todo el comportamiento de los objetos, caso en el cual la implementación no guarda una
correspondencia uno a uno respecto de los objetos. Esta situación se ilustra
en los vértices inferiores del gráfico de la Figura 8.2.
En el vértice inferior derecho de la Figura 8.2 la concurrencia ofrecida por el
entorno de programación sólo es utilizada para implementar distintos aspectos
del monitor, no relacionados directamente con objetos del sistema.
Siendo el propósito fundamental en este trabajo la validación de requisitos
expresados mediante una especificación OASIS, es indispensable mantener la
implementación lo más cercana posible a la semántica de OASIS. De esta
forma existirá un camino de formalización y verificación de la implementación
obtenida respecto de la semántica de la especificación OASIS. Esto sugiere que
la mejor alternativa es utilizar un entorno de programación concurrente y dotar
de un hilo de ejecución a cada objeto, es decir, trabajar en el vértice superior
derecho del gráfico de la Figura 8.2. Así, el modelo abstracto de ejecución que se
plantea a continuación está orientado a entornos de programación concurrente.
94
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
8.2.1.
Alcance del modelo
Desde el punto de vista de la semántica de OASIS, el modelo de ejecución
no es más que un modelo para animar fórmulas de obligación, permiso y evaluación, asociadas a un objeto. En esta perspectiva, la información utilizada por
el modelo es la signatura de atributos y acciones del objeto junto al conjunto
de fórmulas en Lógica Dinámica que describen su comportamiento, incluyendo las especificaciones de proceso interpretadas también como fórmulas en la
Lógica Dinámica utilizada. Cuando se trata con objetos de clases simples, esta
información es precisamente la plantilla de la clase del objeto. Sin embargo,
si la clase del objeto es compleja (por especialización o agregación) no toda
la información está directamente en la plantilla de la clase del objeto. A pesar de esto, podemos suponer externo al modelo de ejecución el trabajo que
determina la estructura y el comportamiento del objeto en el caso de objetos
pertenecientes a clase complejas y así reducir el planteamiento del modelo de
ejecución al caso de un objeto instancia de una clase simple.
No serán incluidos dos aspectos del comportamiento del objeto: las restricciones de integridad y las operaciones etiquetadas como transacción.
Sólo se abordarán los mecanismos básicos de comunicación: action sending
y action waiting. Sin embargo, la extensión del modelo para incluir action
calling y action sharing debe utilizar dichos mecanismos básicos. La creación
y tratamiento de objetos complejos hace uso exhaustivo de los mecanismos
action calling y action sharing, por consiguiente también los objetos complejos
quedarán fuera del alcance de este trabajo.
Por lo anterior, el modelo de ejecución excluye algunos casos de especificación y su correspondiente animación pero reduce el alcance del trabajo a
proporciones y complejidad adecuadas.
8.2.2.
Aspectos básicos
La secuencia de pasos que le acontecen a un objeto está ordenada respecto
del tiempo. Podemos suponer que existe un objeto “reloj” que envía acciones
especiales —llamadas ticks- hacia cada objeto del sistema4 . Los ticks recibidos
por un objeto son correlativos con los números naturales, t1 , t2 , etc. Sean i y
j números naturales tal que i < j ⇐⇒ ti < tj .
Definición 17 Buzón. Es el conjunto de acciones que pueden formar parte
del paso que un objeto ejecuta en un determinado tick. El buzón en el instante
ti se denota por Mboxi . Consideraremos el buzón como un buffer ilimitado,
en el cual las acciones se ordenan por orden de llegada.
4
Para propósitos de animación en este punto no tiene mayor importancia el que el reloj
sea sólo uno para todo el sistema, sea uno para cada objeto u otra alternativa.
8.2. UN MODELO ABSTRACTO PARA ANIMACIÓN EN OASIS
Mboxi+1
Mboxi
Statei-1
95
Statei
ti
Statei+1
ti+1
Figura 8.3: Ciclo de vida de un objeto
Definición 18 Estado i-ésimo del objeto. Denotado por Statei , representa el estado del objeto en el intervalo (ti , ti+1 ] . Es decir, inmediatamente
después de ti y hasta ti+1 inclusive, el estado se mantiene constante.
La Figura 8.3 muestra un Diagrama de Vida de Objeto simplificado, el cual
permite ilustrar el ciclo de vida de un objeto según las definiciones dadas. El
conjunto de acciones en cada paso es obtenido desde el buzón de acciones del
objeto y la ejecución del paso en un instante produce un cambio de estado, el
cual no será observable hasta el siguiente tick. Así, en la estructura de tiempo
utilizada aunque la ocurrencia de acciones es instantánea, los estados tienen
una cierta duración.
8.2.3.
Concurrencia intra-objeto
Una cuestión que se plantea es ¿Se limita o no el número de acciones a ser
ejecutadas en un determinado instante?, o en otras palabras: ¿Se permitirá
concurrencia intra-objeto en el modelo de ejecución?. La concurrencia intraobjeto es imprescindible para una animación fiel a la semántica de OASIS.
Básicamente dos situaciones justifican la incorporación de concurrencia intraobjeto en el modelo de ejecución:
Cuando en un instante hay que ejecutar más de una acción (de acuerdo
a las obligaciones establecidas), deben todas ellas realizarse en el mismo instante de lo contrario se contradice la semántica de la fórmula de
obligación correspondiente.
En el caso de objetos agregados, la ejecución concurrente de los objetos componentes en forma natural puede producir acciones concurrentes
vistas desde el objeto agregado.
96
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
La definición de consistencia para un conjunto de acciones es de carácter
general. Para obtener una implementación directa y sencilla que asegure la
consistencia de las acciones en un paso a continuación se define el concepto de
conflicto entre acciones.
8.2.4.
Conflicto entre acciones
Si se ejecuta más de una acción en un paso, tal como se plantea en [32],
debería garantizarse la consistencia y la terminación, o al menos indicar al analista/diseñador que dichas propiedades no se pueden determinar con certeza en
la especificación.
El total de las acciones ejecutadas en un paso debería ser consistente5 , es
decir, no debe existir conflicto respecto de las modificaciones que realizan las
acciones sobre los atributos del objeto.
Definición 19 Relación afecta. Sea Att el conjunto de atributos del objeto.
Se define la relación afecta como:
AfectaStatei ⊆ M boxi × Att
Sea a1 ∈ Mboxi y att1 ∈ Att, diremos que a1 AfectaStatei att1 si y sólo si la
ejecución de la acción a1 modifica6 el valor del atributo att1 en ti .
Definición 20 Conflicto entre acciones. Sea Acc ⊆ Mboxi y Att el conjunto de atributos del objeto. Diremos que Acc tiene conflicto entre acciones
si NO se satisface la siguiente condición:
∀a1 , a2 ∈ Acc y ∀att ∈ Att : [a1 Af ectaStatei att ∧ a2 AfectaStatei att] =⇒
a1 = a2
Definición 21 Conjunto consistente de acciones (versión modelo de
ejecución). Sea Acc ⊆ Mboxi , diremos que Acc es consistente si no presenta
conflicto entre sus acciones.
Así, para garantizar la consistencia de un de un conjunto de acciones en
el buzón bastará con asegurar que dichas acciones no están en conflicto. Esto puede detectarse automáticamente, basta con inspeccionar los conjuntos
de atributos que pueden sufrir una asignación de valor para cada acción, revisando las evaluaciones asociadas a dicha acción. Los conjuntos de atributos
5
O sea, tener un comportamiento funcional: su resultado es siempre el mismo para un
conjunto de acciones dadas, independiente del orden en el que se ejecuten.
6
La modificación puede ser indirecta en el caso de atributos derivados. Así, si att2
es un atributo derivado definido en función de att1 , entonces: a1 Af ectaStatei att1 =⇒
a1 Af ectaStatei att2 .
8.2. UN MODELO ABSTRACTO PARA ANIMACIÓN EN OASIS
97
obtenidos deben ser disjuntos para que el conjunto de acciones correspondiente
sea consistente.
Nótese que cuando existe conflicto entre acciones puede aún existir consistencia (según su definición original). Por ejemplo, consideremos las siguientes
evaluaciones:
att = V [a1 ]att = V + 1
att = V [a2 ]att = V + 2
En este caso, a1 y a2 están en conflicto pero al aplicar a1 y luego a2 el
efecto es el mismo que al hacerlo en el otro orden, con lo cual a1 y a2 constituyen un conjunto consistente (según la definición de consistencia original).
Sin embargo, la exclusión de casos como este no contradice la semántica de
OASIS y facilita la determinación de los conjuntos de acciones que pueden
ejecutarse en un paso.
En [32] se plantean los problemas de terminación que pueden surgir al
aplicar una a una las acciones de un paso, cambiando de estado en cada aplicación, lo cual podía a su vez generar nuevas acciones producto de obligaciones
por cambio de estado. En nuestro caso, una vez seleccionado el conjunto consistente de acciones que forma el paso, se aplican todas las acciones a la vez,
produciendo un sólo cambio de estado correspondiente al efecto de todas las
acciones (sin inconvenientes gracias a que no existe conflicto entre ellas). Debido a este enfoque, la propiedad de terminación en el procesamiento de las
acciones en un paso está siempre asegurada.
8.2.5.
Clasificación de acciones en el buzón
El procesamiento de las acciones del buzón implica clasificar las acciones
contenidas en él. A continuación se presentan las categorías de acciones identificables en el buzón, caracterizadas como subconjuntos de Mboxi (es decir,
en el instante ti ).
Definición 22 Acciones de requerir. Es un subconjunto de M boxi constituido por acciones asociadas a obligaciones por requerir un servicio (en las
cuales el cliente es el propio objeto) y que deben acontecer. El conjunto de
acciones de requerir en el instante ti se denota por OReqi .
Las acciones de requerir están determinadas por fórmulas de obligación, es
decir, de la forma: φ[¬a]false, en las cuales a =< self, Server, Service >, es
decir, el cliente de la acción es el propio objeto, indicado usando la palabra
self.
Definición 23 Acciones obligadas de proveer. Es un subconjunto de Mboxi
constituido por acciones correspondientes a servicios que el objeto debe proveer.
98
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
Estas acciones están asociadas a obligaciones, en las cuales el cliente no es el
propio objeto. El conjunto de acciones obligadas de proveer en el instante ti
se denota por OP rovi .
Las acciones obligadas de proveer están determinadas por fórmulas de obligación, es decir, de la forma: φ[¬a]false, en las cuales una acción tiene la estructura siguiente: < Client, self, Service >, es decir, el servidor de la acción
es el propio objeto, indicado usando la palabra self.
Definición 24 Acciones obligadas. Es un subconjunto de Mboxi denotado
por OExeci , tal que: OExeci = OReqi ∪ OP rovi .
Supondremos que garantizar la no-existencia de conflicto entre acciones
obligadas es parte de la verificación estática de la especificación. Es decir, en
tiempo de ejecución no puede presentarse conflicto entre obligaciones7 . Del
mismo modo, no debe darse una situación en la cual una acción obligada no
está permitida.
Definición 25 Acciones no-obligadas. Es un subconjunto de Mboxi constituido por acciones correspondientes a servicios solicitados por otros objetos
(o por el propio objeto) y que el objeto puede proveer, dependiendo de los permisos establecidos sobre dichas acciones, verificados sobre Statei . El conjunto
de acciones no-obligadas en el instante ti se denota por OExeci .
Definición 26 Acciones rechazadas. Es un subconjunto de OExeci constituido por acciones no-obligadas cuya ocurrencia NO está permitida en el
instante ti . El conjunto de acciones rechazadas se denota por Rejecti .
Las acciones rechazadas están determinadas por fórmulas de prohibición,
es decir, de la forma: ¬φ[a]false.
La opción básica para el tratamiento de las acciones rechazadas es simplemente ignorarlas. Un tratamiento más elaborado podría ser, por ejemplo:
Generar automáticamente una “acción de rechazo”, es decir, una acción
de requerir dirigida hacia el cliente indicando el rechazo de su solicitud
de servicio. Esto implica, desde el punto de vista del cliente, tener que
considerar acciones implícitas de ”aviso de rechazo” por cada posible
acción de solicitud de servicio.
Mantener las acciones rechazadas como acciones no-obligadas que podrían ser ejecutadas en el próximo tick. Aunque esta alternativa no contradice la semántica del lenguaje introduce una relatividad no deseada
Si se tienen las fórmulas φ1 [¬a1 ]f alse y φ2 [¬a2 ]f alse siendo a1 y a2 dos acciones en
conflicto, entonces no debe existir un mundo w tal que |=w φ1 ∧ φ2 .
7
8.2. UN MODELO ABSTRACTO PARA ANIMACIÓN EN OASIS
99
respecto del comportamiento del objeto durante su ejecución. Además
el crecimiento y manipulación de la acumulación de acciones rechazadas
presenta inconvenientes obvios.
Se optará por generar automáticamente acciones de rechazo. Estás serán
registradas como acciones obligadas de requerir en el buzón del instante en
el cual se produce su rechazo. Se trata de acciones cuyo cliente es el objeto
que rechaza la ocurrencia de una acción y el servidor es el cliente de la acción
rechazada, es decir, constituyen un aviso para un cliente cuando la acción es
rechazada en el servidor.
Definición 27 Acciones candidatas. Es un subconjunto de OExeci constituido por acciones no-obligadas cuya ocurrencia está permitida en el instante
ti . El conjunto de acciones candidatas se denota por Candi .
Además, se cumple que OExeci = Rejecti ∪ Candi .
Definición 28 Acciones ejecutadas. Es el conjunto de acciones correspondiente al paso a ser ejecutado en un determinado instante. El paso en el
instante ti será denotado por Execi . El paso estará constituido por OExeci
(acciones obligadas) más un subconjunto de Candi , es decir, acciones noobligadas que están permitidas.
La selección del subconjunto de acciones de Candi que serán incluidas en
Execi puede responder a distintos criterios y la única restricción es que no se
produzcan conflictos entre las acciones del paso.
Definición 29 Acciones en conflicto. Es un subconjunto de Candi constituido por acciones no-obligadas cuya ocurrencia está permitida en el instante
ti , pero que están en conflicto con alguna de las acciones obligadas o con alguna de las acciones no-obligadas seleccionadas. El conjunto de acciones en
conflicto se denota por Confi .
Utilizaremos un criterio sencillo para la selección de acciones desde Candi :
ante dos acciones que no pueden ser seleccionadas por estar en conflicto se
seleccionará aquella llegada antes al buzón. Este criterio evita postergación
indefinida de acciones en conflicto. Las acciones en conflicto Confi serán copiadas al buzón correspondiente al siguiente instante (Mboxi+1 ).
8.2.6.
Comunicación self
La comunicación del objeto consigo mismo se produce cuando una acción
obligada de requerir es dirigida hacia el mismo objeto (el servidor es self).
100
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
Esta comunicación es tratada de forma uniforme respecto del resto de comunicaciones, es decir, la acción obligada de requerir será posteriormente recibida
en el buzón como una acción no-obligada (una solicitud de servicio). Según
esto, en dicha situación se distinguen dos acciones: la acción de requerir el servicio a sí mismo (obligación) y la acción no-obligada de proveer dicho servicio.
En general la segunda acción podría sufrir algún retraso y ser procesada en
un intervalo de tiempo posterior. La primera por tratarse de una obligación
no puede ser rechazada, la segunda sí.
8.2.7.
Modelando el comportamiento interno del objeto
El comportamiento de un objeto estará regido por un bucle de actividad
interna. Esta actividad realiza la transición del objeto desde un estado inicial
Statei a un estado final Statei+1 .
Utilizaremos una acción implícita para representar los ticks e incluirlos
homogéneamente dentro del buzón. Un tick corresponde a la acción representada por la tupla: < reloj, Object, tick(t, i) >. Object una referencia de objeto
servidor que coincide con el propio objeto, es decir, se trata como una acción
de servicio solicitada por “reloj”. t es el tiempo real correspondiente al i-ésimo
tick. La separación real de tiempo entre tick y tick podría no ser constante.
La Figura 8.4 ilustra los principales aspectos considerados en el modelo de
ejecución. Un objeto transita desde el estado Statei hacia el estado Statei+1
por la ocurrencia del paso representado por Execi correspondiente a un subconjunto de acciones de Mboxi . La comunicación desde otros objetos (o desde
el propio objeto) se representa por las flechas etiquetadas como OExeci y
OExeci+1 . La comunicación hacia otros objetos se representa en la parte inferior de la Figura 8.4 por las flechas saliendo hacia buzones de otros objetos.
Las flecha etiquetada con Confi representa las acciones en conflicto en ti , las
cuales son copiadas al siguiente buzón. La flecha etiquetada con OExeci+1
representa las obligaciones de requerir que el objeto adquirirá en el instante
ti+1 producto de la ocurrencia de las acciones Execi .
Las clases en ejecución serán implementadas homogéneamente como objetos. Estos metaobjetos proveen el servicio de creación de objetos de la clase
correspondiente. Por lo tanto, como ilustra la Figura 8.4 en su parte inferior
derecha, si un metaobjeto ejecuta una acción de creación de instancias (acción
new) dentro de su proceso de cambio de estado se incorporará la creación de
un nuevo objeto, cuya primera acción ocurrida es la acción new.
Cada M box se considera completo sólo cuando ha llegado la acción tick. Si
el objeto termina el cambio de estado y aún no se recibe la acción tick, esperará
hasta que esta llegue. Por el contrario, si objeto termina el cambio de estado
8.2. UN MODELO ABSTRACTO PARA ANIMACIÓN EN OASIS
OExeci
OExeci
OExeci+1 OExeci+1
Confi
Confi-1
Confi+1
Mboxi+1
Mboxi
...
a1
a2
101
...
tick a3 a4
ti
...
...
tick
ti+1
Execi+1
Execi
cambio de
estado
Statei
Statei+1
Envío de acciones en OReqi a
los servidores correspondientes
Creación de un objeto
(realizada sólo por objetos "clase")
Mbox'j
...
Mbox'''0
...
tick
...
new
...
Mbox''k
...
...
tick
...
State'''0
State'j
State''k
Figura 8.4: Vida de un objeto en OASIS
y ha llegado más de una acción tick, sólo se considerará el último, los otros
son ignorados. Nótese que la frecuencia de tick determina el tamaño del Mbox
que se procesará, por lo tanto si se aumenta la frecuencia de ticks ( sin variar
la frecuencia de acciones que llegan al Mbox) se puede llegar al extremo en el
cual el buzón contiene sólo una acción además de la acción tick o incluso sólo
la acción tick. Por otra parte, reduciendo la frecuencia de ticks el buzón tiene
la posibilidad de contener mayor cantidad de acciones lo cual podría producir
más acciones en conflicto. Cualquiera que sea el caso, la frecuencia de ticks y el
ordenamiento de acciones del buzón representan el indeterminismo propio de
los sistemas concurrentes. Sin embargo, la fidelidad respecto de la semántica
de OASIS siempre se mantiene.
La semántica de la comunicación action waiting exige un tratamiento especial. Aunque ya esté presente un tick para completar el Mbox el objeto no
102
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
puede alcanzar el nuevo estado si no están presentes las acciones obligadas
de proveer (que precisamente corresponden a comunicación action waiting).
Esto ocasionará una posible espera, en la cual podrán llegar nuevos ticks que
serán ignorados. Sólo cuando todas las acciones obligadas de proveer están contenidas en el buzón y ha llegado un tick (en un instante posterior) el objeto
procesará el buzón y alcanzará el estado siguiente.
Finalmente, el siguiente algoritmo expresa la actividad interna de cada
objeto durante su existencia:
i=0
OP rovi = {}
State0 ← {}
REPETIR
ESPERAR HASTA QUE (tick ∈ M boxi ∧ OP rovi ⊆ M boxi )
OReqi ← obtener_acciones_de_requerir(M boxi )
enviar_acciones_de_requerir(OReqi )
OExeci ← obtener_acciones_no_obligadas(Mboxi )
Rejecti ← calcular_acciones_rechazadas(OExeci , Statei )
Candi ← OExeci − Rejecti
Confi ← calcular_acciones_en_conflicto(Candi , Statei )
Execi ← OReqi ∪ OP rovi ∪ (Candi − Confi )
Statei+1 ← determinar_nuevo_estado(Execi , Statei )
OP rovi+1 ← calcular_próx_accs_obligadas_de_proveer(Statei+1 )
OReqi+1 ← calcular_próx_accs_obligadas_de_requerir(Statei+1 )
M boxi+1 ← Mboxi+1 ∪ OReqi+1 ∪ Confi
i =i+1
FIN_REPETIR
Observaciones
Las funciones “obtener_...” seleccionan subconjuntos de Mbox de acuerdo con las definiciones dadas.
El procedimiento enviar_acciones_de_requerir se encarga de hacer
llegar las acciones de requerir a los buzones de los respectivos servidores.
Las funciones “calcular_...” utilizan además las fórmulas que definen el
comportamiento del objeto (fórmulas de obligaciones, permisos y cambios de estado).
La función determinar_nuevo_estado obtiene el estado siguiente utilizando además las fórmulas de cambio de estado.
Mediante las definiciones y comentarios respecto de cada uno de los
conjuntos involucrados todas las funciones pueden ser implementadas
sin ambigüedad en el entorno de programación concurrente elegido.
8.2. UN MODELO ABSTRACTO PARA ANIMACIÓN EN OASIS
asignar_categoria(0)
reintegro(20)
reintegro(10)
ingreso(40)
reintegro(30)
Mbox1
Mbox2
asignar_categoria(0)
x reintegro(20)
reintegro(10)
t1
saldo=10
veces=1
categoria=1
buen_saldo=false
asignar_categoria(2)
::pagar_comision
saldo=0
veces=2
categoria=0
buen_saldo=false
Mbox3
ingreso(40)
x reintegro(30)
t2
cerrar
ingreso(90)
pagar_comision
saldo=40
veces=3
categoria=0
buen_saldo=false
t3
reintegro(70)
Mbox4
asignar_categoria(2)
:: pagar_comision
Mbox5
x cerrar
ingreso(90)
pagar_comision
saldo=40
veces=0
categoria=2
buen_saldo=false
103
reintegro(70)
ingreso(90)
t4 saldo=39
veces=0
categoria=2
buen_saldo=false
t5 saldo=129
veces=1
categoria=2
buen_saldo=true
self:pagar_comision
Figura 8.5: Ciclo de vida de una instancia de cuenta entre t1 y t5
8.2.8.
El modelo de ejecución en funcionamiento
Usando el ejemplo de la cuenta bancaria, realizaremos una animación basada en el modelo de ejecución propuesto. La siguiente tabla muestra una posible
secuencia de eventos recibida por un objeto de la clase cuenta.
Intervalo (ti−1 − ti ]
(... − t1 ]
(t1 − t2 ]
(t2 − t3 ]
(t3 − t4 ]
(t4 − t5 ]
Acciones contenidas en Mboxi
asignar_categoria(0)
reintegro(20)
reintegro(10)
ingreso(40)
reintegro(30)
asignar_categoria(2)
::pagar_comision
pagar_comision
ingreso(90)
cerrar
reintegro(70)
La Figura 8.5 muestra un Diagrama de Vida del Objeto en el cual se
detalla parte del ciclo de vida de un objeto (entre los instantes t1 y t5 ). Para
esta instancia de la clase cuenta, consideraremos que su estado actual (justo
antes de t1 ) es:
State0 = {< num, 1010 >, < nombre, juan >, < saldo, 10 >,
< veces, 1 >, < categoria, 1 >, < buen_saldo, false >}
104
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
El eje horizontal representa el tiempo de izquierda a derecha. Bajo el eje del
tiempo se indican los valores de atributos variables del objeto. Entre (ti − ti+1 ]
el estado del objeto no cambia. Sobre el eje del tiempo y bajo los rectángulos
se indica los cambios que sufrirán los atributos variables y que se reflejarán en
el siguiente ti . Los rectángulos representan el buzón (Mboxi ) y su contenido
en cada tick.
El símbolo “X”delante de una acción en el Mboxi indica que está permitida
en dicho instante, el símbolo “x” delante de una acción indica lo contrario. Las
acciones en conflicto han sido subrayadas.
Las acciones no-obligadas recibidas entre (ti − ti+1 ] están representadas
en las flechas descendientes entre Mboxi y Mboxi+1 . La flecha ancha inferior
representa acciones obligadas de requerir.
Comentarios respecto del ejemplo
Después de t2 , y sabiendo que en t3 será satisfecha la obligación que
produce una acción por requerir el servicio pagar_comision, es generada
automáticamente la correspondiente acción de requerir en Mbox3 .
En t3 se tiene en el buzón una acción de requerir asociada a la obligación
de solicitar a sí mismo el servicio pagar_comision. Posteriormente, se
recibe como la correspondiente acción de solicitud de servicio y es ejecutada en t4 .
En t4 y t5 el buzón contiene acciones que están en conflicto pues el
atributo saldo puede ser modificado por más de una acción. En t4 la
acción cuyo servicio es ingreso(90) está en conflicto con la acción cuyo
servicio es . Así, la acción cuyo servicio es ingreso(90) es postergada
hasta el siguiente tick, siendo copiada a Mbox5 . En t5 la acción cuyo
servicio es ingreso(90) forma un conjunto inconsistente con la acción
cuyo servicio es reintegro(20). En este caso, esta última acción se ha
considerado en conflicto, y se ha copiado en el siguiente buzón.
8.3.
Conclusiones del capítulo
Se ha presentado el modelo de ejecución que permite animar especificaciones OASIS 3.0. En OASIS el comportamiento de un objeto es formalizado
en una variante de Lógica Dinámica y se expresa como un conjunto de fórmulas que representan obligaciones, permisos y cambios de estado. Así, el modelo
de ejecución planteado es un animador para este tipos de fórmulas.
Este modelo es una base sólida para trabajos de animación de especificaciones OASIS fieles a la semántica del modelo OASIS. El modelo puede
8.3. CONCLUSIONES DEL CAPÍTULO
105
ser extendido para incluir aspectos más complejos del comportamiento, tales
como: restricciones de integridad, operaciones etiquetadas como transacción,
comunicación usando action calling y action sharing, y por último objetos
complejos.
106
CAPÍTULO 8. UN MODELO DE EJECUCIÓN PARA OASIS
Capítulo 9
Programación Lógica
Concurrente
En este capítulo se hace una introducción al paradigma de Programación
Lógica Concurrente (PLC). Se describen las principales características de este
paradigma y se compara con la Programación Lógica clásica. Posteriormente se
analizan las capacidades de la Programación Lógica Concurrente para el modelado de comunicación entre procesos, desarrollando varios ejemplos en PARLOG. Finalmente se presentan los elementos básicos para la representación de
clases y objetos en Programación Lógica Concurrente.
La Programación Lógica Concurrente surge como un intento de mejorar
la eficiencia de los lenguajes lógicos mediante el uso del paralelismo AND
de flujo. Además, son lenguajes de alto nivel muy convenientes para sistemas
paralelos y distribuidos. El nombre de concurrentes para este tipo de lenguajes
lógicos, los distingue de otros intentos por construir un PROLOG paralelo. La
diferencia radica en la distinción que se establece entre dos tipos de sistemas
o programas: transformacionales y reactivos (interactivos) [85]. Un sistema
transformacional recibe un entrada al comienzo de su ejecución y devuelve un
resultado al final, el propósito de los sistemas reactivos no es, necesariamente,
obtener un resultado final, sino mantener un interacción con el entorno. De
hecho, los sistemas reactivos más usuales (sistemas operativos, sistemas de
administración de bases de datos) nunca terminan.
PROLOG fue diseñado desde un punto de vista transformacional y, aunque
contiene algunas características de entrada/salida básicas, usualmente no están integradas en su modelo de cómputo. Por el contrario, los lenguajes lógicos
concurrentes responden mejor al modelo reactivo, aunque esto no descarta su
conveniencia en aplicaciones que son transformacionales por naturaleza. Es
decir, aunque un sistema concurrente (lógico o no) sea de forma global transformacional o reactivo, sus componentes pueden verse como reactivas, ya que
107
108
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
tienen una interacción continua entre sí y posiblemente también con el entorno.
De este modo, todos los sistemas concurrentes, independientemente de la razón
por la que explotan la concurrencia, tienen un aspecto en común: el lenguaje
en el que se implementan necesitan especificar procesos reactivos, su creación,
interconexión, comportamiento interno, comunicación y sincronización.
Del mismo modo que los programas lógicos admiten una interpretación
basada en procedimientos, también admiten una lectura basada en procesos:
cada objetivo atómico p(t1 , t2 , ..., tn ) puede verse como un proceso, cuyo estado
del programa es el predicado p con aridad n (p/n), y su estados de datos es
la secuencias de términos t1 , t2 , ..., tn . El objetivo complejo (conjunción de
objetivos atómicos) se ve como una red de procesos, cuya interconexión es
especificada por variables lógicas compartidas entre los objetivos atómicos.
Los procesos se comunican instanciando las variables lógicas compartidas, y
sincronizan esperando que una variable lógica sea instanciada.
El comportamiento de un proceso como se ha descrito se ajusta a las
Cláusulas de Horn con Guardas como se muestra a continuación:
H ← G1 , ..., Gn : B1 , ..., Bm
n, m > 0
La cabeza H y la guarda G1 , ..., Gn (por sus comprobaciones) especifican
las condiciones bajo las cuales puede utilizarse la cláusula para reducir un
determinado objetivo. El cuerpo B1 , ..., Bm determina el estado del proceso
después de haberse realizado la reducción. De este modo, dependiendo del
cuerpo de la cláusula utilizada para reducir un objetivo atómico, el estado
del correspondiente proceso puede cambiar su naturaleza. Si el cuerpo de la
cláusula es vacío, el proceso en cuestión termina; si es unitario, formado por
un solo átomo, el proceso cambia de estado; y si el cuerpo está compuesto por
una conjunción de objetivos, el proceso inicial se transforma en una serie de
procesos concurrentes.
Un objetivo tiene la forma:
← M1 , ..., Mk
k>0
Los Mi son evaluados en paralelo (paralelismo AND), utilizando las cláusulas del programa para su reducción.
Para cada Mi se examinan en forma paralela las cláusulas que lo pueden
reducir (paralelismo OR), seleccionándose a lo más una y sin bactracking.
El criterio de selección es que el Mi unifique con la cabeza de la cláusula
y se satisfagan la conjunción de guardas G1 , ..., Gn (evaluadas también en
paralelismo AND), si existen. Si más de una cláusula es candidata, entonces
se hace una elección no determinista entre ellas.
En cada paso de reducción un objetivo Mi puede:
9.1. PROGRAMACIÓN LÓGICA Y PLC
109
Reducirse al conjunto de subobjetivos del cuerpo de la cláusula seleccionada y continuar la evaluación paralela de los subobjetivos.
Reducirse utilizando una cláusula sin cuerpo (hecho) y finalizar con éxito.
No unificar con la cabeza de alguna cláusula y finalizar con fracaso.
Suspender, si no tiene suficientemente instanciado alguno de sus argumentos definidos con restricción de entrada.
Cada argumento de un predicado tiene una definición de modo. Una declaración
de modo input para un argumento de predicado, puede obligar a que ese argumento este instanciado en el momento de intentar la reducción, esto se denomina restricción de entrada para el argumento. Si en un subobjetivo todos los
argumentos con restricción de entrada no están instanciados, el subobjetivo
suspende, con posibilidad de deadlock si todos los subobjetivos suspenden. Es
decir, la unificación entre un objetivo y la cabeza de una cláusula no es bidireccional como sucede en Programación Lógica, el programador debe especificar
el uso que hará del predicado (en PARLOG esto se hace explícitamente, en
KL1 el sistema lo determina).
9.1.
Programación Lógica y PLC
La semántica declarativa de un programa lógico concurrente (PARLOG o
KL1) no es diferente a la de un programa lógico (PROLOG) dado que esta
semántica es universal para todos los programas lógicos y no depende de la
elección de un lenguaje de programación lógica en particular. Respecto de la
semántica operacional, las diferencias más importantes son:
Estrategia en la selección de objetivo: La estrategia para selección de un
objetivo en PROLOG es evaluar los subobjetivos de una conjunción secuencialmente desde izquierda a derecha. Solamente un proceso de evaluación de un subobjetivo está activo a la vez. Se utiliza el mecanismo
de backtracking para reintentar con subobjetivos que han fallado. Una
conjunción en PARLOG o KL1 puede también ser evaluada secuencialmente de izquierda a derecha, pero lo más común es que los subobjetivos
sean evaluados concurrentemente (paralelismo AND). Así, cada subobjetivo es un proceso. Muchos procesos pueden estar activos a la vez, por
tanto es necesaria una sincronización, ésta es especificada por medio de
la declaración de modo. No hay backtracking, cuando un subobjetivo en
una conjunción fracasa, la conjunción completa fracasa.
110
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
Estrategia de elección de cláusulas: En la búsqueda de una cláusula para
resolver un subobjetivo, PROLOG explora las cláusulas en forma secuencial, buscando según orden textual en el programa. En PARLOG o
KL1 las cláusulas son examinadas concurrentemente (paralelismo OR).
Completo: PARLOG y KL1 son incompletos como lenguajes de programación lógica porque pueden existir soluciones de acuerdo a la semántica
declarativa que no son producidas como resultado de la evaluación. Una
causa del por qué no son completos es la declaración de modo en los
argumentos de un predicado. Por otra parte, PROLOG también es incompleto porque el lenguaje tiene una estrategia de búsqueda secuencial
y en profundidad, pudiéndose presentar una evaluación que entre en un
bucle infinito, sin obtenerse una respuesta.
El rol de la unificación: Cuando PROLOG busca una cláusula para resolver un subobjetivo se intenta unificación completa entre todos los
pares de argumentos correspondientes entre el subobjetivo y la cabeza
de la cláusula. En PARLOG o KL1 cada predicado tiene asociado un
modo que distingue entre argumentos de entrada y de salida, los cuales
son tratados de manera diferente.
A continuación se muestran implementaciones del predicado append ilustrando las diferencias indicadas antes.
PROLOG
append([],L,L).
append([H|L1],L2,[H|L3]) :append(L1,L2,L3).
PARLOG
mode append(?,?,^).
append([],L,L).
append([H|L1],L2,[H|L3]) <append(L1,L2,L3).
9.2. COMUNICACIÓN ENTRE PROCESOS
111
Aplicando los siguiente objetivos, en cada caso se obtiene:
Objetivo
append([1,2],[3,4,5],[1,2,3,4,5])
append([1,2],[3,4,5],X)
append([1,2],L,[1,2,3,4,5])
append(L,[3,4,5],[1,2,3,4,5])
append(L1,L2,[1,2,3,4,5]).
PROLOG
yes
X=[1,2,3,4,5] ;
L=[3,4,5] ;
L=[1,2] ;
L1 = []
L2 = [1,2,3,4,5] ;
L1 = [1]
L2 = [2,3,4,5] ;
L1 = [1,2]
L2 = [3,4,5] ;
L1 = [1,2,3]
L2 = [4,5] ;
L1 = [1,2,3,4]
L2 = [5] ;
L1 = [1,2,3,4,5]
L2 = [] ;
PARLOG
yes
X=[1,2,3,4,5]
L=[3,4,5]
[deadlock]
[deadlock]
Los últimos dos objetivos provocan un deadlock en PARLOG pues los
argumentos con restricción de entrada no están suficientemente instanciados
para permitir seleccionar una cláusula, luego el objetivo suspende, y por ser
el único objetivo a resolver, el sistema se bloquea.
En PARLOG, el paralelismo AND puede evitarse utilizando “&” en lugar
de “,” para separar los subobjetivos y los átomos del cuerpo de una cláusula.
Así, la selección de subobjetivo a evaluar se hace secuencialmente (de izquierda
a derecha) entre átomos separados por “&”.El paralelismo OR puede evitarse
utilizando “;” en lugar de “.” para separar las cláusulas. La búsqueda de
cláusula candidata se hace secuencialmente (en orden textual de arriba abajo)
entre cláusulas separadas por “;”.
9.2.
Comunicación entre procesos
En Programación Lógica Concurrente cada objetivo en ejecución es un
proceso, es decir, tiene su propio hilo de ejecución. Los procesos concurrentes
se comunican al instanciar variables lógicas compartidas y se sincronizan al
esperar que dichas variables sean instanciadas. Las variables lógicas son utilizadas como canales de comunicación instanciando la variable a una lista cuya
cabeza y cuerpo son variables lógicas; la cabeza puede ser usada para enviar
el mensaje actual y el cuerpo puede ser usado para los mensajes siguientes.
Estas ideas se ilustran a continuación, implementando algunos protocolos de
comunicación que usan definiciones para un productor y un consumidor.
112
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
Caso A: Comunicación unidireccional asíncrona (Figura 9.1).
p
naranja
naranja
c
c
p
naranja
c
Figura 9.1: Se produce una naranja, se consume una.
Programa
mode p(^).
p(Out) <Out = naranja.
mode c(?).
c(naranja) <write(’crouch!’).
Ejecución
| ?- p(X),c(X).
crouch!
X = naranja
La implementación de broadcasting es inmediata, como se muestra en el
siguiente objetivo.
| ?- p(X),c(X),c(X).
crouch!crouch!
X = naranja
9.2. COMUNICACIÓN ENTRE PROCESOS
113
Caso B: Comunicación unidireccional asíncrona(Figura 9.2).
1
p
2
p
...
naranja
naranja
...
c
c
...
Figura 9.2: Se produce un número ilimitado de naranjas.
Programa
mode p(^).
p([Out|RestoOut]) <Out = naranja,
p(RestoOut).
mode c(?).
c([naranja|RestoIn]) <write(’crouch!’),
c(RestoIn).
Ejecución
| ?- p(X),c(X).
crouch!crouch!crouch!...
114
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
Caso B’: Unidireccional asíncrona (Figura 9.3).
1
p
2
p
naranja
c
c
...
...
p
N
naranja
naranja
...
c
Figura 9.3: Se producen N naranjas.
Programa
mode p(?,?,^).
p(F,F,[]);
p(I,F,[Out|RestoOut]) <Out = naranja,
NewI is I + 1,
p(NewI,F,RestoOut).
mode c(?).
c([]).
c([naranja|RestoIn]) <write(’crouch!’),
c(RestoIn).
Ejecución
| ?- p(0,3,X),c(X).
crouch!crouch!crouch!
X = [naranja,naranja,naranja]
Nótese que el ritmo de producción del productor no tiene por qué ser igual
para el consumidor.
9.2. COMUNICACIÓN ENTRE PROCESOS
115
Caso C: Bidireccional síncrona (Figura 9.4).
dame_una
1
p
2
p
naranja
c
dame_una
...
naranja
...
c
...
Figura 9.4: El consumidor solicita ilimitadas naranjas, cada vez que se recibe
una se pide otra.
Programa
mode p(?,^).
p([dame_una|RestoIn],[Out|RestoOut]) <Out = naranja,
p(RestoIn,RestoOut).
116
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
mode c(?,^).
c([naranja|RestoIn],[Out|RestoOut]) <write(’crouch!’),
Out = dame_una,
c(RestoIn,RestoOut).
Ejecución
| ?- p([dame_una|X],Y),c(Y,X).
crouch!crouch!crouch! ...
Caso C’: Bidireccional síncrona (Figura 9.5).
dame_una
1
p
2
p
naranja
c
dame_una
naranja
c
...
...
...
dame_una
N
p
naranja
c
Figura 9.5: El consumidor solicita N naranjas.
Programa
mode p(?,^).
p([],[]).
p([dame_una|RestoIn],[Out|RestoOut]) <Out = naranja,
p(RestoIn,RestoOut).
mode c(?,?,?,^).
c(I,F,[naranja|RestoIn],[]) <F is I + 1:
write(’crouch!’);
9.2. COMUNICACIÓN ENTRE PROCESOS
117
c(I,F,[naranja|RestoIn],[Out|RestoOut]) <write(’crouch!’),
Out = dame_una,
NewI is I + 1,
c(NewI,F,RestoIn,RestoOut).
Ejecución
| ?- p([dame_una|X],Y),c(0,3,Y,X).
crouch!crouch!crouch!
X = [dame_una,dame_una]
Y = [naranja,naranja,naranja]
Caso D: Bidireccional sincronizada por espera de instanciación de
término incluido en mensaje incompleto (Figura 9.6).
1
p
2
p
...
naranja(Ok)
Ok=ok
naranja(Ok)
Ok=ok
...
c
c
...
Figura 9.6: Espera usando mensaje incompleto.
Programa
mode p(^).
p([Out|RestoOut]) <Out = naranja(OK) &
data(OK) &
p(RestoOut).
mode c(?).
c([naranja(OK)|RestoIn]) <write(’crouch!’),
OK = ok,
c(RestoIn).
118
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
Ejecución
| ?- p(X),c(X).
crouch!crouch!crouch! ...
Caso E : Comunicación N:1.
Si N es un número determinado antes de la ejecución, bastaría con tener
un merge que combine N entradas. Por ejemplo, la Figura 9.7 ilustra el caso
N=2.
p
naranja
naranja
merge
p
c
naranja
Figura 9.7: Más de un productor enviando mensajes a un mismo consumidor.
Utilizando alguna de las definiciones para p y c de los casos anteriores
junto a un merge típico, la comunicación 2:1 se conseguiría con el siguiente
objetivo :
<- p(X1),p(X2),merge(X1,X2,X),c(X).
Sin embargo, si N no se conoce de antemano la solución anterior no es aplicable pues el merge que se defina siempre tiene un número fijo de entradas. Una
fácil solución en PARLOG es utilizar el merge implícito en las sentencias de
manipulación de canales: create_channel, write_channel y close_channel.
Con estas sentencias se crea, escribe y cierra un merge implícito con un número
no determinado de entradas, este merge es llamado canal y tiene un identificador establecido en la creación, con el cual es referenciado en la escritura y
cierre.
9.3. OBJETOS Y CLASES EN PLC
119
p
naranja
p
naranja
...
naranja
c
p
Figura 9.8: Utilizando un merge sin límite de entradas.
canal_y_consumidor <create_channel(entrada,X),
c(X).
mode c(?).
c([naranja|RestoIn]) <write(’crouch!’),
c(RestoIn).
p <write_channel(entrada,naranja),
p.
Así, en este caso el predicado canal_y_consumidor crea un canal llamado
entrada el cual es una variable compartida con el argumento de c. El predicado
p escribe en el canal. Si se tienen varias ocurrencias del objetivo p todas
escribirán al mismo canal, el sistema realiza el merge implícito. La Figura
9.8 ilustra esta situación. En este caso el objetivo, dependiendo del N deseado,
sería :
<- canal_y_consumidor,p,...,p.
9.3.
Objetos y clases en PLC
Primero se mostrará en términos generales cómo algunos conceptos de
programación orientada a objeto pueden ser reflejados en un programa lógico
concurrente, las ideas fundamentales fueron establecidas en [46]. Como ya se
mencionó, se utilizará el enfoque en el cual los objetos son como procesos perpetuos, los cuales se comunican enviando mensajes. En Programación Lógica
Concurrente dicha enfoque se traduce en las siguientes funcionalidades claves:
120
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
Cada predicado tiene asociada un conjunto de cláusulas contra las cuales
puede efectuar su reducción, esto constituye la plantilla de objeto.
Cada cláusula de la plantilla tiene recursividad de cola, es decir, en el
cuerpo de la cláusula el predicado de la cabeza se vuelve a lanzar como
objetivo (a esto se debe el nombre de objetos perpetuos). La excepción
es el caso de finalización de la sesión del sistema, para la cual cada objeto
tiene asociada una cláusula sin recursividad de cola.
Cada objeto es un objetivo en reducción. El estado del objeto está representado por el valor de los términos usados como argumentos del objetivo. En cada reducción del objetivo dichos valores podrían cambiar.
Para determinar el valor de un atributo de un objeto puede utilizarse
tanto una perspectiva deductiva como una dinámica (temporal). En el
enfoque deductivo se tiene un argumento para registrar la traza de acciones y para cada atributo se establece un predicado que deduce el valor
del atributo a partir de la traza actual del objeto. En el enfoque dinámico se tiene uno o varios argumentos que registran sólo el valor actual de
los atributos. Se ha experimentado con ambos enfoques. En el apéndice
A se incluyen dos ejemplos utilizando el enfoque deductivo. Finalmente
se optó por el enfoque dinámico por ser el utilizado en OASIS 2.2.
La comunicación, interpretada como envío de mensajes, es provista mediante la instanciación parcial de variables compartidas entre los objetivos en reducción. Un objeto cliente se comunica con el objeto servidor
escribiendo el mensaje en una variable compartida entre ambos. La instanciación parcial se consigue implementando la variable compartida
como una lista, lo cual simula un canal de envío/recepción de mensajes.
Cada clase es también un objetivo que mediante su reducción, en el
cuerpo de las cláusulas que definen el predicado de la clase, cumplirá
esencialmente dos tareas :
• Atenderá el mensaje de creación de instancias de la clase. Para
ello existirá una cláusula que además de proveer recursividad en
cola para el objetivo que representa a la clase, generará un nuevo
objetivo representando a la instancia creada.
• Distribuir los mensajes desde un cliente a una instancia particular
de la clase, efectuando la relación entre el identificador usado para
referenciar al objeto y el oid del objeto, y luego escribiendo el mensaje en el canal de la instancia correspondiente. Para cumplir esta
tarea, el objetivo que representa a la clase contendrá un término
que almacena la población de la clase (una lista de términos que
9.3. OBJETOS Y CLASES EN PLC
121
relaciona identificador de objeto con canal de recepción de mensajes
del objeto).
El siguiente programa ilustra las ideas expuestas. En el programa se tienen
tres predicados clase/2, objeto/2 y enviar_a_todos/3, los dos primeros
constituyen la plantilla para instancias (objetivos) clase y objeto, el último es
un predicado usado en una cláusula del predicado clase/2 para implementar
un broadcasting del mensaje stop a cada instancia de la clase.
mode clase(?,?).
clase([new|Resto],[OidSiguiente,Poblacion]) <concat_atom([oid,OidSiguiente],Oid) &
create_channel(Oid,In) &
NOidSiguiente is OidSiguiente+1 &
objeto(In,[Oid,0,verde]),
clase(Resto,[NOidSiguiente,[Oid|Poblacion]])).
clase([fin|Resto],[OidSiguiente,Poblacion]) <enviar_a_todos(stop,Poblacion) &
close_channel(c).
mode enviar_a_todos(?,?).
enviar_a_todos(Evento,[]).
enviar_a_todos(Evento,[Oid|Resto]) <write_channel(Oid,Evento),
enviar_a_todos(Evento,Resto).
122
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
mode objeto(?,?).
objeto([e1|RestServicios],[Oid,N,C]) <not(C==verde):
objeto(RestServicios,[Oid,N,C]);
objeto([e1|RestServicios],[Oid,N,C]) <NN is N+1 &
CC = rojo &
objeto(RestServicios,[Oid,NN,CC]).
objeto([e2|RestServicios],[Oid,N,C]) <not(N > 0):
objeto(RestServicios,[Oid,N,C]);
objeto([e2|RestServicios],[Oid,N,C]) <NN is N-1 &
CC = verde &
objeto(RestServicios,[Oid,NN,CC]).
objeto([e3|RestServicios],[Oid,N,C]) <NN is N+1 &
CC = rojo &
objeto(RestServicios,[Oid,NN,CC]).
objeto([stop|RestServicios],[Oid,N,C]) <close_channel(Oid).
Los predicados clase/2 y objeto/2 utilizan su primer argumento como
una variable compartida que será instanciada parcialmente implementando así
un canal de comunicación. El segundo argumento de clase u objeto representa a variables de estado, para clase son : OidSiguiente y Poblacion, para
objeto son : Oid, N y C.
Para cada cabeza de cláusula se establecen instanciaciones apropiadas para
la variable compartida, con lo cual se consigue dirigir la reducción del objetivo hacia la cláusula que reflejará la admisión del mensaje y que en su cuerpo
contiene el comportamiento asociado a dicha admisión de mensaje. En nuestro
ejemplo un objeto clase reconoce los mensajes new y fin, un objeto objeto
reconoce los mensajes e1, e2 y e3. En las guardas se ponen condiciones adicionales a la recepción de un cierto mensaje. Sólo una cláusula podrá ser
seleccionada.
El usuario del programa lanzará el siguiente objetivo para ejecutar el sistema:
&& create_channel(c,X),clase(X,[1,[]]).
9.3. OBJETOS Y CLASES EN PLC
123
El objetivo create_chanel(c,X) crea un canal (variable compartida) identificada por c, esto implementa un merge implícito de todos los mensajes
que se escriban en dicho canal. El objetivo clase(X,[1,[]]) crea el objeto que representa a la clase, asociándole en su canal de entrada la variable
del canal identificado por c, además sus atributos tienen los siguiente valores:
OidSiguiente=1, Poblacion=[]. Los “&&” permiten lanzar el objetivo en segundo plano para evitar que se produzca deadlock y poder introducir objetivos
adicionales.
En este momento de la sesión sólo se tiene el objetivo clase en espera
por instanciación de su canal de entrada. A continuación se podría lanzar el
siguiente objetivo
write_channel(c,new).
Este objetivo tiene éxito y escribe en el canal c el mensaje new, el objetivo
clase([new|X’],[1,[]]) podrá ahora reducirse utilizando la cláusula correspondiente, con lo que se generará el primer objeto(In,[oid1,0,verde]). El
objetivo en este estado de la computación será:
<- clase(Resto,[2,[oid1|Poblacion]]), objeto(In,[oid1,0,verde]).
0
fin
1
new
Figura 9.9: Diagrama de transición de estados para el proceso clase.
124
CAPÍTULO 9. PROGRAMACIÓN LÓGICA CONCURRENTE
0
new
e2
1
fin
e1
e2
e3
2
fin
e3
Figura 9.10: Diagrama de transición de estados para el proceso objeto.
Es decir, tenemos en ejecución el objeto que representa a la clase y una
instancia de dicha clase. Posteriormente podemos comunicarnos con la clase
para continuar creando instancias mediante el mensaje new o comunicarnos
con cualquiera de las instancias creadas lanzando los mensajes e1, e2 o e3 al
canal identificado por su Oid. Las Figuras 9.9 y 9.10 muestran las secuencias
de mensajes que pueden recibir los objetos modelados en el ejemplo.
9.4.
Conclusiones del capítulo
Se ha hecho una breve introducción a la Programación Lógica Concurrente.
Particularmente se han analizado los tipos de comunicación entre procesos
ofrecidos. Un objeto en Programación Lógica Concurrente puede ser representado en forma natural y directa como un proceso perpetuo, es decir, un objetivo que se reduce y cambia de estado repetidamente. El predicado usado para
reducir dicho objetivo corresponde a la plantilla de clase, en la cual diferentes
cláusula permiten modelar distintos comportamientos para cada servicio. La
comunicación entre objetos se establece mediante variables compartidas entre
los objetivos correspondientes. Así, mediante instanciación parcial de dichas
variables compartidas se consigue el efecto de envío de un mensaje desde un
objeto a otro. Utilizando el paralelismo AND cada objetivo (objeto) tiene su
propio hilo de ejecución.
Capítulo 10
PLC y OASIS
En este capítulo se estudia la representación de conceptos OASIS en Programación Lógica Concurrente (PLC). Así, dada una especificación en OASIS
se podrá establecer un conjunto de pautas de traducción que permitan generar automáticamente el programa lógico concurrente correspondiente a una
especificación OASIS.
La Programación Lógica Concurrente es un paradigma de programación
con características apropiadas para la animación de especificaciones de sistemas dentro del enfoque orientado a objeto, ofreciendo un grado de implementación suficiente para prototipación dentro de un marco con posibilidades
de justificación formal.
La integración de la Programación Lógica Concurrente y la Programación
Orientada a Objeto ha motivado varias enfoques y propuestas. Esta Tesis se
enmarca dentro de las propuestas que modelan los objetos como procesos perpetuos, enfoque inspirado en los trabajos de Shapiro y Takeuchi [84]. Algunas
propuestas en esta línea son: Polka [18] y L2||O2 [74] basados en PARLOG y
A’UM [100] basado en GHC [95]. Sin embargo, la motivación en este trabajo
de Tesis es diferente, no se pretende aumentar la expresividad del lenguaje
lógico concurrente sino que proporcionar ejecutabilidad a una especificación
OASIS mediante traducción automática hacia un lenguaje lógico concurrente.
Se ha escogido Programación Lógica Concurrente como entorno de programación por las siguientes razones:
Los conceptos de orientación a objeto de OASIS tienen una directa representación en Programación Lógica Concurrente. Esto se constató en
[46].
La concurrencia en Programación Lógica Concurrente permite que cada
objeto tenga su propio hilo de ejecución.
125
126
CAPÍTULO 10. PLC Y OASIS
Es posible proveer una semántica declarativa y operacional para OASIS desde la perspectiva de la Programación Lógica Concurrente según
las equivalencias establecidas. Existen varias propuestas que abordan la
definición formal de la semántica para lenguajes lógicos concurrentes, entre ellas [7, 8, 6]. Esto permitiría a su vez justificar (al menos en parte)
la equivalencia del programa lógico concurrente obtenido por traducción
automática respecto de la especificación OASIS asociada.
Además, PARLOG y KL1, los lenguajes lógicos concurrentes que se han
utilizado, son de libre uso.
Los primeros experimentos relacionando conceptos OASIS con Programación Lógica Concurrente se hicieron con PARLOG [46]. Fruto de esto se
determinaron las correspondencias básicas presentadas anteriormente. PARLOG y KL1 son muy similares en cuanto a funcionalidad. Sin embargo, desde
el punto de vista de la prototipación de especificaciones OASIS, son relevantes
las siguientes comparaciones:
Todos los elementos de la especificación OASIS relacionados con verificación de condiciones (precondiciones, condiciones de evaluación, condiciones de derivación, condiciones de disparo, condiciones de restricciones
de integridad, etc.) se corresponden directamente con el concepto de
guardas de cláusulas en Programación Lógica Concurrente. Por esto, resulta bastante más abreviado el programa obtenido si el lenguaje permite
la especificación de guardas profundas1 , de lo contrario, para verificar
condiciones deben crearse cláusulas intermedias adicionales. PARLOG
provee cláusulas profundas, KL1 no.
Respecto a la implementación de comunicación inter-objeto, esto en
PARLOG es mucho más sencillo de implementar por disponer de primitivas para creación, escritura y cierre de canales, estas realizan implícitamente el merge que establece la comunicación muchos-a-uno necesaria
para cada objeto en su papel de servidor. En KL1 dicha mezcla debe
hacerse explícitamente manipulando variables denominadas vectores.
En cuanto a plataforma sobre la cual se pueden ejecutar, PARLOG se
restringe a máquinas Sun. KLIC el compilador de KL1, se puede instalar en cualquier plataforma UNIX. Además, los programas PARLOG
requieren arrancar su ambiente para ser ejecutados. Los programas KL1,
son traducidos por KLIC a C, es decir, se genera un código ejecutable
1
Se dice que un lenguaje lógico concurrente permite “guardas profundas” si es posible usar
en una guarda predicados adicionales a los provistos por el sistema. Cuando no se permiten
guardas profundas el lenguaje (o su versión) se califica como “plana” (flat ).
10.1. REPRESENTANDO UNA ESPECIFICACIÓN OASIS EN KL1
127
independiente. Esto último facilita la integración del programa generado
con otros programas.
El grupo de investigación que daba soporte para PARLOG se disolvió a
principios de los 90’s y no se tiene conocimiento de esfuerzos de continuación. Por otra parte, KL1 fue una pieza fundamental en la investigación llevada a cabo por el ICOT (Institute for New Generation
Computer Technology) mediante el proyecto FGCS (Fifth Generation
Computer Systems). Aunque el proyecto finalizó, el AITEC (Research
Institute for Advanced Information Technology), sucesor del ICOT, se
ha hecho cargo hasta la actualidad de la difusión y continuo desarrollo
del lenguaje.
Aunque las dos primeras comparaciones favorecen a PARLOG, las dos últimas resultaron más relevantes y determinantes para decidir utilizar KL1 como
lenguaje a ser generado. Por lo cual todos los trabajos posteriores asociados a
esta tesis se basaron en KL1.
10.1.
Representando una especificación OASIS en
KL1
En este apartado se estudiará en detalle cómo una especificación OASIS
puede ser representada mediante un programa KL1. Los detalles de algunas
cláusulas serán omitidos para facilitar su lectura.
10.1.1.
Clases y objetos
En Programación Lógica Concurrente una sociedad de objetos puede ser
vista (en tiempo de ejecución) como un objetivo a resolver, donde cada objeto es un subobjetivo. Cada subobjetivo es evaluado usando paralelismo AND
(concurrencia inter-objeto). El siguiente objetivo representa la situación descrita.
← object1 (In1 , Out1 , State1 ), ..., objectk (Ink , Outk , Statek )
k>0
Ini es el canal de entrada para las acciones que el objeto podría proveer. A
su vez, Ini es usado como oid para el objeto. Outi es canal de salida para las
acciones requeridas por el objeto. Statei es una lista de términos de la forma
att(Attribute, value), uno para cada atributo del objeto.
En general, en tiempo de ejecución se requiere creación (y destrucción)
de objetos. Por esto, deben existir subobjetivos con la capacidad de generar
(en su reducción) una nueva instancia. Estos subobjetivos corresponden en
128
CAPÍTULO 10. PLC Y OASIS
forma natural a la noción de clase como factoría de objetos. Así, las clases son
también implementadas como subobjetivos del objetivo que inicia la ejecución.
Una clase tiene un atributo llamado P opulation, el cual es una lista de pares
(Ini , Key) para cada instancia de la clase. Ini es el Oid del objeto, Key es una
lista de atributos constantes que permiten referenciar al objeto. El nombre del
predicado para una clase es el mismo nombre de la clase. Para un objeto el
nombre del predicado será el nombre de la clase precedido por “o_”.
o_account
o_account
o_customer
o_customer
o_account
(Oid2)
(Oid4)
(Oid3)
(Oid1)
customer
(Oid5)
account
Figura 10.1: Una situación de ejecución para el ejemplo bancario.
Ejemplo 33 Un situación de ejecución para el ejemplo bancario. En la Figura se ilustra una situación de ejecución en la cual existen dos instancias
de customer y tres instancias de account. El objetivo asociado (omitiendo
algunos detalles) sería el siguiente:
:- ...,customer(...),o_customer(Oid1,...),o_customer(Oid2,...),
account(...),o_customer(Oid3,...),o_customer(Oid4,...),
o_customer(Oid1,...).
El programa lógico concurrente que representa una especificación OASIS
estará compuesto por:
Para cada clase especificada, un conjunto de cláusulas cuyo predicado
en la cabeza lleva el nombre de la clase.
Para cada clase especificada, un conjunto de cláusulas cuyo predicado
en la cabeza lleva el nombre o_clase.
Un conjunto de cláusulas para los predicados de librería.
10.1.2.
Comunicación entre objetos
El mecanismo de comunicación ofrecido por la Programación Lógica Concurrente es la variable compartida entre subobjetivos, interpretada como un
canal de comunicación entre subobjetivos. Para permitir que muchos objetos se
10.1. REPRESENTANDO UNA ESPECIFICACIÓN OASIS EN KL1
129
Router
action(Clientx,Servery,Event)
Object
Clientx
action(Clientx,Servery ,Event)
Server
Class
action(Clientx ,Servery,Event)
Object
Servery
Figura 10.2: Esquema de comunicación entre objetos
comuniquen con un determinado objeto se ha implementado la configuración
mostrada en la Figura 10.2.
En general, si un objeto cliente clientx tiene que establecer una comunicación con un objeto servidor servery (que puede ser el mismo objeto cliente),
clientx instanciará parcialmente la variable que representa a su canal de salida Out. La variable Out es mezclada con el resto de variables de salida de
los objetos y proporcionada como canal de entrada para un objetivo adicional
llamado router. El router tiene tantos canales de salida como clases hay en
el sistema. Cada vez que el router recibe una acción en su entrada pondrá la
acción en el canal de salida asociado a la clase del objeto servidor de la acción.
El objetivo original al ejecutar un programa KL1 es el átomo main. Así, en
el cuerpo de este predicado se establece el esquema de comunicación descrito.
Ejemplo 34 La cláusula asociada al predicado main definida para el ejemplo
del sistema bancario.
main:take_active_actions(ExternActions),
UserActions=[action(c(tester),s(user),e(add,[att(userid,root)]))
|InUser],
user(InUser,OutUser,[att(population,[])]),
customer(InCustomer,OutCustomer,[att(population,[])]),
account(InAccount,OutAccount,[att(population,[])]),
generic:new(merge,{ExternActions,OutUser,OutCustomer,OutAccount},
Actions),
router(Actions,InUser,InCustomer,InAccount).
130
CAPÍTULO 10. PLC Y OASIS
El predicado take_active_actions coge las acciones externas durante la
sesión de animación. Siempre existirá una clase llamada user y una instancia
de dicha clase cuyo atributo userid tiene el valor root. Esto permite que el
analista durante la animación y en representación del objeto root introduzca
acciones que no tiene un cliente especificado, en nuestro ejemplo esto sucede
con las acciones de creación de objetos customer u objetos account. Del mismo
modo, el analista podrá introducir acciones en representación de cualquier
objeto que pueda actuar como cliente.
10.1.3.
Comportamiento del objeto
Cada objeto intenta reducirse a sí mismo usando las cláusulas que representan su especificación. Cada cláusula que reconoce una acción es capaz de
reducir al objeto a un conjunto de subobjetivos. A continuación se muestra el
subobjetivo o_classi (In∗ , Out∗ , State∗ ) que representa a un objeto y la forma de las cláusulas que pueden utilizarse para reducirlo. In∗ , Out∗ y State∗
representan las variables lógicas In, Out y State en un determinado momento
de la resolución. Se consideran p, q, s, t > 0 y r > 0.
: −..., o_classi (In∗ , Out∗ , State∗ ), ...
o_classi ([actioni1 |In], Out, State) : −
Gi1 , ..., Gip |
Bi1 , ..., Bit ,
o_classi (In, NOut, NState).
...
o_classi ([actionir |In], Out, State) : −
Gi1 , ..., Giq |
Bi1 , ..., Bis ,
o_classi (In, NOut, NState).
10.1.4.
Creación y destrucción de objetos
Las clases son subobjetivos lanzados en el objetivo inicial. Las nuevas instancias se obtienen por reducción del subobjetivo asociado a una clase cada
vez que se recibe una acción con el evento new. La creación de un objeto
implica que los siguientes subobjetivos son generados:
...
NOut = {Out, ObjectOut},
o_class(Oid, ObjectOut, Attributes),
10.1. REPRESENTANDO UNA ESPECIFICACIÓN OASIS EN KL1
131
...
Out es el canal de acciones requeridas por el subobjetivo asociado a la
clase. Este canal es separado en dos nuevas variables lógicas. NOut será usada
como nuevo canal de salida para la clase. ObjectOut será el canal de acciones
requeridas para el nuevo objeto. Oid es una variable lógica que será usada como
Oid del nuevo objeto y a la vez representa el canal de acciones a proveer.
Ejemplo 35 La cláusula que reduce al subobjetivo asociado a la clase account
cuando acontece una acción de creación (acción cuyo servicio solicitado es el
evento open2 ). En el cuerpo de la cláusula puede verse el lanzamiento del
nuevo subobjetivo asociado a la instancia creada de la clase account.
account([action(Client,s(account),e(open,Attributes))|RestActions],
Out,State) :Out={NOut,ObjectOut},
o_account(Oid,ObjectOut,Attributes),
get_attributes(Attributes,[att(number,Number)]),
NPopulation=[object(Oid,Number)|Population],
update_state(State,[chg(population,NPopulation)],NState),
...
account(RestActions,NOut,NState).
get_attributes es un predicado que extrae algunos valores de atributo
desde una lista. El predicado update_state modifica una lista de atributos
produciendo una nueva lista con ciertos cambios indicados en su segundo argumento. Cuando la acción solicitando open(101,john,0,0,1234,0,false)
es recibida, el subobjetivo account es:
account(action(Client,c(account),
e(open,[101,john,0,0,1234,0,false]))|Rest],Out,State)
Utilizando la cláusula antes mostrada, el subobjetivo es reducido finalmente
a dos subobjetivos, uno correspondiente al relanzamiento de la clase y otro
asociado al nuevo objeto, tal como se muestra a continuación:
...
o_account(Oid,ObjectOut,[att(number,101),att(name,john),
att(balance,0),att(times,0),att(pin,1234),
att(rank,0),att(good_balance,false)]),
account(Rest,NOut,[att(population,[object(Oid,101)]]).
La destrucción de un objeto es obtenida mediante una reducción del respectivo subobjetivo pero utilizando una cláusula cuyo cuerpo no relanza a
2
Un evento de creación tiene implícitamente como argumentos todos los atributos constantes y variables del objeto que se creará.
132
CAPÍTULO 10. PLC Y OASIS
dicho objeto. Es decir, se trata de una cláusula sin recursividad de cola, así,
la ejecución del objeto finaliza.
10.1.5.
Cambio de estado
Los objetos son implementados como procesos perpetuos (al menos mientras no son destruidos) porque entre los subobjetivos en los cuales un objeto
es reducido vuelve a aparecer el objeto. Esto produce el efecto de continuidad
en la vida del objeto. Cada vez que el objeto es relanzado alguno de sus atributos pueden ser diferentes respecto del subobjetivo anterior. De esta forma
se refleja el cambio de estado debido a la ocurrencia de una acción. El efecto
“ejecutar una acción” es obtenido en la reducción cuando el nuevo canal de
acciones a proveer es el del subobjetivo anterior con excepción de la acción recién ejecutada. Las fórmulas que definen el estado alcanzado inmediatamente
después de la ocurrencia de la acción corresponden a subobjetivos que asignan
nuevos valores a los atributos del objeto.
Ejemplo 36 La ejecución de la acción asociada al evento deposit(10) enviado al objeto creado anteriormente es representada como una reducción del
siguiente subobjetivo:
o_account([action(Client,s(account,id(number,[att(number,101)])),
e(deposit,[10]))|RestIn],Out,[att(number,101),att(name,john),
att(balance,0),att(times,0),att(pin,1234),att(rank,0),
att(good_balance,false)])
Este subobjetivo es reducido usando la siguiente cláusula:
o_account([action(Client,Server,e(deposit,[N]))|Rest],Out,State) :get_attributes(State,[att(balance,Balance),att(times,Times)]),
NBalance:= Balance+N,
NTimes:= Times+1,
LExp1:= NBalance,
RExp1:= 100,
test_condition([[c(ge,LExp1,RExp1)]],NGood_balance),
update_state(State,[chg(balance,NBalance),chg(times,NTimes),
chg(good_balance,NGood_balance)],NState)
o_account(Rest,Out,NState).
El predicado test_condition evalúa una lista de conjunciones representando una Fbf de la especificación. Si todos las conjunciones son satisfechas
el segundo argumento de test_condition es instanciado a true, de lo contrario su valor será false. Finalmente, el objetivo es reducido a uno nuevo con
10.1. REPRESENTANDO UNA ESPECIFICACIÓN OASIS EN KL1
133
un nuevo estado (NState), es decir, el objeto ha cambiado de estado. En el
ejemplo el objetivo resultante es:
o_account(Rest,Out,[att(number,101),att(name,john),att(balance,10),
att(times,1),att(pin,1234),att(rank,0),att(good_balance,false)])
10.1.6.
Permisos y prohibiciones
Las prohibiciones para acciones son implementadas mediante predicados
intermedios invocados desde el cuerpo de las cláusulas de un objeto.
Ejemplo 37 A continuación se muestra la cláusula que verifica las precondiciones de la solicitud de servicio withdraw(1234,10).
check_one_o_account_condition(action(Client,This,e(withdraw,[P,N])),
State,Result,Msg) :utility:get_attributes(State,[att(balance,Balance),
att(rank,Rank),att(pin,Pin)]),
LExp1:= Balance, RExp1:= N,
LExp2:= Balance, RExp2:= N,
LExp3:= Rank, RExp3:= 2,
LExp4:= P, RExp4:= Pin,
test_condition([[c(eq,LExp4,RExp4),c(ge,LExp1,RExp1)],
[c(eq,LExp4,RExp4),c(lt,LExp2,RExp2),c(eq,LExp3,RExp3)]],
Result),
Msg=not([[c(eq,LExp4,RExp4),c(ge,LExp1,RExp1)],
[c(eq,LExp4,RExp4),c(lt,LExp2,RExp2),c(eq,LExp3,RExp3)]]).
Esta vez el predicado test_condition es utilizado para instanciar a true
o false la variable Result, la cual representa si la Fbf del permiso se satisface.
Cuando la precondición no se satisface se genera una acción requerida al cliente
original y que incluye el mensaje Msg, el cual indica la Fbf no satisfecha.
10.1.7.
Obligaciones
En OASIS la comunicación entre objetos es activada por obligaciones. Este
trabajo se centra en el mecanismo fundamental de comunicación representado
por los disparos en OASIS. Los disparos representan comunicación asíncrona y
son implementados ejecutando Out = [Action|NOut] sin esperar una respuesta. Los disparos se generan debido a la satisfacción de una Fbf en el estado
actual del objeto. Así, en el cuerpo de cada cláusula que implementa un cambio de estado relacionado con la Fbf asociada se añade un objetivo que evalúa
la condición y realiza el disparo. Esta sentencia aparecerá en el cuerpo de una
134
CAPÍTULO 10. PLC Y OASIS
cláusula seleccionada en la reducción de un objeto cliente. Out es el identificador de la variable compartida que constituye el canal de acciones requeridas
por el objeto. NOut es la nueva variable para el canal de acciones requeridas.
Las acciones deben primero llegar al router, el cual envía la acción al correspondiente canal de entrada de la clase servidora. Si el servidor de la acción
es una instancia de la clase, dicha clase buscará en su atributo P opulation la
variable que representa al canal de entrada del objeto servidor.
Ejemplo 38 Un objetivo representando a un objeto de la clase account al
alcanzar un nuevo estado:
o_account([action(this,self,e(pay_commission,[]))|In],Out,
[att(number,101),att(name,john),att(balance,80),
att(times,5),att(pin,1234),att(rank,0),att(good_balance,false)])
La posibilidad de activación de un disparo en el nuevo estado fue detectada
durante el calculo del cambio de estado. La cláusula encargada de este trabajo
fue:
verify_o_account_triggers([t1|RestTriggers],State,Triggers) :utility:get_attributes(State,[att(times,Times),
att(good_balance,Good_balance),att(rank,Rank)]),
LExp1:= Times,
RExp1:= 5,
LExp2=Good_balance,
RExp2=false,
LExp3:= Rank,
RExp3:= 0,
utility:test_condition([[c(ge,LExp1,RExp1),
c(eq,LExp2,RExp2),c(eq,LExp3,RExp3)]],Answer),
utility:get_attributes(State,[att(number,Number)]),
utility:put_trigger(Answer,
action(this,self,e(pay_commission,[])),
Triggers,NTriggers),
verify_o_account_triggers(RestTriggers,State,NTriggers).
El predicado put_trigger pone la acción a disparar en la lista de disparos
(NTriggers) si la variable Answer es instanciada a true. En este ejemplo el
predicado test_condition instanciaría a true la variable Answer con lo cual
en el buzón Mbox, inmediatamente siguiente, el objeto tendrá como acción
obligada de ejecutar la siguiente:
action(this,self,e(pay_commission,[]))
Esta acción debe ser disparada y se reconoce porque el cliente es el término
this. Así, dicha acción es puesta en el canal de salida usando:
10.2. CONCLUSIONES DEL CAPÍTULO
135
Out=[action(This,self,e(pay_commission,[]))|NOut]
Esta vez, This está instanciada con la identificación del objeto, como
cliente de la acción generada.
10.2.
Conclusiones del capítulo
Las representación de clases y objetos presentada en el capítulo anterior
fue refinada en términos de conceptos específicos de OASIS. Para cada concepto OASIS se estableció una correspondiente representación en KL1. De esta
forma una especificación de clase en OASIS puede ser traducida a un programa
lógico concurrente. A partir de este trabajo se determinaron plantillas de traducción OASIS-KL1 mediante las cuales se construyó un programa traductor
que genera automáticamente un programa KL1 a partir de una especificación
OASIS almacenada en un repositorio. En el apéndice C se presenta parte de las
plantillas establecidas y ejemplos de código KL1 generado automáticamente.
136
CAPÍTULO 10. PLC Y OASIS
Capítulo 11
LUNA: Una herramienta
basada en OASIS
En este capítulo se elabora una propuesta global para la animación automática de especificaciones OASIS. LUNA es un ambiente de software para
la especificación incremental y validación de modelos conceptuales OASIS. LUNA está parcialmente terminado en su primera versión. El núcleo del entorno
lo constituye un programa traductor que a partir de una especificación OASIS
genera un programa lógico concurrente que sirve como prototipo para validar
la especificación. El capítulo está organizado de la siguiente forma: primero se
provee una descripción introductoria del entorno, posteriormente se detallan
cada uno de sus módulos y finalmente se presenta un proceso de construcción
incremental y validación de requisitos apoyado por el entorno de animación
propuesto.
11.1.
Ambiente de especificación incremental y validación
En el contexto de OASIS el comportamiento del sistema corresponde al
comportamiento de la sociedad de objetos incluidos en él y puede ser observado a través de las acciones acontecidas y los estados alcanzados por cada
objeto. La animación de una especificación OASIS debe permitir examinar
el comportamiento de un objetos o grupo de objetos, explorando las acciones
acontecidas (generadas internamente o desde el exterior al grupo de objetos observados) y los correspondientes estados alcanzados. Esta facilidad exploratoria ya constituye una mejora para la validación del modelo conceptual. Sin
embargo, para una validación dirigida a contrastar requisitos y que a la vez
aproveche en mayor medida la animación se propone: especificar los requisitos
funcionales del sistema usando escenarios en términos de objetos involucrados,
137
138
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
acciones acontecidas y estados alcanzados. De esta forma, se consigue una representación de los requisitos que es comparable con la observación a realizar
en la animación del modelo conceptual.
comportamiento
esperado
escenarios
elementos
de especificación
modificación y/o
extensión
de escenarios
Asistente
para
construir
escenarios
Entorno
gráfico de
especificación
Repositorio
basado en el
modelo de
OASIS
Entorno
gráfico de
animación
comparación
animación versus
comportamiento
esperado
Prototipo
Traductor
resultados
comparación
Figura 11.1: Ambiente para especificación y validación de especificaciones OASIS
La Figura 11.1 muestra cómo las ideas planteadas se materializan en un
entorno software para la especificación incremental y validación de modelos
conceptuales. Los componentes del entorno (en el rectángulo de la derecha)
son: un asistente para especificar escenarios en el formato adecuado para su
comparación, un subentorno gráfico de especificación que editar el modelo
conceptual, un repositorio que almacena el modelo conceptual y los escenarios,
un traductor que genera automáticamente un prototipo a partir del modelo
conceptual almacenado y un subentorno de animación para interactuar de
manera exploratoria con el prototipo o para validar específicamente cada uno
de los escenarios almacenados respecto del comportamiento del prototipo.
En términos generales, se trata de un trabajo que puede ser extendido (o
integrado) en el desarrollo de una herramienta CASE. Sin embargo, se ha prescindido de características no estrictamente relacionadas con la construcción
incremental y validación del modelo conceptual. La programación de las interfaces gráficas se ha realizado con Tcl/Tk [68]. Los componentes del entorno
(en el rectángulo de la derecha en la Figura 11.1) son:
Un asistente para construir escenarios. La programación de este módulo
aún no se ha comenzado. Las técnicas usadas para especificar escenar-
11.2. REPOSITORIO OASIS
139
ios varían considerablemente (ver [80]) desde textuales a gráficas, desde
informales a formales, etc. Con respecto del entorno propuesto, el objetivo es poder realizar una comparación de resultados obtenidos por
animación respecto de resultados esperados incluidos en los escenarios.
De esta forma, interesa que tanto la especificación de escenarios caracterice el comportamiento esperado mediante trazas de acciones y estados
alcanzados de la vida de los objetos estudiados, tal como se obtienen de
la animación del modelo conceptual.
Un entorno gráfico de especificación, que permite editar el modelo conceptual. Este módulo permite la edición gráfica del modelo, definiendo
los elementos de la especificación que se almacenan en el repositorio.
Para las especificaciones de proceso de una clase (operaciones y protocolos) se ha integrando un editor gráfico de diagramas de transición de
estados.
El repositorio, que almacena el modelo conceptual y los escenarios. Corresponde a un metamodelo estático para especificaciones OASIS sobre
un modelo relacional.
Un traductor de OASIS a Programación Lógica Concurrente que genera
automáticamente un prototipo a partir del modelo conceptual almacenado.
El entorno de animación, que permite al analista interactuar adecuadamente con el prototipo. La idea es ofrecer tanto una validación exploratoria como una validación dirigida a comprobar cada uno de los escenarios
establecidos respecto del comportamiento del prototipo.
11.2.
Repositorio OASIS
Considerando el propósito de este trabajo, el repositorio OASIS surge con
la necesidad de disponer de una estructura de almacenamiento para especificaciones OASIS a partir de la cual pueda generarse automáticamente un
prototipo en KL1. Una vez establecidas las pautas de traducción (plantillas) OASIS-KL1, incluyendo todas las correspondencias estudiadas, el paso
siguiente para implementar la automatización requería como entrada una estructura de almacenamiento para especificaciones OASIS. Así, el repositorio
haría el papel de pivote entre la especificación y la prototipación. Una posibilidad era establecer una estructura de almacenamiento en memoria primaria
y además definir un fichero de intercambio en un determinado formato, esto
último para posibilitar la conexión entre distintas herramientas. Sin embargo,
para permitir una mejor integración entre herramientas se decidió establecer
140
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
una estructura en almacenamiento secundario para ser implementada en un
gestor de base de datos. Además, de acuerdo a la tecnología imperante, el
objetivo fue diseñar una base de datos relacional.
Desde la perspectiva de modelado, el repositorio debería ser el metamodelo
estático de una especificación OASIS, es decir, una especificación OASIS de
la estructura de cualquier especificación OASIS concreta. Sin embargo, considerando que el objetivo sólo era definir un modelo relacional, se optó por un
enfoque más pragmático orientado a definir un modelo sintáctico para especificaciones OASIS, basado en la BNF del lenguaje.
La primera versión de una BNF para OASIS 2.2 (extendido con todos los
aspectos necesarios para animación automática) y el correspondiente repositorio relacional fue establecido en [47]. En su primera versión el repositorio
era poblado directamente a partir de una especificación OASIS textual utilizando un analizador sintáctico. En 16 proyectos de fin de carrera posteriores
se trabajó utilizando dicho repositorio, lo cual sirvió para depurarlo. Finalmente, con la aparición de OASIS 3.0 (el cual incluyó todas las extensiones
que habían sido consideradas sobre la versión anterior) y dentro del marco del
proyecto MENHIR [63], el repositorio fue actualizado para la sintaxis de la
nueva versión [77].
11.3.
Entorno gráfico de especificación
La Figura 11.2 muestra la versión actual de este módulo que permite especificar gráficamente el Diagrama de Configuración de Clases [72] y en forma
textual los detalles de la plantilla de una clase. Este módulo sirve de entrada a
todo el entorno de animación propuesto. En él es posible modificar o crear un
repositorio, modificando o creando esquemas conceptuales dentro de ellos. Una
vez establecidos el repositorio y el esquema conceptual de trabajo, el analista
puede modificar el diagrama de configuración de clases.
Haciendo clic en alguna de las clases es posible acceder a la especificación
de la misma, tal como se ilustra en la Figura 11.2. De esta forma se pueden especificar: identificadores, atributos, eventos, evaluaciones, precondiciones, disparos, protocolos y operaciones. Además en la parte inferior de dicha ventana
pueden detallarse las características particulares de cada relación en la cual
participa la clase especificada.
En particular, para la especificación de protocolos y operaciones se utiliza
un subentorno de edición de Diagramas de Transición de Estados [72]. La
Figura 11.4 muestra la representación gráfica de un protocolo en la versión
actual de dicho subentorno.
Toda la información introducida acerca de la especificación, sea gráfica o
textual, es almacenada en el repositorio OASIS de la herramienta. Desde la
11.4. TRADUCTOR OASIS-PLC
141
Figura 11.2: Entorno Gráfico de Especificación.
ventana de la Figura puede realizarse una verificación de consistencia de la
especificación (seleccionando entre las opciones del menú “Especificación”) y
generar la especificación OASIS textual correspondiente al modelo introducido. Una vez que la especificación ha sido verificada con éxito, puede generarse
automáticamente un prototipo para animación. Nótese que la especificación
debe satisfacer unas restricciones mínimas de completitud y consistencia para
posibilitar su prototipación. Mediante la opción de menú “Simulación” se accede al subentorno de animación.
11.4.
Traductor OASIS-PLC
Se ha construido un programa traductor que accede al repositorio OASIS
y genera una serie de ficheros KL1, éstos son traducidos a C (usando el compilador KLIC) y finalmente el código C resultante es compilado para obtener
el prototipo de la especificación. El programa traductor de OASIS a KL1 está
escrito en lenguaje C. La Figura 11.5 muestra un esquema simplificado de la
generación de código KL1 desde el repositorio. Tal como se aprecia en dicha
142
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
Figura 11.3: Especificación de una clase.
figura en el total del código generado es posible identificar tres aspectos (que
en el código resultante se mezclan): el código asociado estrictamente a los requisitos modelados en la especificación (que puede variar significativamente de
un sistema a otro), el código asociado al modelo de ejecución (integrado dentro
del anterior pero con una estructura no cambiante) y finalmente el código de
librería que es igual para todos los sistemas (por esto, como veremos dicho
código no se genera sino que se integra al traducir de KL1 a C).
11.4. TRADUCTOR OASIS-PLC
143
Figura 11.4: Subentorno para edición de Diagramas de Transición de Estados.
Código por
Modelo de
ejecución
Traducción
automática
Modelo
OASIS
Código por
Requisitos
Prototipo
para
animación
Código de
librería
Figura 11.5: Tres aspectos en el código KL1 de un prototipo.
144
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
11.4.1.
Alcance del prototipo generado
El entorno de especificación y el repositorio usados actualmente permiten
cubrir prácticamente toda la expresividad de OASIS 2.2 incluyendo además
muchas de las mejoras de OASIS 3.0. Sin embargo, y por limitaciones de
alcance del presente trabajo, en cuanto a generación de prototipo, actualmente
se ha abordado sólo una parte de dicha expresividad. Se ha intentado equilibrar
el avance logrado en cuanto a repositorio, entorno de especificación y modelo
de ejecución. Los aspectos de una especificación OASIS que hasta la fecha se
pueden animar automáticamente son:
Clases simples.
Atributos (constantes, variables y derivados).
Identificadores de objetos (identificadores alternativos y posiblemente
formados por más de un atributo).
Eventos
Evaluaciones (incluyendo perspectiva cliente)
Precondiciones
Disparos
Protocolos y Operaciones (sin incluir anidamiento, comunicación del tipo
call/return ni action waiting).
Aunque otras importantes características aun no están incorporadas, es
posible efectuar validación de requerimientos para especificaciones de clases
considerando al menos un comportamiento restringido de ellas. Entre los aspectos no tratados y que deberán ser incorporados en futuras versiones se
puede destacar:
Relaciones entre clases
Comunicación action waiting, action calling y action sharing.
Restricciones de Integridad
Transacciones
11.4. TRADUCTOR OASIS-PLC
11.4.2.
145
Plantillas para generación de código KL1
Con las correspondencias entre OASIS y Programación Lógica Concurrente
(en particular las establecidas con KL1), descritas en el capítulo anterior, se
determinaron plantillas1 de traducción [49] para cada uno de los elementos del
programa que deben ser generados. Estas plantillas incorporan el modelo de
ejecución común a todas las especificaciones OASIS. El proceso de generación
de un prototipo consiste en completar dichas plantillas con la información del
repositorio para un sistema en particular. El enfoque seguido es similar al
utilizado en OBLOG [67] y System Architect [76], en los cuales se provee un
lenguaje de scripts el cual incorpora primitivas de acceso al repositorio. De esta
forma se facilita la tarea de generación a distintos lenguajes y/o en distinto
estilo para un mismo lenguaje. Sin embargo, los scripts no son fácilmente
legibles. En este trabajo no se consideró interesante trabajar con un lenguaje
de scripts puesto que el lenguaje de generación era sólo uno y el estilo también.
Por otra parte, la necesidad de realizar continuos experimentos modificando las
plantillas hacía imprescindible que éstas fueran legibles. Finalmente, cuando se
alcanza una generación satisfactoria las plantillas se mantienen sin cambios. La
desventaja de utilizar plantillas y no un lenguaje de scripts es que las plantillas
deben ser implementadas en un lenguaje de programación para construir el
traductor (en este trabajo se ha utilizado C), con lo cual las modificaciones de
una plantilla deben posteriormente (y en forma manual) trasladarse al código
del traductor.
La información desde el repositorio se obtiene de forma directa recorriendo las tablas mediante sus relaciones. Por ejemplo, para obtener los atributos
de un objeto de una clase se consulta la tabla atributos usando el campo
nro_clase, de manera que éste corresponda a la clase que se está generando.
Un aspecto que no es tan directo, es la representación y tratamiento de acciones. En una especificación OASIS los clientes y servidores de las acciones
muchas veces son implícitos, pero en la ejecución deben ser tratados explícitamente.
Se han considerado las siguientes representaciones particulares para clientes
y servidores:
Cliente puede ser uno de los siguientes términos self, this o c(clase).
El término this es el cliente implícito para todas las acciones que representan una obligación del objeto. Si el cliente es una clase se utiliza el
nombre de la clase como término cliente. Si el cliente no es declarado en
la especificación OASIS, se usa la variable Client lo cual implica que el
cliente puede ser cualquiera.
1
Se ha preferido utilizar simplemente la palabra “plantilla” en lugar de otras usadas en el
ámbito de generación automática de código, tales como: framework, arquitectura, etc. Esta
últimas más elegantes pero a la vez menos precisas.
146
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
Servidor puede ser self, this, s(society,everyone), s(clase,everyone)
o s(clase).
Servicio es el término e(evento_u_operación,Args), donde evento_u_operación es un nombre de evento u operación en la signatura de la clase especificada y Args es una lista de los valores de argumentos en el mismo orden en
el cual fueron puestos en la declaración del evento u operación.
Las correspondencias entre clientes especificados en OASIS y términos en
PLC se muestra en la siguiente tabla:
Cliente en OASIS
no declarado
self
“::”(obligación)
society(someone)
clase
clase(someone)
clase(Id,Value)
Cliente en PLC
Client
self
this
c(society,someone)
c(clase)
c(clase,someone)
c(clase,id(Id,Value))
Del mismo modo, las correspondencias entre servidores especificados en
OASIS y términos en PLC se muestra en la siguiente tabla:
Servidor en OASIS
self
society(everyone)
clase
clase(everyone)
clase(Id,Value)
Servidor en PLC
self
s(society,everyone)
s(clase)
s(clase,everyone)
s(clase,id(Id,Value))
Estructura del prototipo
El código KL1 del prototipo para un esquema conceptual está formado por
los siguientes predicados (generados en el fichero prototipo.kl1):
Los predicados main y router para arrancar la sesión de prototipación
y establecer los enlaces de comunicación entre objetos.
Un par de predicados c_clase y o_clase por cada clase del sistema. Estos predicados definen los proceso perpetuo correspondientes a la clase
y a sus instancias. El tratamiento para ambos casos es homogéneo. El
evento declarado new para instancias de clase es un evento del objeto
que representa a la clase, el evento destroy es un evento de cada instancia. Los procesos al reducirse por recepción de acciones en su canal
11.4. TRADUCTOR OASIS-PLC
147
de entrada enviarán toda la información relevante hacia la interfaz del
entorno de animación (o la registrarán en el fichero test.res cuando se
haga la animación con entrada por lotes). En todo sistema existe una
clase llamada user que recibe las acciones introducidas por el analista (o
lee desde el fichero del caso de prueba, llamado test.dat) y encamina
las acciones hacia el router.
Los predicados de librería, predicados comunes invocados en los cuerpos
de las cláusulas de los otros predicados.
Una vez generado el ficheros con el código fuente KL1 se invoca al compilador KLIC de la siguiente forma:
klic prototipo.kl1
Esto produce directamente un programa ejecutable, pasando automáticamente por una etapa intermedia de traducción a código C.
Con las plantillas establecidas en [49] se construyó un programa en C
(aproximadamente 5.000 líneas código fuente) que genera cada grupo de cláusulas del fichero prototipo.kl1. La traducción, generación del prototipo y su
ejecución se realizan en una máquina UNIX.
La Figura 11.6 muestra los pasos, las líneas de código y tamaños asociados a
la generación del prototipo para el ejemplo del sistema bancario (con las clases
cliente y cuenta). Aunque el tamaño del prototipo resultante es considerable
(1.4 Mb), no aumenta considerablemente cuando se tienen más clases, esto se
debe a la generación automática a C que realiza el compilador KLIC, paso en
el cual se añade gran cantidad de código por defecto.
Traductor
automático
Modelo
OASIS
2 clases
60 líneas
1 Kb
Traductor
Klic
Programa KL1
2.100 líneas
75 Kb
Compilador C
Programa en C
> 17.000 líneas
0.5 Mb
Programa
ejecutable
1.4 Mb
Figura 11.6: Un ejemplo de los pasos de generación automática
Desde el punto de vista del programa KL1 gererado por el traductor
OASIS-KL1, se tienen las siguientes estadísticas:
148
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
Predicados
main y router
de librería
por cada clase
Nro. Predicados
2
41
16
Nro. Cláusulas
3 + (4*Nro. clases2 )
129
32 + (3*Nro. servicios)
+ (1*Nro. disparos)
Así, en ejemplo bancario simplificado se tienen los siguientes datos:
Predicados
main y router
de librería
por clases
Nro. Predicados
2
41
48
91
Nro. Cláusulas
15
129
127
406
Figura 11.7: Primera versión del Entorno de Animación
2
Contabilizando la clase user.
11.5. ENTORNO DE ANIMACIÓN
11.5.
149
Entorno de animación
Hasta el momento se han desarrollado tres versiones para este entorno. En
la primera versión [49] las sesiones de prototipación se hacían mediante procesamiento por lotes. Un fichero servía de entrada para en prototipo y contenía
una secuencia de acciones a ser aplicadas. Las clases e instancias ejecutaban
dichas acciones y registraban su comportamiento y estado en un fichero de
salida. Posteriormente el analista examinaba dicho fichero de salida y lo comparaba manualmente con el comportamiento esperado. En el Apéndice D se
detalla una sesión de animación utilizando esta versión. Este enfoque resulta
útil cuando se tienen que aplicar muchas acciones (por el analista) al prototipo
y ellas están bien definidas previamente. Sin embargo, cuando se quiere realizar
una validación exploratoria o debe existir una interacción más compleja con
el analista, este enfoque no resulta apropiado. Sin embargo, las posibilidades
ofrecidas debían mantenerse en futuras versiones porque cuando se contara con
el asistente para construir escenarios sería imprescindible hacer animaciones
en modo de entrada por lotes (batch) y así, poder realizar comparaciones en
forma automática. Esto ha hecho que en las posteriores versiones el módulo
de animación se centre en establecer una interfaz más adecuada para la validación exploratoria sin que esto haya producido cambios en la forma en la
cual el prototipo es generado.
La Figura 11.7 muestra la interfaz de la segunda versión del entorno de
animación, que puede ser ejecutada en una página Web mediante la instalación del Plug-In para Tcl/Tk. La funcionalidad es similar a la ofrecida por
la tercera versión. Sin embargo, se desecho la idea de continuar trabajando con
el Plug-In (es decir, con el animador incrustado en una página Web) puesto
que los comandos inhabilitados restringen demasiado la interacción posible de
incorporar.
A continuación se describe la tercera versión para el entorno de animación.
La Figura 11.8 ilustra el inicio de la sesión de animación. La animación empieza desde el ambiente integrado, donde previamente se carga (o se crea) un
esquema conceptual, se verifica su consistencia y se genera el prototipo. La
ventana de la Figura 11.8 está dividida en dos áreas: a la izquierda el área
de objetos permite visualizar los objetos que están activos y a la derecha se
muestran las listas de acciones procesadas hasta el último tick significativo
(aquel en el cual algún objeto alcanzó un nuevo estado). Se ha implementado
un mecanismo versátil de filtros para la visualización de acciones y facilitar el análisis de las trazas de objetos. Por un lado, en el área de objetos
se puede seleccionar un objeto, un grupo de objetos o todos los objetos del
esquema conceptual (haciendo clic en el fondo del área izquierda). Adicionalmente, con los botones del área derecha, se puede seleccionar el subconjunto
de acciones que se desea visualizar. Por defecto se muestran todas (Mboxi ),
150
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
Figura 11.8: Inicio de la sesión de animación
pero se pueden filtrar las obligadas de requerir (OReqi ), las no-obligadas de
ejecutar (OExeci ), las acciones en conflicto (Confi ), las acciones ejecutadas
(Execi ) o las acciones rechazadas (Rejecti )3 . Los botones de la parte inferior
del área izquierda tienen la siguiente funcionalidad: el botón play comienza la
animación; el botón stop detiene la animación para comenzar una nueva con
play; el botón pausa suspende la animación y habilita los botones rewind y
forward que permiten retroceder o avanzar examinando las trazas en ticks ya
ejecutados (el área de la derecha se refresca a medida que se cambia el tick.
Al avanzar o retroceder sólo se muestran los ticks significativos.
Al comienzo, se refleja la creación de un metaobjeto por cada clase del
esquema. Además, también por defecto, se crea un objeto user identificado por
root. A través de este objeto el analista puede crear las instancias necesarias
de las clases correspondientes.
Al hacer un click sobre un objeto aparece la ventana de la Figura 11.9.
Esta ventana muestra todas las clases y servicios que son accesibles para el
objeto seleccionado. Además, se mostrará una ventana indicando el estado del
objeto seleccionado. Por defecto, el objeto user(root) puede acceder a todos
las clases del esquema y a todos sus servicios. Para otros objetos dicho acceso
depende exclusivamente de las interfaces establecidas en el esquema conceptual. En la ventana de la Figura 11.9 se realiza la creación de dos instancias
de cuenta (con número 101 y 102) y una instancia de cliente identificado por
el nombre “diego”.
Después de lanzar las acciones de creación y hacer clic en el fondo del área
3
En esta versión del traductor y entorno de animación no ha sido incorporado el tratamiento de acciones obligadas de proveer (OP rovi ).
11.6. PROCESO DE ESPECIFICACIÓN Y VALIDACIÓN
151
Figura 11.9: Construcción de acciones de creación de instancias
de objetos, la ventana resultante se muestra en la Figura 11.10. A continuación,
se recreará un escenario en el cual un objeto cliente realiza cuatro depósitos y un reintegro en una cuenta. Los servicios solicitados son: deposit(10),
deposit(20), deposit(30), deposit(40) y withdraw(50). Seleccionando el
objeto customer(diego) se accederá a una ventana similar a la Figura 11.9
desde la cual el analista puede construir las acciones y requerir los servicios en
representación del objeto customer(diego). Las cinco acciones serán enviadas
al objeto account(101).
Si posteriormente se selecciona el objeto account(101) y se presiona el
botón Execi , puede verse en la Figura 11.11 la lista de todas las acciones
ejecutadas hasta el último tick significativo. La Figura 11.12 muestra el estado
del objeto account(101) a partir de dicho tick.
11.6.
Proceso de especificación y validación
El proceso de construcción del modelo conceptual, en términos generales
contendría las siguientes actividades:
1. Capturar requisitos del usuario mediante técnicas de escenarios.
2. Especificar los escenarios en una forma representativa para su comparación (objetos, acciones y estados alcanzados).
3. Especificar los elementos de la especificación asociados a cada escenario
y que determinan partes del modelo conceptual.
4. Verificación automática de la consistencia del modelo conceptual y de
los escenarios introducidos.
152
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
Figura 11.10: Sesión de animación después de crear tres instancias
5. Obtención automática de un prototipo para animación.
6. Validación del modelo conceptual. Mediante animación de la especificación se contrasta el funcionamiento del sistema respecto de cada
escenario introducido. Además, realizando una animación exploratoria
pueden buscarse situaciones de funcionamiento que evidencien comportamientos no deseados o que el modelo conceptual no está completo.
7. Modificación y/o extensión del conjunto de escenarios.
Estas actividades se repetirían en la secuencia establecida hasta conseguir
un resultado satisfactorio en lo que respecta a la actividad 6. Cualquier modificación en los requisitos funcionales del sistema determinaría posibles cambios
en los escenarios, con lo cual se volvería a entrar en el ciclo de actividades
indicadas.
11.7.
Conclusiones del capítulo
Se ha presentado una versión preliminar de la herramienta LUNA, un ambiente para la especificación incremental y validación de especificaciones OASIS. LUNA permite especificar gráficamente un modelo conceptual OASIS.
La orientación hacia validación se ve reflejada en dos entornos específicos: un
asistente para la construcción de escenarios (aún no construido) y un entorno
de animación (versión preliminar). Mediante la traducción automática de una
especificación OASIS en un prograrma KL1, se dispone de un prototipo el cual
es utilizado para contrastar su comportamiento respecto del comportamiento
11.7. CONCLUSIONES DEL CAPÍTULO
153
Figura 11.11: Acciones ejecutadas por el objeto account(101)
Figura 11.12: Estado actual del objeto account(101)
esperado, este último incluido en los escenarios especificados. En el estado actual de la herramienta, se traducen especificaciones OASIS (incluyendo clases
simples y abarcando casi toda la plantilla de clase) y es posible realizar una
validación exploratoria interactuando con el prototipo a través del entorno de
animación. El propósito final es que LUNA se integre dentro del contexto más
amplio de una herramienta CASE.
154
CAPÍTULO 11. LUNA: UNA HERRAMIENTA BASADA EN OASIS
Capítulo 12
Conclusiones
El aporte indirecto más importante de este trabajo de Tesis lo constituyen
las extensiones y mejoras sobre OASIS 2.2, formando todas ellas parte fundamental de la nueva versión: OASIS 3.0. Las principales contribuciones en este
sentido son: incorporación de la perspectiva cliente, una nueva formalización
para las especificaciones de proceso en el marco de la Lógica Dinámica y un
esquema de comunicación más preciso y completo. Además, se ha establecido
un modelo de ejecución para especificaciones OASIS 3.0.
Se determinaron correspondencias entre conceptos OASIS y Programación
Lógica Concurrente, mediante las cuales se definieron plantillas de traducción
que fueron finalmente implementadas en un programa traductor. Se constató
que la representación de clases y objetos en Programación Lógica Concurrente
resulta directa. Gracias a la concurrencia ofrecida por el lenguaje (PARLOG
y KL1) cada objeto (y la clase como un objeto más) se implementa como
un proceso con su propio hilo de ejecución y la comunicación se establece
mediante variables compartidas. De esta forma la representación es natural
respecto de la semántica dada a los objetos en OASIS. Así, no se tiene que
introducir un monitor para gestionar la actividad del sistema como ocurre
en el caso de implementaciones usando un lenguaje secuencial. Se diseñó e
implementó un repositorio para almacenar especificaciones OASIS. El traductor genera automáticamente un programa KL1 a partir de una especificación
OASIS almacenada en el repositorio.
Se elaboró una propuesta de ambiente para la especificación incremental y
validación de modelos conceptuales OASIS basada en animación automática,
describiendo el proceso asociado. El traductor OASIS-KL1 es el elemento clave
de la propuesta. En este marco, se construyó una versión preliminar para el
entorno gráfico de especificación que permite introducir el modelo conceptual
OASIS y almacenarlo en el repositorio. También se construyó una versión
preliminar para el entorno de animación que posibilita la interacción adecuada
155
156
CAPÍTULO 12. CONCLUSIONES
del analista con el prototipo (programa KL1 automáticamente generado).
12.1.
Trabajo futuro
Respecto de la herramienta construida y su posterior mejora o extensión
para incluir toda la expresividad de OASIS 3.0, existen cuatro aspectos a considerar: modelo de ejecución OASIS, repositorio OASIS, traductor OASIS-KL1
y entornos de especificación y animación. El repositorio actual incluye todas
las características de OASIS 3.0. El modelo de ejecución debe ser extendido
para considerar restricciones de integridad y transacciones. Estas extensiones
involucran también cambios en el traductor OASIS-KL1.
Se está trabajando actualmente en un aplanamiento de las relaciones entre
clases de manera que con un paso intermedio (previo a la generación de código
KL1) se obtiene una representación equivalente de la especificación, pero sin
incluir dichas relaciones. La idea es aplanar las jerarquías de especialización
estableciendo directamente las plantillas asociadas y eliminar las jerarquías
de agregación reemplazándolas por determinados esquemas de comunicación
entre objetos. Así, el modelo de ejecución, traductor y del entorno de animación
no deben ser extendidos para incluir dichas características.
El entorno “asistente gráfico para construir escenarios” no ha sido aún
desarrollado. Esto es indispensable para poder conseguir algún grado de automatización en la comparación entre el comportamiento esperado y el comportamiento exhibido por el prototipo.
En particular, se constató que para la validación sería interesante incorporar animación simbólica tal como se plantea en [4, 37]. La evaluación simbólica
permite que los escenarios sean parcialmente especificados. Aquellos aspectos
no especificados son tratados simbólicamente con todos los casos (relevantes a
la especificación) y automáticamente explorados. Esto provee un medio para
explorar clases de escenarios simultáneamente.
También sería conveniente asistir automáticamente la validación exploratoria mediante generación automática de escenarios. Existen técnicas de prueba
que ayudan a la generación de casos de pruebas. Con alguna adaptación en
dichas técnicas, que utilizan pseudocódigo o código fuente, podrían ser aplicadas a especificaciones OASIS. Por ejemplo, de camino básico (para operaciones y protocolos), pruebas de condiciones, de valores límite, etc.
Por otra parte, la equivalencia entre el programa lógico obtenido respecto
de la especificación OASIS es una materia aún pendiente. Sin embargo, en
nuestro caso la verificación y demostración de dicha equivalencia (al menos
en forma parcial) se ve favorecida por tres importantes factores: primero el
modelo conceptual es especificado en un lenguaje formal (OASIS), segundo el
modelo abstracto de ejecución está asociado a la semántica de dicho lenguaje
12.2. PUBLICACIONES IMPULSADAS POR ESTA TESIS
157
formal y en tercer lugar existen varias propuestas que abordan la formalización
de Lenguajes Lógicos Concurrentes [6, 7, 8]. Esto ofrece la posibilidad de justificar formalmente las equivalencias entre constructores del modelo conceptual
OASIS y el programa obtenido para animación. Así, los factores indicados
proveen un camino de formalización en el cual se puede trabajar. De todas
formas, debe destacarse que la situación actual de este trabajo no es peor
que la mejor situación posible en muchas otras propuestas de validación usando prototipación, más aún si se trata de enfoques basados en un proceso
de generación manual e informal del prototipo. El problema planteado es en
sí una de las tareas pendientes no sólo en prototipación sino en la obtención
del producto final. Hasta nuestros días no existen técnicas de verificación que
aseguren la equivalencia 100 % de un producto de software (considerando un
producto de carácter industrial) respecto de una determinada especificación.
12.2.
Publicaciones impulsadas por esta Tesis
A continuación de indican las publicaciones en las cuales ha participado
el autor y que han sido producto directo del desarrollo de esta Tesis. Estas
han sido agrupados según los objetivos parciales perseguidos y clasificados por
tipo de publicación. También se ha incluido el número de Proyectos de Fin
de Carrera dirigidos por el autor en la Facultad de Informática de la UPV
entre los años 1995 y 1999, los cuales han sido desarrollados en el marco de
esta Tesis. El resumen de publicaciones es el siguiente: 1 libro, 1 artículo en
revista, 9 artículos en congresos, 6 informes técnicos y 21 Proyectos de Fin de
Carrera.
Extensión de OASIS para establecer una proceso de generación automática de prototipos
Libro: “OASIS 3.0: Un enfoque formal para el modelado conceptual orientado a objeto” (1998) [56]. Artículo en revista: “Representación de objetos
en teorías y su traducción a un modelo de concurrencia”(1997) [82]. Artículos
en congresos: “Especificaciones de proceso para objetos y su representación e
Lógica Dinámica” (1998) [55], “Un modelo abstracto de ejecución para especificaciones OASIS 3.0” (1998) [52] y “Modelado conceptual con un lenguaje
formal y orientado a objeto” (1999) [83]. Informes técnicos: “Modelado de la
perspectiva cliente en especificaciones OASIS” (1997) [48] y “Formalización
de OASIS en Lógica Dinámica incluyendo especificaciones de proceso” (1997)
[53].
158
CAPÍTULO 12. CONCLUSIONES
Traducción de OASIS a Programación Lógica Concurrente
Artículos en congresos: “Animation of system specifications using concurrent logic programming” (1997) [51], “Animación de modelos conceptuales
para ayudar en la validación de requisitos” (1997) [50], “Animación de especificaciones OASIS en entornos concurrentes” (1998) [54], “Prototyping a Requirements Specification Through an Automatically Generated Concurrent Logic
Program” (1999) [57] y “Animation of Conceptuals Models using two Concurrent Environments: An overview”(1999) [59]. Informes técnicos: “Conceptos básicos de OASIS implementados en Programación Lógica Concurrente”
(1996) [46] y “Guías para la generación automática de un programa lógico concurrente que sirve de prototipo para una especificación OASIS” (1997) [49].
Proyectos de Fin de Carrera: 5.
Construcción de un ambiente para validación y especificación incremental de especificaciones OASIS
Artículos en congresos: “Un ambiente para especificación incremental y
validación de modelos conceptuales (1999) [58]. Informes técnicos: “Un metamodelo estático para especificaciones OASIS y su implementación en una base
de datos relacional (1996) [47] y “Un modelo estático para especificaciones
OASIS 3.0 y su implementación en una base de datos relacional (1999) [77].
Proyectos de Fin de Carrera: 16.
Apéndice A
Ejemplos en PARLOG
En este apéndice se presentan dos ejemplos que ilustran con mayor detalle
cómo clases y objetos pueden ser implementados utilizando Programación Lógica Concurrente. Los ejemplos han sido desarrollados utilizando PARLOG.
A.1.
Pequeña biblioteca
Se modelan tres clases: usuario, libro y lector. Para este ejemplo, sólo
los objetos de la clase usuario son activos (requieren servicios), los objetos de
las clases libro y lector son pasivos (sólo proveen servicios). Debido a que el
número de objetos libro y lector no es fijo, las clases libro y lector son
implementadas como objetos que proveen el servicio new asociado a la creación
de objetos o_libro y o_lector, respectivamente. La Figura A.1 ilustra el
esquema del problema. Se optó por establecer un broadcast de mensajes desde
el objeto usuario hacia los objetos lector, libro, o_lector y o_libro, los
servicios desconocidos para un objeto son simplemente ignorados. Los eventos
de consulta se establecieron mediante mensajes incompletos. La solución utiliza
el enfoque deductivo para establecer el estado de los objetos en un instante
determinado. El objetivo que representa al objeto incluye como argumento la
traza de eventos relevantes que acontecen. Así, para obtener el valor de cada
atributo del objeto existe un predicado que procesa la traza del objeto.
Los servicios implementados son los siguientes:
new_libro(Key,Autor,Anno): Crea objeto o_libro.
new_lector(Key,Direccion,Fono): Crea objeto o_lector.
prestar(Lector,Libro): Registra un préstamo, evento compartido por
objetos o_lector y o_libro.
159
160
APÉNDICE A. EJEMPLOS EN PARLOG
...
devolver
prestar
np
disponible
destroy
o libro
new_libro
libro
usuario
new_lector
devolver
prestar
npc
pc
npv
pv
lector
o-lector
...
Figura A.1: Esquema de comunicación en la pequeña biblioteca
devolver(Lector,Libro): Registra una devolución, evento compartido
por objetos o_lector y o_libro.
np(Key,Num): Obtiene Num, el número de préstamos del libro del objeto.
disponible(Key,Resp): Obtiene Resp, valor que representa si está o no
prestado el libro.
destroy(Key): Destruye el objeto cuyo mecanismo de identificación tiene
el valor Key.
npc(Key,Num): Obtiene Num, el número de préstamos concedidos al lector.
pc(Key,Prestamos): Obtiene Prestamos, una lista con los préstamos
concedidos al lector.
npv(Key,Num): Obtiene Num, el número de préstamos vigentes del lector.
pv(Key,Prestamos): Obtiene Prestamos, una lista con los préstamos
vigentes del lector.
A.1. PEQUEÑA BIBLIOTECA
161
En cada servicio, Key representa el atributo utilizado para identificar al
objeto. A continuación se muestra un ejemplo de ejecución del sistema pequeña
biblioteca.
| ?- usuario(X),libro(X),lector(X).
>new_lector(juan,valencia,111).
new_lector(juan,valencia,111)
>npc(juan,N).
npc(juan,0)
>new_lector(pedro,madrid,555).
new_lector(pedro,madrid,555)
>new_libro(parlog,conlon,1989).
new_libro(parlog,conlon,1989)
>disponible(parlog,R).
disponible(parlog,si)
>new_libro(bd,date,1992).
new_libro(bd,date,1992)
>prestar(juan,parlog).
prestar(juan,parlog)
>prestar(juan,bd).
prestar(juan,bd)
>npc(juan,N).
npc(juan,2)
>npv(juan,N).
npv(juan,2)
>devolver(juan,parlog).
devolver(juan,parlog)
>disponible(bd,R).
disponible(bd,no)
>disponible(parlog,R).
disponible(parlog,si)
>npv(juan,N).
npv(juan,1)
>pc(juan,L).
pc(juan,[prestar(juan,bd),prestar(juan,parlog)])
>pv(juan,L).
pv(juan,[prestar(juan,bd)])
>prestar(pedro,parlog).
prestar(pedro,parlog)
>np(parlog,N).
np(parlog,2)
>stop.
X = [new_lector(juan,valencia,111),npc(juan,0),
new_lector(pedro,madrid,555),new_libro(parlog,conlon,1989),
disponible(parlog,si),new_libro(bd,date,1992),
prestar(juan,parlog),prestar(juan,bd),npc(juan,2),
npv(juan,2),devolver(juan,parlog),disponible(bd,no),
disponible(parlog,si),npv(juan,1),pc(juan,[prestar(juan,bd),
prestar(juan,parlog)]),pv(juan,[prestar(juan,bd)]),
prestar(pedro,parlog),np(parlog,2)]
yes
| ?-
Como se observa, la animación comienza al establecer el objetivo que contiene los subobjetivos que representan a las clases del sistema. La variable
compartida X implementa la comunicación entre los objetos (y clases), quienes
se comunican instanciando parcialmente dicha variable. Cada vez que se ejecuta un evento de creación (new_libro o new_lector) se lanza un nuevo
subobjetivo asociado al objeto creado.
162
APÉNDICE A. EJEMPLOS EN PARLOG
A continuación se presenta el código PARLOG para las definiciones de las
clases usuario, libro y lector, junto a sus respectivas definiciones para instancias en los predicados o_usuario, o_libro y o_lector, respectivamente.
mode usuario(^).
1 usuario(Salida) <write(’> ’) &
read(Mensaje),
o_usuario(Mensaje,Salida).
mode o_usuario(?,^).
o_usuario(stop,[]);
2 o_usuario(Mensaje,[Mensaje|Salida]) <-
ground(Mensaje) &
write(Mensaje) & nl &
write(’> ’) &
read(Otro_mensaje) &
o_usuario(Otro_mensaje,Salida).
mode libro(?).
3 libro([new_libro(Key,Autor,Anno)|Ins]) <o_libro(Ins,[Key,Autor,Anno,[new(Key,Autor,Anno)]]),
libro(Ins).
libro([]);
4 libro([Desconocido|Ins]) <-
libro(Ins).
5 mode
o_libro(?,?).
o_libro([destroy(Key)|Ins],[Key,Autor,Anno,Traza]).
o_libro([disponible(Key,Resp)|Ins],[Key,Autor,Anno,Traza])
libro_disponible(Traza,Resp),
o_libro(Ins,[Key,Autor,Anno,Traza]).
6
1
o_libro([np(Key,Num)|Ins],[Key,Autor,Anno,Traza])
libro_np(Traza,Num),
o_libro(Ins,[Key,Autor,Anno,Traza]).
<-
<-
El objetivo asociado a la clase usuario se reduce inmediatamente a un objetivo
o_usuario. Esto representa la creación implícita de un objeto usuario. Así, sólo existirá
un objeto usuario durante la animación.
2
La única tarea del objeto usuario es enviar mensajes al sistema instanciando parcialmente
su argumento de salida.
3
El cuerpo de esta cláusula refleja la creación de una instancia de libro.
4
Los mensajes desconocidos son ignorados.
5
Como se observa, se tiene una cláusula para el reconocimiento y ejecución de cada servicio
del objeto. En particular la ejecución del servicio de destrucción (destroy(Key)) no tiene
asociado el relanzamiento del subobjetivo o_libro, con lo cual dicho proceso termina.
6
Se dice que np(Key,Num) es un mensaje incompleto pues Num es una variable no instanciada. En este caso el predicado libro_np(Traza,Num) instanciará Num realizando un
procesamiento de la variable Traza.
A.1. PEQUEÑA BIBLIOTECA
163
o_libro([prestar(Lector,Key)|Ins],[Key,Autor,Anno,Traza]) <o_libro(Ins,[Key,Autor,Anno,[prestar(Lector,Key)|Traza]]).
o_libro([devolver(Lector,Key)|Ins],[Key,Autor,Anno,Traza]) <o_libro(Ins,[Key,Autor,Anno,[devolver(Lector,Key)|Traza]]).
7 o_libro([],[Key,Autor,Anno,Traza]);
o_libro([Desconocido|Ins],[Key,Autor,Anno,Traza])
o_libro(Ins,[Key,Autor,Anno,Traza]).
<-
mode libro_disponible(?,^).
libro_disponible([new(_,_,_)],si).
libro_disponible([devolver(_,_)|Resto],si).
libro_disponible([prestar(_,_)|Resto],no).
mode libro_np(?,^).
libro_np([new(_,_,_)],0).
libro_np([prestar(_,_)|Resto],Num)
Num is Num1 + 1,
libro_np(Resto,Num1);
<-
libro_np([_|Resto],Num) <libro_np(Resto,Num).
8 mode
lector(?).
lector([new_lector(Key,Direccion,Fono)|Ins]) <o_lector(Ins,[Key,Direccion,Fono,[new(Key,Direccion,Fono)]]),
lector(Ins).
lector([]);
lector([Desconocido|Ins])
lector(Ins).
<-
mode o_lector(?,?).
o_lector([destroy(Key)|Ins],[Key,Direccion,Fono,Traza]).
o_lector([npc(Key,Num)|Ins],[Key,Direccion,Fono,Traza])
lector_npc(Traza,Num),
o_lector(Ins,[Key,Direccion,Fono,Traza]).
<-
o_lector([pc(Key,Prestamos)|Ins],[Key,Direccion,Fono,Traza])
lector_pc(Traza,Prestamos),
o_lector(Ins,[Key,Direccion,Fono,Traza]).
<-
7
El fin de la sesión de animación se determina al instanciar totalmente la variable compartida, en este caso, finalizando la lista asociada.
8
La implementación de la clase lector y sus instancias (o_lector) es similar a la explicada
para libro y o_libro.
164
APÉNDICE A. EJEMPLOS EN PARLOG
o_lector([npv(Key,Num)|Ins],[Key,Direccion,Fono,Traza])
lector_npv(Traza,Num),
o_lector(Ins,[Key,Direccion,Fono,Traza]).
<-
o_lector([pv(Key,Prestamos)|Ins],[Key,Direccion,Fono,Traza])
lector_pv(Traza,Prestamos),
o_lector(Ins,[Key,Direccion,Fono,Traza]).
<-
o_lector([prestar(Key,Libro)|Ins],[Key,Direccion,Fono,Traza]) <o_lector(Ins,[Key,Direccion,Fono,[prestar(Key,Libro)|Traza]]).
o_lector([devolver(Key,Libro)|Ins],[Key,Direccion,Fono,Traza]) <o_lector(Ins,[Key,Direccion,Fono,[devolver(Key,Libro)|Traza]]).
o_lector([],[Key,Direccion,Fono,Traza]);
o_lector([Desconocido|Ins],[Key,Direccion,Fono,Traza])
o_lector(Ins,[Key,Direccion,Fono,Traza]).
mode lector_npc(?,^).
lector_npc([new(_,_,_)],0).
lector_npc([prestar(_,_)|Resto],Num)
Num is Num1 + 1,
lector_npc(Resto,Num1);
<-
lector_npc([_|Resto],Num) <lector_npc(Resto,Num).
mode lector_pc(?,^).
lector_pc([new(_,_,_)],[]).
lector_pc([prestar(Key,Libro)|Resto1],
[prestar(Key,Libro)|Resto2])
lector_pc(Resto1,Resto2);
lector_pc([_|Resto1],Resto2) <lector_pc(Resto1,Resto2).
mode lector_npv(?,^).
lector_npv([new(_,_,_)],0).
lector_npv([devolver(_,_)|Resto],Num)
Num is Num1 - 1,
lector_npv(Resto,Num1).
lector_npv([prestar(_,_)|Resto],Num)
Num is Num1 + 1,
lector_npv(Resto,Num1);
lector_npv([_|Resto],Num) <lector_npv(Resto,Num).
mode lector_pv(?,^).
lector_pv([new(_,_,_)],[]);
<-
<-
<-
<-
A.1. PEQUEÑA BIBLIOTECA
lector_pv(Traza,Prestamos_vig) <lector_pc(Traza,Prestamos_con),
lector_quitar_dev(Traza,Prestamos_con,Prestamos_vig).
mode lector_quitar_dev(?,?,^).
lector_quitar_dev([new(_,_,_)],Prestamos_con,Prestamos_con).
lector_quitar_dev([devolver(Key,Libro)|Resto],
Prestamos_con,Prestamos_vig) <lector_sacar_un_prestado(Key,Libro,Prestamos_con,
Prestamos_sin_uno),
lector_quitar_dev(Resto,Prestamos_sin_uno,Prestamos_vig);
lector_quitar_dev([_|Resto],Prestamos_con,Prestamos_vig) <lector_quitar_dev(Resto,Prestamos_con,Prestamos_vig).
mode lector_sacar_un_prestado(?,?,?,^).
lector_sacar_un_prestado(Key,Libro,[],[]);
lector_sacar_un_prestado(Key,Libro,
[prestar(Key,Libro)|Resto1],Resto2) <lector_sacar_un_prestado(Key,Libro,Resto1,Resto2);
lector_sacar_un_prestado(Key,Libro,
[Prestamo|Resto1],[Prestamo|Resto2]) <lector_sacar_un_prestado(Key,Libro,Resto1,Resto2).
165
166
APÉNDICE A. EJEMPLOS EN PARLOG
A.2.
Sistema de control de nivel
La Figura A.2 muestra el esquema del problema. Un controlador debe
actuar abriendo o cerrando la válvula de entrada (Ve) para mantener un nivel
constante de 200 cm en un depósito, el controlador recibe el nivel actual desde
el sensor. La válvula de salida (Vs) tiene un comportamiento aleatorio respecto
de sus aperturas y cierres.
controlador
Ve
Qe = 6000 cm3/s
sensor
200 cm
Vs
200 cm
Qs = 3000 cm3/s
Figura A.2: Esquema del sistema de control de nivel.
controlador
Co2
Co1
abrir
cerrar
nivel
Ve
Ve2
abrir
cerrar
sensor
nivel
abrir
cerrar
Vs
Vs2
Vs1
Mo4
clock
T
Tinicial
monitor
md
random
Figura A.3: Esquema de implementación en PARLOG para el ejemplo.
La Figura A.3 muestra un esquema para la solución en PARLOG, indicán-
A.2. SISTEMA DE CONTROL DE NIVEL
167
dose las clases, canales de comunicación y eventos recibidos a través de dichos
canales. El sensor es simulado calculando la altura según las aperturas y cierres
de las válvulas. El comportamiento aleatorio de la válvula de salida se consigue
utilizando valores aleatorios generados por el objeto random.
Como se verá, para todos los objetos del sistema se utiliza una perspectiva
dinámica, es decir, sus estado se modela como argumentos del objetivo, que
son actualizados en cada reducción. Una excepción la constituyen los objetivos
o_sensor, se simula un sensor real registrando las trazas de aperturas y cierres
de válvulas, calculando con ellas el nivel actual del depósito. A continuación se
presenta una ejecución del sistema. Las columnas indican tiempo (en segundos
desde el comienzo de la ejecución), nivel del depósito, válvula (Ve o Vs) y
evento ocurrido a la válvula. El controlador actúa abriendo o cerrando la
válvula de entrada para mantener el nivel entre 199 y 200 cm.
| ?- control(Co1,Co2),
ve(Co2,Ve2),
vs(Vs1,Vs2),
random(Vs1),
sensor(Co1,Ve2,Vs2,Mo4),
monitor(Ve2,Vs2,T,Mo4),
clock(T).
35 199.0 Vs: abrir
37 198.95 Ve: abrir
65 199.65 Vs: cerrar
72 200.0 Ve: cerrar
78 200.0 Vs: abrir
99 199.475 Vs: cerrar
147 199.475 Vs: abrir
161 199.125 Vs: cerrar
166 199.125 Vs: abrir
172 198.975 Vs: cerrar
175 198.975 Ve: abrir
196 200.025 Ve: cerrar
209 200.025 Vs: abrir
250 199.0 Vs: cerrar
252 199.0 Ve: abrir
262 199.5 Vs: abrir
281 199.975 Vs: cerrar
282 200.025 Ve: cerrar
323 200.025 Vs: abrir
330 199.85 Vs: cerrar
359 199.85 Vs: abrir
389 199.1 Vs: cerrar
406 199.1 Vs: abrir
411 198.975 Ve: abrir
439 199.675 Vs: cerrar
447 200.075 Ve: cerrar
452 200.075 Vs: abrir
498 198.925 Ve: abrir
499 198.95 Vs: cerrar
508 199.4 Vs: abrir
524 199.8 Vs: cerrar
528 200.0 Ve: cerrar
. . .
A continuación se presenta el código PARLOG que implementa el sistema.
Se especifican cláusulas para cada uno de los objetos del esquema solución.
Aunque en este ejemplo no existe creación de objetos en ejecución, siguiendo
el enfoque planteado en el ejemplo anterior, se han implementado las clases
168
APÉNDICE A. EJEMPLOS EN PARLOG
como objetivos que en su primera reducción crean objetivos asociados a cada
uno de los objetos participantes.
mode control(^,^).
control(Sensor,Ve) <o_control([Sensor,Ve]).
mode o_control(?).
o_control([Sensor,Ve]) <clock(Tactual) &
9 Sensor = [nivel(N,Tactual)|Resto1] &
data(N) &
1 0 control_actuar(Ve,Resto2,N) &
sleep(5000) &
o_control([Resto1,Resto2]).
mode control_actuar(^,?,?).
control_actuar(Ve,Resto,N) <N < 199:
Ve = [abrir|Resto].
control_actuar(Ve,Resto,N) <N >= 200:
Ve = [cerrar|Resto];
control_actuar(Ve,Ve,N).
mode monitor(?,?,?,^).
monitor(Ve,Vs,Tinicial,Sensor) <o_monitor([Ve,Vs],Tinicial,Sensor).
mode o_monitor(?,?,^).
1 1 o_monitor([[abrir(T)|Ve],Vs],Tinicial,Sensor)
Sensor = [nivel(N,T)|Resto] &
data(N) &
Tiempo is T - Tinicial &
write(Tiempo) & write(’ ’) & write(N) &
write(’ Ve: abrir’) & nl &
o_monitor([Ve,Vs],Tinicial,Resto).
o_monitor([[cerrar(T)|Ve],Vs],Tinicial,Sensor)
Sensor = [nivel(N,T)|Resto] &
data(N) &
Tiempo is T - Tinicial &
write(Tiempo) & write(’ ’) & write(N) &
write(’ Ve: cerrar’) & nl &
o_monitor([Ve,Vs],Tinicial,Resto).
o_monitor([Ve,[abrir(T)|Vs]],Tinicial,Sensor)
Sensor = [nivel(N,T)|Resto] &
data(N) &
9
<-
<-
<-
El objeto control o_control consulta el nivel al objeto sensor. Para esto se utiliza un
mensaje incompleto nivel(N,Tactual) donde N es una variable no instanciada. Se establece
una sincronización de espera mediante el subobjetivo data(N) el cual suspende hasta que N
sea instanciada.
10
Se determina si se debe abrir o cerrar la válvula de entrada (instanciando la variable
Ve, compartida con el objeto válvula de entrada). Posteriormente el predicado sleep(5000)
implementa una espera que consiste simplemente en ejecutar 5000 reducciones.
11
El objeto monitor o_monitor se encarga de mostrar por pantalla la actividad del sistema,
indicando las aperturas y cierres de cada válvula.
A.2. SISTEMA DE CONTROL DE NIVEL
169
Tiempo is T - Tinicial &
write(Tiempo) & write(’ ’) & write(N) &
write(’ Vs: abrir’) & nl &
o_monitor([Ve,Vs],Tinicial,Resto).
o_monitor([Ve,[cerrar(T)|Vs]],Tinicial,Sensor)
Sensor = [nivel(N,T)|Resto] &
data(N) &
Tiempo is T - Tinicial &
write(Tiempo) & write(’ ’) & write(N) &
write(’ Vs: cerrar’) & nl &
o_monitor([Ve,Vs],Tinicial,Resto).
<-
mode random(?).
random(Vs) <o_random(Vs,13.0).
mode o_random(?,?).
1 2 o_random([rnd(R,N)|Vs],Semilla) <random_gen_n(Semilla,R,N),
random_gen_ns(Semilla,New_Semilla),
o_random(Vs,New_Semilla).
mode random_gen_n(?,?,^).
random_gen_n(S,R,N) <T1 is S mod R &
N is T1 + 1.
mode random_gen_ns(?,^).
random_gen_ns(S,NS) <T1 is 125 * S + 1 &
NS is T1 mod 4096.
mode sensor(?,?,?,?).
sensor(Control,Ve,Vs,Monitor) <o_sensor([Control,Ve,Vs,Monitor],
[199.0,[cierre(ve,0),cierre(vs,0)]]).
mode o_sensor(?,?).
13
o_sensor([[nivel(N,T)|Control],Ve,Vs,Monitor],[Nivel,Traza])
sensor_tpo_ult_ap(ve,Traza,Tiempove),
sensor_cambio_nivel(ve,Tiempove,T,Aumento),
sensor_tpo_ult_ap(vs,Traza,Tiempovs),
sensor_cambio_nivel(vs,Tiempovs,T,Disminucion),
Cambio is Aumento - Disminucion,
N is Nivel + Cambio,
o_sensor([Control,Ve,Vs,Monitor],[Nivel,Traza]).
o_sensor([Control,Ve,Vs,[nivel(N,T)|Monitor]],[Nivel,Traza])
sensor_tpo_ult_ap(ve,Traza,Tiempove),
sensor_cambio_nivel(ve,Tiempove,T,Aumento),
sensor_tpo_ult_ap(vs,Traza,Tiempovs),
sensor_cambio_nivel(vs,Tiempovs,T,Disminucion),
Cambio is Aumento - Disminucion,
N is Nivel + Cambio,
<-
<-
12
El objeto o_random se encarga de generar números aleatorios entre 1 y 999 solicitados
por la válvula de salida para determinar sus aperturas y cierres.
13
El objeto sensor o_sensor calcula el nivel del depósito de acuerdo con las aperturas y
cierres de las válvulas. También informa al objeto o_control respecto del nivel del depósito.
170
APÉNDICE A. EJEMPLOS EN PARLOG
o_sensor([Control,Ve,Vs,Monitor],[Nivel,Traza]).
o_sensor([Control,[abrir(T)|Ve],Vs,Monitor],[Nivel,Traza]) <o_sensor([Control,Ve,Vs,Monitor],[Nivel,[apertura(ve,T)|Traza]]).
o_sensor([Control,[cerrar(T)|Ve],Vs,Monitor],[Nivel,Traza]) <sensor_tpo_ult_ap(ve,Traza,Tiempo),
sensor_cambio_nivel(ve,Tiempo,T,Aumento),
Altura is Nivel + Aumento,
o_sensor([Control,Ve,Vs,Monitor],[Altura,[cierre(ve,T)|Traza]]).
o_sensor([Control,Ve,[abrir(T)|Vs],Monitor],[Nivel,Traza]) <o_sensor([Control,Ve,Vs,Monitor],[Nivel,[apertura(vs,T)|Traza]]).
o_sensor([Control,Ve,[cerrar(T)|Vs],Monitor],[Nivel,Traza]) <sensor_tpo_ult_ap(vs,Traza,Tiempo),
sensor_cambio_nivel(vs,Tiempo,T,Disminucion),
Altura is Nivel - Disminucion,
o_sensor([Control,Ve,Vs,Monitor],[Altura,[cierre(vs,T)|Traza]]).
mode sensor_cambio_nivel(?,?,?,^).
sensor_cambio_nivel(Valvula,0,Tactual,0);
sensor_cambio_nivel(Valvula,Tiempo,Tactual,Cambio) <sensor_caudal(Valvula,Caudal),
Cambio is ((Tactual - Tiempo) * Caudal) / 120000.
mode sensor_tpo_ult_ap(?,?,^).
sensor_tpo_ult_ap(Valvula,[apertura(Valvula,Tiempo)|Resto],Tiempo).
sensor_tpo_ult_ap(Valvula,[cierre(Valvula,Tiempo)|Resto],0);
sensor_tpo_ult_ap(Valvula,[_|Resto],Tiempo) <sensor_tpo_ult_ap(Valvula,Resto,Tiempo).
mode sensor_caudal(?,^).
sensor_caudal(ve,6000).
sensor_caudal(vs,3000).
mode ve(?,^).
ve(Control,Sensor) <o_ve(Control,cerrada,Sensor).
mode o_ve(?,?,?).
1 4 o_ve([abrir|Control],Estado,Sensor) <-
Estado == cerrada:
clock(Tactual) &
Sensor = [abrir(Tactual)|Resto],
o_ve(Control,abierta,Resto).
o_ve([cerrar|Control],Estado,Sensor) <Estado == abierta:
clock(Tactual) &
Sensor = [cerrar(Tactual)|Resto],
o_ve(Control,cerrada,Resto);
14
La válvula de entrada o_ve se abre o cierra según los mensajes que recibe desde el objeto
o_control.
A.2. SISTEMA DE CONTROL DE NIVEL
o_ve([Accion|Control],Estado,Sensor)
o_ve(Control,Estado,Sensor).
171
<-
mode vs(^,^).
vs(Random,Sensor) <o_vs(cerrada,[Random,Sensor]).
mode o_vs(?,?).
1 5 o_vs(cerrada,[Random,Sensor]) <-
Random = [rnd(1000,T1),rnd(1000,T)|Resto1] &
Tiempo is T * 1000 &
sleep(Tiempo) &
clock(Tactual) &
Sensor = [abrir(Tactual)|Resto2] &
o_vs(abierta,[Resto1,Resto2]).
o_vs(abierta,[Random,Sensor]) <Random = [rnd(1000,T)|Resto1] &
Tiempo is T * 1000 &
sleep(Tiempo) &
clock(Tactual) &
Sensor = [cerrar(Tactual)|Resto2] &
o_vs(cerrada,[Resto1,Resto2]).
mode sleep(?).
sleep(N) <N =< 0 : true;
sleep(N) <N1 is N - 10 &
sleep(N1).
15
La válvula de salida espera un tiempo aleatorio determinado por el número entre 1 y
999 que recibe desde el objeto o_random y luego se abre o cierra dependiendo si antes estaba
cerrada o abierta, respectivamente.
172
APÉNDICE A. EJEMPLOS EN PARLOG
Apéndice B
Repositorio OASIS
El repositorio de una herramienta de modelado hace de pivote entre las
diferentes actividades involucradas. Para la herramienta LUNA, el repositorio conecta la edición de la especificación con la generación automática del
prototipo y su animación. Este apéndice describe el repositorio utilizado para
almacenar la especificaciones OASIS 3.0. Actualmente el repositorio está implementado como una base de datos relacional que almacena especificaciones
OASIS.
A continuación se ilustra la estructura actual del repositorio presentando
sólo su modelo conceptual (los aspectos posibles de expresar gráficamente).
Para obtener mayores detalles o conocer el modelo relacional asociado consultar [77]. Se ha optado por utilizar Diagramas de Clases según la notación
UML. Hay que remarcar que la lectura de los diagramas presentados debe hacerse orientada a la sintáxis del lenguaje OASIS, no en una perspectiva pura de
metamodelado. Por otra parte, quizás hubiese sido más razonable presentar
el modelo del repositorio usando la notación Entidad-Relación Extendida más
cercana a lo que estrictamente se quería producir (una base de datos relacional), pero se decidió UML por su aceptación como notación estándar y la
posibilidad de utilizar el repositorio en trabajos posteriores que incorporen el
tratamiento de aspectos dinámicos.
El modelo ha sido organizado en 14 paquetes interrelacionados, los cuales
de muestran a continuación.
173
174
APÉNDICE B. REPOSITORIO OASIS
clase
nombre : string
1
cliente_servidor (from cliente-servidor)
0 ..*
clave_especial : string
1 ..*
0..*
1..*
{or}
interfaz
0..*
1
atributos_todos : char
servicios_todos : char
1 ..*
1
1
esquema_conceptual
0..*
1
1
accion
(from accion)
0..*
relacion (from relacion)
Figura B.1: Paquete “esquema”
disparo
(from disparo)
pr eco ndi ci on
proceso
0..*
(from precondicion)
restriccion
(from protocolo)
n om bre : st ri ng
(from restriccion)
0..*
1
1
0..*
0..*
clase
evaluacion
1
(from clase,interfaz y e_conceptual)
(from evaluacion)
1
0..*
nom bre : string
ev_new
1 {or}
ev_destroy
1
derivacion
(f ro m d eri va cion)
1
0..*
1
1
0 ..*
1
0..*
id ent ifi cad or
(from at ributo e i de ntificador)
nom bre : string
card_m in : char
card_m ax : char
evento
0..1
0..*
atributo
0 ..1
(from servicio, evento, operacion y transaccion)
1
servicio
(from servicio, evento, operacion y transaccion)
(from atributo e identificador)
nom bre : string
nom bre : string
valor_defecto : string
Figura B.2: Paquete “clase”
175
in ter faz
(from clase,int erf az y e_conceptual)
atr ibutos _todos : char
ser vici os_todos : char
0..1
0..1
0..*
0..*
atr ibuto ofertado
ser vicio ofertado
1
0..*
1
cl iente
ser vici o
servi dor
(f rom client e_servidor)
(f rom cliente_servidor)
0..*
atr ibuto
(f rom servicio, event o, operacion y t ransaccion)
nom bre : str ing
(f rom atributo e ident ificador)
nom bre : string
car d_mi n : char
car d_max : char
valo r_defecto : str i ng
Figura B.3: Paquete “interfaz”
c la s e
( fr om c las e,i nter faz y e_c onc eptual)
n o m b re : s t rin g
1
1
0 ..*
d o m i n io
1
1
t ip o a t rib u t o
0..*
0..*
a t rib u t o
n o m b r e : s t rin g
c a rd _ m in : c h a r
c a rd _ m a x : c h a r
v a lo r_ d e f e c t o : s t rin g
0 ..*
id e n t if ic a d o r
n o m b re : s t rin g
re p re s e n t a c io n
ra n g o in f e rio r : s t rin g
ra n g o s u p e rio r : s t r in g
{o r d e n a d a }
c a rd _ m a x > 1
1
1 ..*
0..*
a t r ib u t o m u lt iv a lu a d o
a t rib u t o d e riv a d o
a t rib u t o v a ria b le
a t rib u t o c o n s t a n t e
re p re s e n t a c io n : s t rin g
ra n g o _ in f e rio r : c h a r
ra n g o _ s u p e rio r : c h a r
v a lo r_ d e f e c t o : lis t a (s t rin g )
lis t a _ c a d e n a : lis t a (s t rin g )
Figura B.4: Paquete “atributo e identificador”
0 ..*
176
APÉNDICE B. REPOSITORIO OASIS
c la se
(from clase,interfaz y e_conceptual)
nom bre : s t ring
arg um en to
1
{ordenado}
0..*
se rv ic io
1
0. .*
nom bre : s tring
dom inio
tipo
(from argum ento)
nom bre : s tr ing
nro_ ord en : nat 0..*
(from atributo e identificador)
1
0..1
1
proc es o
(from protocolo)
nom bre : s tring
0..*
ev ento
alias _f or
op era cion
1
0..1
1
0.. *
trans ac c ion
param etro_alias _f or
ev ento_c all_s hare
0.. *
ev ento new
ev ento des troy
1
c all_s hare
1.. *
0 . .*
1
0..*
param etro_c all_s hare
1
ev ento _c all
e v e nto_s hare
s erv idor
(fr om cliente _servi dor)
Figura B.5: Paquete “servicio, proceso y parámetro”
clase
(fr om cl ase,i nter faz y e_
nom bre : st ring
1
0 . .*
ev a lu ac ion
1
1
0. .1
c ondic io n ev alu ac ion
0 . .1
1
a c c ion
1
a sig nac ion e v aluac ion
( from accion)
Figura B.6: Paquete “evaluaciones”
177
clas e
( from clase,inter faz y e_c onceptual)
n om b re : s tring
1
0. . *
de riv acio n
1
1
1
0. . 1
co nd ic ion deriv a ci on
asig nacion deriv a cion
Figura B.7: Paquete “derivaciones”
clase
(fr om c lase,i nter faz y e_conceptual )
nom bre : stri ng
1
0..*
pr econdicion
1
1
con dicion pr econdi ci on
0..*
1
accion
( fr om acci on)
Figura B.8: Paquete “precondiciones”
178
APÉNDICE B. REPOSITORIO OASIS
c las e
( fr om cl ase,interfaz y e_conceptual)
nom b re : s t ring
1
0. . *
dis pa ro
1
0. . *
1
1
a c c ion
c o ndic ion dis paro
( from accion)
Figura B.9: Paquete “disparos”
clase
(fro m clase,interfaz y e_conceptual)
nom bre : str ing
1
0..*
a rgum ento
{ordenado}
(from argum ento)
nom bre : string
nro_orden : nat
estado
proceso
nom bre : string
nom bre : string
0..*
1..*
1
0..1
1
0..1
estado fuente
estado destino
0..*
0..*
transicion
r elacion de m igracion
(from P : Herencia)
1
0..1
1
guarda
0..*
param etro operacion
servicio
(from servicio, evento, operacion y transaccion)
nom bre : string
0..*
protocolo
operacion
(from servicio, evento, operacion y transaccion)
transaccion
(from servi ci o, ev en to, op eracio n y tra ns acc o
i n)
Figura B.10: Paquete “procesos”
1
accion
(from accion)
179
clase
esq uema_conceptual
(from clase,int erfaz y e_conceptual)
(from clase,int erfaz y e_conceptual)
nom br e : stri ng
1
1
1..*
0..*
{ ordenado}
cli ente_ser vi dor
param etr o_identificador
cl ave_especial : str ing
0..1
0..*
0..*
0..1
cliente
1
identificador
(from at ributo e identif icador)
ser vidor
1
1
1
nom bre : stri ng
1
0..*
0..*
0..*
acci on
0..*
call_shar e
0..*
(from servicio, event o, operacion y transaccion)
i nter faz
(f rom accion)
(from clase,int erfaz y e_concept ual)
atributos_todos : char
ser vi cios_todos : char
Figura B.11: Paquete “cliente-servidor”
es quem a _c on c ept u al
(fr om cl ase,inter faz y e_c onceptual)
1
0 .. *
0. .*
1
clie nte
a cc ion
1
0. . *
param e tro acc io n
0. . *
( fr om clie nte_ser vido r)
1
0. .*
1
s erv idor
( fr om c liente_ser vidor)
s erv ic io
(fr om ser vici o, evento , oper aci on y tr ansacci on)
n om bre : s t ring
Figura B.12: Paquete “acciones”
180
APÉNDICE B. REPOSITORIO OASIS
esquem a_conceptual
relacion
0..*
1
(from clase, int erfaz y e_concept ual)
herencia
agr egacion
alias_com ponente : string
card_m in_agregacion : char
card_m ax_agregacion : char
card_m in_com ponente : char
card_m ax_com ponente : char
lista_cadena_com ponentes : lista(string)
lista_cadena_com puestas : lista(string)
P : H erencia
P : Agregacion
Figura B.13: Paquete “relaciones”
rela cion
(from relacion)
represent acion componente
compuest a
1
0.. *
c lase
(f rom clase,int erfaz y e_concept ual)
ag rega cio n
0.. *
(from relacion)
n omb re : st rin g
1.. *
0..*
componente
agregacion inclusiva
1
a ila s_componen te : strin g
car d_min_agreg acion : char
c ar d_ m ax _a gr eg acio n : ch ar
card_min_component e : char
c ar d_ m ax_compone nte : char
list a_cadena_co mponent es : list a(st ring)
list a _ca de na _c ompu es ta s : li st a( str n
i g)
ag re ga ci on rela cion al
repr es en ta cion
(from atributo e identif icador)
rango inferior : string
r an go s up er ior : strin g
r eprese nt ac ion c omp ues t a
1
0. .*
agregaci on d n
i amic a
agregacion est at ica
card_max_componente > 1
grouping by
asociacion
condicion asociacion
0.. 1
1
0.. *
Figura B.14: Paquete “agregacion”
1. .*
atribut o
(from at ributo e ident ificador)
n omb re : st rin g
c ar d_ m in : ch ar
card_max : char
val or _d ef ec to : st rin g
181
relac ion
(from relacion)
s ubc las e
c las e
herenc ia
0.. *
(from relacion)
0. . *
1. .* (from clase,interfaz y e_
nom bre : s t ring
1
s uperc las e
rol
partic ion
0. .*
1. .*
par t ic ion es tatica
s erv ic io
partic ion dinam ic a
(from servicio, evento, operacion y transaccion)
nom bre : s t ring
part ic ion dinam ic a ev ento
par tic ion di nam ic a at ri bu to
1
1
1.. *
1
rel aci on de m igra ci on
c ondic ion es pec ializac ion
Figura B.15: Paquete “herencia”
182
APÉNDICE B. REPOSITORIO OASIS
fbf
0..1
op_izquierdo
0..1
0..1
op_derecho
0..1
operador : string
atom o
1
operador
1
0..1
1
1
fbf tem poral
tim eout : string
delay : string
unidad_tem p : string
op_der echo
op_izquierdo
op_derecho
1
1
argum ento funcion {ordenado}
term ino
0..1
op_ izquierdo
0..1
0..*
0.. 1
Am bito Form ula
0..1
funcion
argum ento
constan te
atributo
(f rom argu ment o)
nom bre : string
nro_orden : nat
(f rom at ribut o e ident if icador)
nom bre : string
card_m in : char
card_m ax : char
valor_defecto : string
Figura B.16: Paquete “fórmula”
f bf
fbf t em poral
(from f orm ula)
operador : st ring
(from f orm ula)
t im eout : string
delay : string
unidad_t em p : string
rest riccion dinam ica
(f rom restriccion)
condicion evaluacion
(f rom evaluacion)
condicion especializacion
(f ro m P : Her en ci a)
condicion derivacion
asignacion derivacion
(from derivacion)
asignacion evaluacion
(from evaluacion)
(f rom derivacion)
guarda
(from protocolo)
condicion disparo
(from disparo)
condicion precondicion
(from precondicion)
restricc o
i n estatic a
(from restriccion)
Figura B.17: Paquete “ámbito fórmula”
condicion asociacion
(from P : Agregacion)
183
term ino
(from form ula)
para metro
nr o_o rde n : na t
param etro_identificador
param etro accion
(from cliente_servidor)
(from accion)
param etro_alias_for
param etro_call_share
(from servicio, evento, operacion y transaccion)
(from servicio, evento, operacion y transaccion)
param etro operacion
(from protocolo)
Figura B.18: Paquete “parámetros”
184
APÉNDICE B. REPOSITORIO OASIS
Apéndice C
Plantillas para generar KL1
En este apéndice se presentan las plantillas establecidas para la generación
de código KL1 a partir del repositorio OASIS. Se presentarán algunos de los
predicados y cláusulas que dependen de la información del repositorio, es decir,
aquellos que varían de un sistema a otro. Las plantillas completas, incluyendo
los predicados de librería y sus respectivas cláusulas pueden consultarse en
[49].
Notación utilizada
Información extraida desde el repositorio (considerando que las
mayúsculas, cuando se usan, son significativas).
inicio/fin de constructor estructurado .
comentario.
C.1.
Cláusulas para predicados main y router
El predicado main permite arrancar el sistema estableciendo como submetas las clases del sistema y un objeto de la clase user que desempeñará
el papel del analista. El predicado router encamina las acciones desde los
clientes a los servidores.
:- module main.
main :take_active_actions(ActiveActions),
UserActions=[action(c(tester),s(user),e(add,[att(userid,root)]))
|RestUserActions],
c_user(UserActions,UserTriggers,[att(population,[])]),
PARA CADA CLASE
c_clase(ClaseActions,ClaseTriggers,[att(population,[])]),
FIN PARA
generic:new(merge,{ActiveActions,UserTriggers,
185
186
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
PARA CADA CLASE
ClaseTriggers
separa r con “,” si hay m ás de u na
},Actions),
router(Actions,RestUserActions,
PARA CADA CLASE
ClaseActions
separar
FIN PARA
)@lower_priority.
con “,” si hay m ás de una
%****************************************************************************
% router
%****************************************************************************
PARA CADA CLASE
router([action(this,s(clase,id(Id,Value)),e(Server,Event))|RestActions],
PARA CADA CLASE
ClaseActions
separar con “,” si hay m ás de u na
FIN PARA
) :ClaseActions=[action(this,s(clase,id(Id,Value)),e(Server,Event))
|RestClaseActions],
router(RestActions,
PARA CADA CLASE
SI es la clase del bucle externo ENTONCES
RestClaseActions
separar con “,” si queda algu na
SINO
ClaseActions
separar con “,” si queda algu na clase
FIN SI
clase
FIN PARA
)@lower_priority.
FIN PARA
router([action(Client,s(society,everyone),e(stop,[]))|RestActions],
PARA CADA CLASE
ClaseActions
separar con “,” si hay m ás de u na
FIN PARA
) :PARA CADA CLASE
ClaseActions=[action(Client,s(society,everyone),e(stop,[]))]
separar con “,” si queda una c lase, poner u n “.” despu és de la ú ltim a
FIN PARA
PARA CADA CLASE
router([action(Client,s(clase),Event)|RestActions],
PARA CADA CLASE
ClaseActions
separar con “,” si hay m ás de u na
FIN PARA
) :ClaseActions=[action(Client,s(clase),Event)|RestClaseActions],
router(RestActions,
PARA CADA CLASE
SI es la clase del bucle externo ENTONCES
RestClaseActions
separar con “,” si queda algu na
SINO
ClaseActions
separar con “,” si queda algu na clase
FIN SI
FIN PARA
)@lower_priority.
FIN PARA
clase
C.1. CLÁUSULAS PARA PREDICADOS MAIN Y ROUTER
PARA CADA CLASE
router([action(Client,s(clase,everyone),Event)|RestActions],
PARA CADA CLASE
ClaseActions
separar con “,” si hay m ás de u na
FIN PARA
) :ClaseActions=[action(Client,s(clase,everyone),Event)|RestClaseActions],
router(RestActions,
PARA CADA CLASE
SI es la clase del bucle externo ENTONCES
RestClaseActions
separar con “,” si queda algu na
SINO
ClaseActions
separar con “,” si queda algu na clase
FIN SI
clase
FIN PARA
)@lower_priority.
FIN PARA
PARA CADA CLASE
router([action(Client,s(clase,id(Id,Value)),Event)|RestActions],
PARA CADA CLASE
ClaseActions
separar con “,” si hay m ás de u na
FIN PARA
) :ClaseActions=[action(Client,s(clase,id(Id,Value)),Event)|RestClaseActions],
router(RestActions,
PARA CADA CLASE
S I es la clas e d el b u cle ex tern o E N T O N C E S
RestClaseActions
separar con “,” si queda algu na clase
S IN O
ClaseActions
separar con “,” si queda algu na clase
F IN S I
FIN PARA
)@lower_priority.
FIN PARA
otherwise.
router([Action|RestActions],
PARA CADA CLASE
ClaseActions
separar
FIN PARA
) :print_test_router(Action),
router(RestActions,
PARA CADA CLASE
ClaseActions
separar
FIN PARA
)@lower_priority.
con “,” si hay m ás de u na
con “,” si hay m ás de u na
187
188
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
C.1.1.
Ejemplo: Código generado para los predicados main y
router en el sistema bancario
:- module main.
1 main :take_active_actions(ActiveActions),
UserActions=[action(c(tester),s(user),e(add,[att(userid,root)]))
|RestUserActions],
c_user(UserActions,UserTriggers,[att(population,[])]),
c_account(AccountActions,AccountTriggers,[att(population,[])]),
c_customer(CustomerActions,CustomerTriggers,[att(population,[])]),
generic:new(merge,{ActiveActions,UserTriggers,
AccountTriggers,CustomerTriggers},Actions),
router(Actions,RestUserActions,AccountActions,CustomerActions)@lower_priority.
%****************************************************************************
% router
%****************************************************************************
2 router([action(this,s(user,id(Id,Value)),e(Server,Event))|RestActions],
UserActions,AccountActions,CustomerActions) :UserActions=[action(this,s(user,id(Id,Value)),e(Server,Event))
|RestUserActions],
router(RestActions,RestUserActions,AccountActions,CustomerActions
)@lower_priority.
router([action(this,s(account,id(Id,Value)),e(Server,Event))|RestActions],
UserActions,AccountActions,CustomerActions) :AccountActions=[action(this,s(account,id(Id,Value)),e(Server,Event))
|RestAccountActions],
router(RestActions,UserActions,RestAccountActions,CustomerActions
)@lower_priority.
router([action(this,s(customer,id(Id,Value)),e(Server,Event))|RestActions],
UserActions,AccountActions,CustomerActions) :CustomerActions=[action(this,s(customer,id(Id,Value)),e(Server,Event))
|RestCustomerActions],
router(RestActions,UserActions,AccountActions,RestCustomerActions
)@lower_priority.
3 router([action(Client,s(society,everyone),e(stop,[]))|RestActions],
UserActions,AccountActions,CustomerActions) :UserActions=[action(Client,s(society,everyone),e(stop,[]))],
AccountActions=[action(Client,s(society,everyone),e(stop,[]))],
CustomerActions=[action(Client,s(society,everyone),e(stop,[]))].
4 router([action(Client,s(user),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :UserActions=[action(Client,s(user),Event)|RestUserActions],
router(RestActions,RestUserActions,AccountActions,CustomerActions
)@lower_priority.
1
El predicado main arranca la sesión de animación. Inmediatamente es creada la ínica
instancia de usuario, que representa al analista y se encarga de introducir al sistema las
acciones que éste genere a través de la interfaz de animación. Además se lanzan los subobjetivos que representan a cada una de las clases del sistema estableciendo la configuración
de comunicación. El subobjetivo router se encarga de distribuir todas las acciones hacia las
clases correspondientes.
2
Las tres siguientes cláusulas distribuyen las acciones que el analista introduce desempeñando el papel de algún objeto activo.
3
Esta cláusula se utiliza para distribuir la acción de término de la animación a todas las
clases y objetos del sistema.
4
Las tres siguientes cláusulas distribuyen las acciones dirigidas a cada una de las clases.
C.1. CLÁUSULAS PARA PREDICADOS MAIN Y ROUTER
189
router([action(Client,s(account),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :AccountActions=[action(Client,s(account),Event)|RestAccountActions],
router(RestActions,UserActions,RestAccountActions,CustomerActions
)@lower_priority.
router([action(Client,s(customer),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :CustomerActions=[action(Client,s(customer),Event)|RestCustomerActions],
router(RestActions,UserActions,AccountActions,RestCustomerActions
)@lower_priority.
5 router([action(Client,s(user,everyone),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :UserActions=[action(Client,s(user,everyone),Event)|RestUserActions],
router(RestActions,RestUserActions,AccountActions,CustomerActions
)@lower_priority.
router([action(Client,s(account,everyone),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :AccountActions=[action(Client,s(account,everyone),Event)|RestAccountActions],
router(RestActions,UserActions,RestAccountActions,CustomerActions
)@lower_priority.
router([action(Client,s(customer,everyone),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :CustomerActions=[action(Client,s(customer,everyone),Event)
|RestCustomerActions],
router(RestActions,UserActions,AccountActions,RestCustomerActions
)@lower_priority.
6 router([action(Client,s(user,id(Id,Value)),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :UserActions=[action(Client,s(user,id(Id,Value)),Event)|RestUserActions],
router(RestActions,RestUserActions,AccountActions,CustomerActions
)@lower_priority.
router([action(Client,s(account,id(Id,Value)),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :AccountActions=[action(Client,s(account,id(Id,Value)),Event)
|RestAccountActions],
router(RestActions,UserActions,RestAccountActions,CustomerActions
)@lower_priority.
router([action(Client,s(customer,id(Id,Value)),Event)|RestActions],
UserActions,AccountActions,CustomerActions) :CustomerActions=[action(Client,s(customer,id(Id,Value)),Event)
|RestCustomerActions],
router(RestActions,UserActions,AccountActions,RestCustomerActions
)@lower_priority.
otherwise.
router([Action|RestActions],UserActions,AccountActions,CustomerActions) :print_test_router(Action),
router(RestActions,UserActions,AccountActions,CustomerActions)@lower_priority.
5
Las tres siguientes cláusulas distribuyen las acciones enviadas en broadcast a todos los
objetos de una clase.
6
Las tres siguientes cláusulas distribuyen las acciones enviadas a objetos específicos en
alguna de las clases.
190
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
C.2.
Cláusulas por cada clase
Para cada clase del sistema (incluyendo la clase user) se generan los predicados c_clase y o_clase que permiten reducir los objetivos que representan a la
clase y a sus instancias, respectivamente. A continuación se presenta la plantilla para el predicado c_clase y una pequeña parte de la plantilla del predicado
o_clase. Como se verá, ambas plantillas son similares pues el tratamiento de
objetos (procesos en ejecución) es homogéneo, sean estos clases o instancias.
Sin embargo, la plantilla para el predicado o_clase es más simple y reducida porque la única acción que maneja una clase en ejecución es la acción de
creación de objetos.
C.2.1.
Cláusulas para el predicado c_clase
%***************************************************************************
% clase
%**************************************************************************
c_clase(Actions,Triggers,State) :7
Conflicts=[conflict(evento new,[evento new])],
8 TClassClase:=100000,
clock(Stop,TClassClase,TickActions),
generic:new(merge,{TickActions,Actions},Mbox),
c_clase(TickActions,Stop,Mbox,Triggers,Conflicts,State,null)@lower_priority.
c_clase(TickActions,true,Mbox,Triggers,Conflicts,State,OldState).
alternatively.
9
c_clase([TickAction|RestTickActions],Stop,Mbox,Triggers,Conflicts,
State,OldState) :1 0 wait(TickAction) |
This=c(clase),
extract(This,Mbox,RestMbox,TriggerActions,Services),
get_object_actions(Services,ObjectActions,ServiceActions),
send_object_actions(ObjectActions,State,NState,RejectedObjectActions),
check_clase_conditions(ServiceActions,State,AcceptedActions,
RejectedClassActions),
concat_triggers(RejectedObjectActions,RejectedClassActions,
TriggerActions,NTriggerActions),
select_actions(Conflicts,NTriggerActions,AcceptedActions,ExecutedActions,
ConflictActions),
calculate_clase_new_state(ExecutedActions,NState,NNState,Triggers,
NTriggers,Stop),
send_triggers(This,NTriggerActions,NTriggers,RestTriggers),
7
Se establecen los conflictos. Para el caso de una clase cuyo único evento es el de creación,
sólo tiene conflicto consigo mismo.
8
Se establece la frecuencia de los ticks en la vida de una clase. Se ha utilizado por defecto
100.000 microsegundos tanto para las clases como para sus instancias. En futuras versiones
este parámetro podría ser establecido desde la interfaz de animación para ejercitar con distintas velocidades de trabajo de los objetos, permitiendo acumulación de acciones a ser
procesadas.
9
En el cuerpo de esta cláusula se implementa el modelo de ejecución que controla la vida
de cada clase y objeto. Esto se comentará en más detalle sobre el ejemplo que se presenta
más adelante.
10
El objeto se reduce sólo cuando al menos se ha alcanzado el siguiente tick.
C.2. CLÁUSULAS POR CADA CLASE
191
calculate_new_clase_triggers(NNState,MboxTriggers),
calculate_next_mbox(RestMbox,MboxTriggers,ConflictActions,NextMbox),
print_test_class(This,TickAction,NTriggerActions,ServiceActions,
ConflictActions,ExecutedActions,State,OldState),
c_clase(RestTickActions,Stop,NextMbox,RestTriggers,Conflicts,
NNState,State)@lower_priority.
%**************************************************************************
% check_clase_conditions
%**************************************************************************
check_clase_conditions([],State,AcceptedActions,RejectedActions) :AcceptedActions=[],
RejectedActions=[].
check_clase_conditions([Action|RestActions],State,AcceptedActions,
RejectedActions) :check_one_clase_condition(Action,State,Result,Msg),
check_action(Result,Msg,Action,AcceptedActions,RestAcceptedActions,
RejectedActions,RestRejectedActions),
check_clase_conditions(RestActions,State,RestAcceptedActions,
RestRejectedActions)@lower_priority.
%**************************************************************************
% check_one_clase_condition
%**************************************************************************
1 1 check_one_clase_condition(action(Client,This,e(evento new,Attributes)),State,
Result,Msg) :get_attributes(Attributes,[
PARA CADA ATRIBUTO DEL IDENTIFICADOR
att(atributo,Atributo)
poner “,” si q uedan m ás
F IN PARA
])
get_attributes(State,[att(population,Population)]),
get_oid(Found,Population,id(identificador,[
PARA CADA ATRIBUTO DEL IDENTIFICADOR
att(atributo,Atributo)
poner “,” si q uedan m ás
F IN PARA
]),OidObject),
change_result(Found,Result),
Msg=object_exists.
check_one_clase_condition(action(Client,Server1,e(Server2,e(Event,Args))),
State,Result,Msg) :Result=true,
Msg=nothing.
check_one_clase_condition(action(Client,This,e(tick,[I,T])),State,Result,Msg) :Result=true,
Msg=nothing.
check_one_clase_condition(action(Client,This,e(rejected,Action)),State,
Result,Msg) :Result=true,
Msg=nothing.
check_one_clase_condition(action(Client,s(society,everyone),e(stop,[])),
State,Result,Msg) :Result=true,
Msg=nothing.
11
Esta cláusula verificará los permisos (prohibiciones) para el evento de creación.
192
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
otherwise.
check_one_clase_condition(action(Client,This,Event),State,Result,Msg) :Result=false,
Msg=service_unknown.
%**************************************************************************
% calculate_clase_new_state
%**************************************************************************
calculate_clase_new_state(ExecutedActions,State,NState,Triggers,NTriggers,
Stop) :(wait(ExecutedActions);wait(State)) |
verify_stop(ExecutedActions,Stop),
execute_clase_actions(ExecutedActions,State,NState,Triggers,NTriggers).
%**************************************************************************
% execute_clase_actions
%**************************************************************************
execute_clase_actions([],State,NState,Triggers,NTriggers) :NState=State,
NTriggers=Triggers.
execute_clase_actions([Action|RestActions],State,NNState,Triggers,NNTriggers) :execute_one_clase_action(Action,State,NState,Triggers,NTriggers),
execute_clase_actions(RestActions,NState,NNState,NTriggers,
NNTriggers)@lower_priority.
%**************************************************************************
% execute_one_clase_action
%**************************************************************************
1 2 execute_one_clase_action(action(Client,s(clase),e(evento_new,Attributes)),State,
NState,Triggers,NTriggers) :get_attributes(State,[att(population,Population)]),
Triggers={NTriggers,ObjectTriggers},
get_attributes(Attributes,[
PARA CADA ATRIBUTO USADO EN DERIVACION
att(atributo,Atributo)
poner “,” si q uedan m ás
F IN PARA
]),
PARA CADA ATRIBUTO DERIVADO
SI ATRIBUTO DERIVADO ES BOOLEAN
Atributo derivado := expresión de derivación,
SINO
ExpIzq := expresión izquierda,
ExpDer := expresión derecha,
test_condition([[c(operador relacional,ExpIzq,ExpDer)]],Atributo derivado),
FIN SI
concat(Attributes,[att(atributo derivado,Atributo derivado)],NAttributes),
1 3 o_clase([action(Client,s(clase),e(evento new,Attributes))|Oid],ObjectTriggers,
[att(destroy,false)|NAttributes]),
get_attributes(NAttributes,[
PARA CADA ATRIBUTO DEL IDENTIFICADOR
att(atributo,Atributo)
poner “,” si q uedan m ás
F IN PARA
]),
NPopulation=[object(Oid,[id(identificador,[
PARA CADA ATRIBUTO DEL IDENTIFICADOR
att(atributo,Atributo)
poner “,” si q uedan m ás
F IN PARA
12
13
Esta cláusula ejecuta la acción de creación de un objeto.
Este subobjetivo representa al objeto creado.
C.2. CLÁUSULAS POR CADA CLASE
193
])])|Population],
update_state(State,[chg(population,NPopulation)],NState).
otherwise.
execute_one_clase_action(action(Client,This,Event),State,NState,Triggers,
NTriggers) :NState=State,
NTriggers=Triggers.
%**************************************************************************
% calculate_new_clase_triggers
%**************************************************************************
calculate_new_clase_triggers(State,Triggers) :wait(State) |
verify_clase_triggers([],State,Triggers).
%**************************************************************************
% verify_clase_triggers
%**************************************************************************
verify_clase_triggers([],State,Triggers) :Triggers=[].
C.2.2.
Cláusulas para el predicado o_clase
En esta parte de la plantilla no se incluyen las cláusulas específicas para
el tratamiento de evaluaciones ni de disparos. Consultar en [49] por dichos
aspectos.
%***************************************************************************
% o_clase
%**************************************************************************
o_clase(Actions,Triggers,State) :Conflicts=[
PARA CADA SERVICIO
conflict(servicio,[
Lista de servicios que afectan a un conjunto no disjunto de atributos
respecto del servicio analizado. Si el servicio analizado es el new o
destroy, incluir todos los servicios
])
poner “,” si qued an m ás servicios
FIN PARA
],
TObjectClase:=100000,
clock(Stop,TObjectClase,TickActions),
generic:new(merge,{TickActions,Actions},Mbox),
o_clase(TickActions,Stop,Mbox,Triggers,Conflicts,State,null)@lower_priority.
o_clase(TickActions,true,Mbox,Triggers,Conflicts,State,OldState).
alternatively.
o_clase([TickAction|RestTickActions],Stop,Mbox,Triggers,Conflicts,State,
OldState) :wait(TickAction) |
get_attributes(State,[
PARA CADA ATRIBUTO DEL IDENTIFICADOR
att(atributo,Atributo)
poner “,” si q uedan m ás
F IN PARA
]),
This=c(clase,id(identificador,[
PARA CADA ATRIBUTO DEL IDENTIFICADOR
194
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
att(atributo,Atributo)
poner “,” si q uedan m ás
PARA
])),
extract(This,Mbox,RestMbox,TriggerActions,ServiceActions),
check_o_clase_conditions(ServiceActions,State,AcceptedActions,
RejectedActions),
concat(RejectedActions,TriggerActions,NTriggerActions),
select_actions(Conflicts,NTriggerActions,AcceptedActions,
ExecutedActions,ConflictActions),
calculate_o_clase_new_state(ExecutedActions,State,NState,Stop),
send_triggers(This,NTriggerActions,Triggers,RestTriggers),
calculate_new_o_clase_triggers(NState,MboxTriggers),
calculate_next_mbox(RestMbox,MboxTriggers,ConflictActions,NextMbox),
print_test_object(This,TickAction,NTriggerActions,ServiceActions,
ConflictActions,ExecutedActions,State,OldState),
o_clase(RestTickActions,Stop,NextMbox,RestTriggers,Conflicts,
NState,State)@lower_priority.
F IN
%**************************************************************************
% check_o_clase_conditions
%**************************************************************************
check_o_clase_conditions([],State,AcceptedActions,RejectedActions) :AcceptedActions=[],
RejectedActions=[].
check_o_clase_conditions([Action|RestActions],State,AcceptedActions,
RejectedActions) :check_first_o_clase_condition(Action,State,Result,Msg),
check_action(Result,Msg,Action,AcceptedActions,RestAcceptedActions,
RejectedActions,RestRejectedActions),
check_o_clase_conditions(RestActions,State,RestAcceptedActions,
RestRejectedActions)@lower_priority.
%**************************************************************************
% check_first_o_clase_condition
%**************************************************************************
check_first_o_clase_condition(action(Client,s(society,everyone),e(stop,[])),
State,Result,Msg) :Result=true,
Msg=nothing.
otherwise.
check_first_o_clase_condition(Action,State,Result,Msg) :get_attributes(State,[att(destroy,Destroy)]),
LExp1=Destroy,
RExp1=false,
test_condition([[c(eq,LExp1,RExp1)]],First),
check_one_o_clase_condition(First,Action,State,Result,Msg).
%**************************************************************************
% check_one_o_clase_condition
%**************************************************************************
check_one_o_clase_condition(false,Action,State,Result,Msg) :Result=false,
Msg=object_destroyed.
PARA CADA EVENTO
SI EVENTO TIENE PRECONDICION
check_one_o_clase_condition(true,action(Client,This,e(evento,
[lista parámetros])),State,Result,Msg) :get_attributes(State,[
PARA CADA ATRIBUTO USADO EN LA PRECONDICION
att(pin,Pin)
poner “,” si queda n m ás
FIN PARA
C.2. CLÁUSULAS POR CADA CLASE
195
]),
PARA CADA CONDICION EN LA PRECONDICION
SI UNO DE LOS OPERANDOS ES BOOL
ExpIzqi = expresión izquierda,
ExpDeri = expresión derecha,
SINO
ExpIzqi := expresión izquierda,
ExpDeri := expresión derecha,
FIN SI
FIN PARA
test_condition([
PARA DISYUNCION DE CONDICIONES
[
PARA CONDICION
c(operador relacional,ExpIzqi ,ExpDeri )
poner “,” si q uedan m ás
FIN PARA
]
FIN PARA
],Result),
Msg=not([
PARA DISYUNCION DE CONDICIONES
[
PARA CONDICION
c(operador relacional,ExpIzqi ,ExpDeri )
poner “,” si q uedan m ás
FIN PARA
]
FIN PARA
]).
SINO
check_one_o_clase_condition(true,action(Client,This,e(evento,Args)),
State,Result,Msg) :Result=true,
Msg=nothing.
FIN SI
FIN PARA
check_one_o_clase_condition(true,action(Client,This,e(tick,[I,T])),
State,Result,Msg) :Result=true,
Msg=nothing.
check_one_o_clase_condition(true,action(Client,This,e(rejected,Action)),
State,Result,Msg) :Result=true,
Msg=nothing.
otherwise.
check_one_o_clase_condition(true,action(Client,This,Event),State,Result,Msg) :Result=false,
Msg=service_unknown.
196
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
C.2.3.
Ejemplo: Código generado para los predicado c_account
y o_account en el sistema bancario
%***************************************************************************
% account
%**************************************************************************
c_account(Actions,Triggers,State) :Conflicts=[conflict(open,[open])],
TClassAccount:=100000,
clock(Stop,TClassAccount,TickActions),
generic:new(merge,{TickActions,Actions},Mbox),
c_account(TickActions,Stop,Mbox,Triggers,Conflicts,
State,null)@lower_priority.
c_account(TickActions,true,Mbox,Triggers,Conflicts,State,OldState).
alternatively.
c_account([TickAction|RestTickActions],Stop,Mbox,Triggers,Conflicts,
State,OldState) :wait(TickAction) |
This=c(account),
extract(This,Mbox,RestMbox,TriggerActions,Services),
14
get_object_actions(Services,ObjectActions,ServiceActions),
send_object_actions(ObjectActions,State,NState,RejectedObjectActions),
check_account_conditions(ServiceActions,State,AcceptedActions,
RejectedClassActions),
concat_triggers(RejectedObjectActions,RejectedClassActions,TriggerActions,
NTriggerActions),
select_actions(Conflicts,NTriggerActions,AcceptedActions,
ExecutedActions,ConflictActions),
calculate_account_new_state(ExecutedActions,NState,NNState,Triggers,
NTriggers,Stop),
send_triggers(This,NTriggerActions,NTriggers,RestTriggers),
calculate_new_account_triggers(NNState,MboxTriggers),
calculate_next_mbox(RestMbox,MboxTriggers,ConflictActions,NextMbox),
1 5 print_test_class(This,TickAction,NTriggerActions,ServiceActions,
ConflictActions,ExecutedActions,State,OldState),
c_account(RestTickActions,Stop,NextMbox,RestTriggers,Conflicts,
NNState,State)@lower_priority.
%**************************************************************************
% check_account_conditions
%**************************************************************************
check_account_conditions([],State,AcceptedActions,RejectedActions) :AcceptedActions=[],
RejectedActions=[].
check_account_conditions([Action|RestActions],State,AcceptedActions,
RejectedActions) :check_one_account_condition(Action,State,Result,Msg),
check_action(Result,Msg,Action,AcceptedActions,RestAcceptedActions,
RejectedActions,RestRejectedActions),
check_account_conditions(RestActions,State,RestAcceptedActions,
RestRejectedActions)@lower_priority.
%**************************************************************************
% check_one_account_condition
%**************************************************************************
check_one_account_condition(action(Client,This,e(open,Attributes)),
State,Result,Msg) :get_attributes(Attributes,[att(number,Number)]),
get_attributes(State,[att(population,Population)]),
get_oid(Found,Population,id(number,[att(number,Number)]),OidObject),
14
Este objetivo se encarga de identificar las acciones que van dirigidas a las instancias de
la clase y el siguiente subobjetivo las envía a sus canales de entrada correspondientes.
15
Este objetivo se encarga de informar al entorno de animación que el objeto (en este caso
la clase) ha avanzado un tick en su vida.
C.2. CLÁUSULAS POR CADA CLASE
change_result(Found,Result),
Msg=object_exists.
check_one_account_condition(action(Client,Server1,e(Server2,e(Event,Args))),
State,Result,Msg) :Result=true,
Msg=nothing.
check_one_account_condition(action(Client,This,e(tick,[I,T])),State,
Result,Msg) :Result=true,
Msg=nothing.
check_one_account_condition(action(Client,This,e(rejected,Action)),State,
Result,Msg) :Result=true,
Msg=nothing.
check_one_account_condition(action(Client,s(society,everyone),e(stop,[])),
State,Result,Msg) :Result=true,
Msg=nothing.
otherwise.
check_one_account_condition(action(Client,This,Event),State,Result,Msg) :Result=false,
Msg=service_unknown.
%**************************************************************************
% calculate_account_new_state
%**************************************************************************
calculate_account_new_state(ExecutedActions,State,NState,Triggers,NTriggers,
Stop) :(wait(ExecutedActions);wait(State)) |
verify_stop(ExecutedActions,Stop),
execute_account_actions(ExecutedActions,State,NState,Triggers,NTriggers).
%**************************************************************************
% execute_account_actions
%**************************************************************************
execute_account_actions([],State,NState,Triggers,NTriggers) :NState=State,
NTriggers=Triggers.
execute_account_actions([Action|RestActions],State,NNState,Triggers,
NNTriggers) :execute_one_account_action(Action,State,NState,Triggers,NTriggers),
execute_account_actions(RestActions,NState,NNState,NTriggers,
NNTriggers)@lower_priority.
%**************************************************************************
% execute_one_account_action
%**************************************************************************
execute_one_account_action(action(Client,s(account),e(open,Attributes)),State,
NState,Triggers,NTriggers) :get_attributes(State,[att(population,Population)]),
Triggers={NTriggers,ObjectTriggers},
get_attributes(Attributes,[att(balance,Balance)]),
ExpIzq1:=Balance,
ExpDer1:=100,
test_condition([[c(ge,ExpIzq1,ExpDer1)]],Good_balance),
concat(Attributes,[att(good_balance,Good_balance)],NAttributes),
o_account([action(Client,s(account),e(open,Attributes))|Oid],ObjectTriggers,
[att(destroy,false)|NAttributes]),
get_attributes(NAttributes,[att(number,Number)]),
NPopulation=[object(Oid,[id(number,[att(number,Number)])])|Population],
update_state(State,[chg(population,NPopulation)],NState).
197
198
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
otherwise.
execute_one_account_action(action(Client,This,Event),State,NState,Triggers,
NTriggers) :NState=State,
NTriggers=Triggers.
%**************************************************************************
% calculate_new_account_triggers
%**************************************************************************
calculate_new_account_triggers(State,Triggers) :wait(State) |
verify_account_triggers([],State,Triggers).
%**************************************************************************
% verify_account_triggers
%**************************************************************************
verify_account_triggers([],State,Triggers) :Triggers=[].
%**************************************************************************
% o_account
%**************************************************************************
o_account(Actions,Triggers,State) :1 6 Conflicts=[
conflict(open,[open,close,deposit,withdraw,pay_commission,change_pin,
change_rank])
,conflict(close,[open,close,deposit,withdraw,pay_commission,change_pin,
change_rank])
,conflict(deposit,[open,close,deposit,withdraw,pay_commission])
,conflict(withdraw,[open,close,deposit,withdraw,pay_commission])
,conflict(pay_commission,[open,close,deposit,withdraw,pay_commission])
,conflict(change_pin,[open,close,change_pin])
,conflict(change_rank,[open,close,change_rank])
],
TObjectAccount:=100000,
clock(Stop,TObjectAccount,TickActions),
generic:new(merge,{TickActions,Actions},Mbox),
o_account(TickActions,Stop,Mbox,Triggers,Conflicts,
State,null)@lower_priority.
o_account(TickActions,true,Mbox,Triggers,Conflicts,State,OldState).
alternatively.
o_account([TickAction|RestTickActions],Stop,Mbox,Triggers,Conflicts,State,
OldState) :wait(TickAction) |
get_attributes(State,[att(number,Number)]),
This=c(account,id(number,[att(number,Number)])),
extract(This,Mbox,RestMbox,TriggerActions,ServiceActions),
1 7 check_o_account_conditions(ServiceActions,State,AcceptedActions,
RejectedActions),
concat(RejectedActions,TriggerActions,NTriggerActions),
18
select_actions(Conflicts,NTriggerActions,AcceptedActions,ExecutedActions,
ConflictActions),
1 9 calculate_o_account_new_state(ExecutedActions,State,NState,Stop),
20
send_triggers(This,NTriggerActions,Triggers,RestTriggers),
16
Para cada evento que puede proveer un objeto cuenta se establece una lista de los eventos
que estarían en conflicto, es decir, no se ejecutarán en el mismo instante.
17
Verificación de los permisos (prohibiciones) de cada acción no obligada de proveer.
18
Identificación de las acciones que están en conflicto.
19
Ejecución del paso y obtención del nuevo estado.
20
Envío de acciones a otros objetos, asociadas a obligaciones por satisfacer en el estado
actual.
C.2. CLÁUSULAS POR CADA CLASE
199
2 1 calculate_new_o_account_triggers(NState,MboxTriggers),
2 2 calculate_next_mbox(RestMbox,MboxTriggers,ConflictActions,NextMbox),
print_test_object(This,TickAction,NTriggerActions,ServiceActions,
ConflictActions,ExecutedActions,State,OldState),
o_account(RestTickActions,Stop,NextMbox,RestTriggers,Conflicts,NState,
State)@lower_priority.
%**************************************************************************
% check_o_account_conditions
%**************************************************************************
check_o_account_conditions([],State,AcceptedActions,RejectedActions) :AcceptedActions=[],
RejectedActions=[].
check_o_account_conditions([Action|RestActions],State,AcceptedActions,
RejectedActions) :check_first_o_account_condition(Action,State,Result,Msg),
check_action(Result,Msg,Action,AcceptedActions,RestAcceptedActions,
RejectedActions,RestRejectedActions),
check_o_account_conditions(RestActions,State,RestAcceptedActions,
RestRejectedActions)@lower_priority.
%**************************************************************************
% check_first_o_account_condition
%**************************************************************************
check_first_o_account_condition(action(Client,s(society,everyone),e(stop,[])),
State,Result,Msg) :Result=true,
Msg=nothing.
otherwise.
2 3 check_first_o_account_condition(Action,State,Result,Msg)
:get_attributes(State,[att(destroy,Destroy)]),
LExp1=Destroy,
RExp1=false,
test_condition([[c(eq,LExp1,RExp1)]],First),
check_one_o_account_condition(First,Action,State,Result,Msg).
%**************************************************************************
% check_one_o_account_condition
%**************************************************************************
check_one_o_account_condition(false,Action,State,Result,Msg) :Result=false,
Msg=object_destroyed.
2 4 check_one_o_account_condition(true,action(Client,This,e(withdraw,
[XPin,XAmount])),State,Result,Msg) :get_attributes(State,[att(pin,Pin),att(balance,Balance),att(pin,Pin),
att(balance,Balance),att(rank,Rank)]),
ExpIzq1:=Pin,
ExpDer1:=XPin,
ExpIzq2:=Balance,
ExpDer2:=XAmount,
ExpIzq3:=Pin,
ExpDer3:=XPin,
ExpIzq4:=Balance,
ExpDer4:=XAmount,
ExpIzq5:=Rank,
ExpDer5:=2,
21
Verificar las obligaciones que se satisfarán en el próximo estado alcanzado.
Establecer el próximo buzón, incluyendo las acciones en conflicto no ejecutadas.
23
Se verifica una precondición por defecto que establece que para servir cualquier acción
el objeto no debe estar destruido.
24
Se verifica la precondición: withdraw(Pin,Amount) if {(pin=Pin and balance >=
Amount) or (pin=Pin and balance < Amount and rank=2)}.
22
200
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
test_condition([[c(eq,ExpIzq1,ExpDer1),c(ge,ExpIzq2,ExpDer2)],
[c(eq,ExpIzq3,ExpDer3),c(lt,ExpIzq4,ExpDer4),
c(eq,ExpIzq5,ExpDer5)]],Result),
Msg=not([[c(eq,ExpIzq1,ExpDer1),c(ge,ExpIzq2,ExpDer2)],
[c(eq,ExpIzq3,ExpDer3),c(lt,ExpIzq4,ExpDer4),
c(eq,ExpIzq5,ExpDer5)]]).
25
check_one_o_account_condition(true,action(Client,This,
e(change_pin,[XPin,XNewPin])),State,Result,Msg) :get_attributes(State,[att(pin,Pin)]),
ExpIzq1:=Pin,
ExpDer1:=XPin,
test_condition([[c(eq,ExpIzq1,ExpDer1)]],Result),
Msg=not([[c(eq,ExpIzq1,ExpDer1)]]).
2 6 check_one_o_account_condition(true,action(Client,This,e(close,[])),State,
Result,Msg) :get_attributes(State,[att(balance,Balance)]),
ExpIzq1:=Balance,
ExpDer1:=0,
test_condition([[c(eq,ExpIzq1,ExpDer1)]],Result),
Msg=not([[c(eq,ExpIzq1,ExpDer1)]]).
check_one_o_account_condition(true,action(Client,This,e(open,Args)),State,
Result,Msg) :Result=true,
Msg=nothing.
check_one_o_account_condition(true,action(Client,This,e(deposit,Args)),State,
Result,Msg) :Result=true,
Msg=nothing.
check_one_o_account_condition(true,action(Client,This,e(pay_commission,Args)),
State,Result,Msg) :Result=true,
Msg=nothing.
check_one_o_account_condition(true,action(Client,This,e(change_rank,Args)),
State,Result,Msg) :Result=true,
Msg=nothing.
check_one_o_account_condition(true,action(Client,This,e(tick,[I,T])),State,
Result,Msg) :Result=true,
Msg=nothing.
check_one_o_account_condition(true,action(Client,This,e(rejected,Action)),
State,Result,Msg) :Result=true,
Msg=nothing.
otherwise.
check_one_o_account_condition(true,action(Client,This,Event),State,
Result,Msg) :Result=false,
Msg=service_unknown.
%**************************************************************************
% calculate_o_account_new_state
%**************************************************************************
calculate_o_account_new_state(ExecutedActions,State,NState,Stop) :25
26
Se verifica la precondición: change_pin(Pin,NewPin) if {pin=Pin}.
Se verifica la precondición: close if {balance=0}.
C.2. CLÁUSULAS POR CADA CLASE
201
verify_stop(ExecutedActions,Stop),
execute_o_account_actions(ExecutedActions,State,NState).
execute_o_account_actions([],State,NState) :NState=State.
execute_o_account_actions([Action|RestActions],State,NNState) :execute_one_o_account_action(Action,State,NState),
execute_o_account_actions(RestActions,NState,NNState)@lower_priority.
%**************************************************************************
% execute_one_o_account_action
%**************************************************************************
execute_one_o_account_action(action(Client,s(account),e(open,Attributes)),
State,NState) :NState=State.
execute_one_o_account_action(action(Client,This,e(close,[])),State,NState) :update_state(State,[chg(destroy,true)],NState).
2 7 execute_one_o_account_action(action(this,This,e(pay_commission,[])),
State,NState) :get_attributes(State,[]),
NTimes:=0,
update_state(State,[chg(times,NTimes)],NState).
otherwise.
28
execute_one_o_account_action(action(Client,This,e(deposit,[XAmount])),
State,NState) :get_attributes(State,[att(balance,Balance),att(times,Times)]),
NBalance:=Balance+XAmount,
NTimes:=Times+1,
ExpIzq1:=NBalance,
ExpDer1:=100,
test_condition([[c(ge,ExpIzq1,ExpDer1)]],NGood_balance),
update_state(State,[chg(balance,NBalance),chg(times,NTimes),
chg(good_balance,NGood_balance)],NState).
29
execute_one_o_account_action(action(Client,This,e(withdraw,[XPin,XAmount])),
State,NState) :get_attributes(State,[att(balance,Balance),att(times,Times)]),
NBalance:=Balance-XAmount,
NTimes:=Times+1,
ExpIzq1:=NBalance,
ExpDer1:=100,
test_condition([[c(ge,ExpIzq1,ExpDer1)]],NGood_balance),
update_state(State,[chg(balance,NBalance),chg(times,NTimes),
chg(good_balance,NGood_balance)],NState).
3 0 execute_one_o_account_action(action(Client,This,e(pay_commission,[])),
State,NState) :get_attributes(State,[att(balance,Balance)]),
NBalance:=Balance-1,
ExpIzq1:=NBalance,
ExpDer1:=100,
test_condition([[c(ge,ExpIzq1,ExpDer1)]],NGood_balance),
27
Se efectúa la evaluación: [::pay_commision] times:=0. Nótese que esta acción es una
obligación y en la especificación se distingue del servicio asociado al mismo evento anteponiendo “::”. En el programa KL1 se distingue utilizando como cliente “this”.
28
Esta cláusula realiza la evaluación: [deposit(Amount)] balance:= balance + Amount,
times:= times + 1.
29
Aquí se efectúa la evaluación: [withdraw(Pin,Amount)] balance:= balance Amount, times:= times + 1.
30
Esta cláusula efectúa la evaluación: [pay_commision] balance:= balance - 1.
202
APÉNDICE C. PLANTILLAS PARA GENERAR KL1
update_state(State,[chg(balance,NBalance),chg(good_balance,NGood_balance)],
NState).
3 1 execute_one_o_account_action(action(Client,This,e(change_pin,[XPin,XNewPin])),
State,NState) :get_attributes(State,[]),
NPin:=XPin,
update_state(State,[chg(pin,NPin)],NState).
3 2 execute_one_o_account_action(action(Client,This,e(change_rank,[XRank])),
State,NState) :get_attributes(State,[]),
NRank:=XRank,
update_state(State,[chg(rank,NRank)],NState).
otherwise.
execute_one_o_account_action(action(Client,This,Event),State,NState) :NState=State.
%**************************************************************************
% calculate_new_o_account_triggers
%**************************************************************************
calculate_new_o_account_triggers(State,Triggers) :verify_o_account_triggers([t1],State,Triggers).
%**************************************************************************
% verify_o_account_triggers
%**************************************************************************
verify_o_account_triggers([],State,Triggers) :Triggers=[].
33
31
verify_o_account_triggers([t1|RestTriggers],State,Triggers) :get_attributes(State,[att(times,Times),att(good_balance,Good_balance),
att(rank,Rank)]),
ExpIzq1:=Times,
ExpDer1:=5,
ExpIzq2=Good_balance,
ExpDer2=false,
ExpIzq3:=Rank,
ExpDer3:=0,
test_condition([[c(ge,ExpIzq1,ExpDer1),c(eq,ExpIzq2,ExpDer2),
c(eq,ExpIzq3,ExpDer3)]],Answer),
put_trigger(Answer,action(this,self,e(pay_commission,[])),
Triggers,NTriggers),
verify_o_account_triggers(RestTriggers,State,NTriggers)@lower_priority.
Esta cláusula realiza la evaluación: [change_pin(Pin,NewPin)] pin:= NewPin.
En esta cláusula se realiza la evaluación: [change_rank(Rank)] rank:= Rank.
33
Es esta cláusula se verifica la condición de disparo: ::pay_commision when {times>=5
and good_balance=false and rank=0}.
32
Apéndice D
Una sesion con entrada por
lotes
A continuación se presenta una sesión de animación con el prototipo en
modo de entrada por lotes (batch). Las acciones son leidas desde el fichero
test.dat y los resultados (las acciones acontecidas a los objetos y los respectivos estados alcanzados) son almacenados en el fichero test.res. El contenido
del fichero se ha formateado y resumido en tablas. En este modo de trabajo, el
analista valida manualmente el comportamiento esperado del sistema respecto
al comportamiento exhibido por el prototipo.
El fichero test.dat utilizado en este ejemplo es el siguiente:
action(c(user),s(account),e(open,[att(number,101),att(name,pato),
att(balance,0),att(counter,0),att(rank,0)])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[10])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[30])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[20])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[30])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[40])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[10])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[20])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[30])).
action(c(user),s(account),e(open,[att(number,101),att(name,pato),att(balance,0),
att(counter,0),att(rank,0)])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[40])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[10])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[20])).
action(c(user),s(account,id(number,[att(number,101)])),e(change_rank,[1])).
action(c(user),s(account),e(open,[att(number,202),att(name,bicho),att(balance,0),
att(counter,0),att(rank,0)])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[30])).
action(c(user),s(account,id(number,[att(number,202)])),e(deposit,[40])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[20])).
action(c(user),s(account,id(number,[att(number,202)])),e(withdraw,[30])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[40])).
action(c(user),s(account,id(number,[att(number,101)])),e(deposit,[30])).
action(c(user),s(account,id(number,[att(number,202)])),e(deposit,[40])).
action(c(user),s(account,id(number,[att(number,202)])),e(withdraw,[20])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[30])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[40])).
action(c(user),s(account,id(number,[att(number,101)])),e(change_rank,[2])).
action(c(user),s(account,id(number,[att(number,202)])),e(withdraw,[30])).
action(c(user),s(account,id(number,[att(number,202)])),e(close,[])).
203
204
APÉNDICE D. UNA SESION CON ENTRADA POR LOTES
action(c(user),s(account,id(number,[att(number,202)])),e(withdraw,[10])).
action(c(user),s(account,id(number,[att(number,101)])),e(withdraw,[40])).
action(c(user),s(account,id(number,[att(number,202)])),e(deposit,[40])).
Cada una de las siguientes tablas, formateadas a partir del fichero test.res,
reflejan el comportamiento exhibido por uno de los objetos durante la prototipación y ante la aplicación de las acciones en el fichero test.dat. Se han
omitido los intervalos de tiempo en los cuales no se produjo algún cambio en
el objeto.
i
Clase Account
i
i
Services
Conflicts
i
(ti-1 - ti]
t0
Population
Triggers
-
tick
open(...101...)
-
(t8 - t9]
101
open(...101...)
-
(t14 - t15]
101
tick
reject(open(10))
tick
open(...202...)
-
(t35 - t36]
101,202
tick
stop
-
i
i+1
Executed
Population
tick
open(101)
tick
reject(open(101))
tick
open(202)
tick
stop
101
101
101,202
101,202
En t9 se rechazada la acción de creación de la cuenta 101 porque ya existe
una cuenta con dicho valor identificador.
Object Account 101
Servicesi
Conflictsi
(ti-1 - ti]
t0
Statei
Triggersi
Executedi
Statei+1
-
tick
open(...101...)
deposit(10)
deposit(10)
tick
open(101)
(t0 - t1]
destroy: false
number: 101
name: pato
balance: 0
times: 0
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 10
times: 0
rank: 0
good_balance: false
tick
deposit(10)
-
tick
deposit(10)
tick
rejected(wit
hdraw(30))
deposit(20)
withdraw(30)
-
tick
deposit(20)
rejected(withdr
aw(30))
destroy: false
number: 101
name: pato
balance: 0
times: 0
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 10
times: 1
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 30
times: 2
rank: 0
good_balance: false
(t1 - t2]
205
(t3 - t4]
(t4 - t5]
(t5 - t6]
(t6 - t7]
(t7 - t8]
(t8 - t9]
(t10 - t11]
(t11 - t12]
destroy: false
number: 101
name: pato
balance: 30
times: 2
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 60
times: 3
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 100
times: 4
rank: 0
good_balance: true
destroy: false
number: 101
name: pato
balance: 90
times: 5
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 90
times: 0
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 70
times: 1
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 40
times: 2
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 39
times: 2
rank: 0
good balance: false
tick
deposit(30)
deposit(40)
tick
deposit(40)
withdraw(10)
tick
withdraw(10)
tick
self::pay_co
mmision
withdraw(20)
withdraw(30)
tick
withdraw(20)
withdraw(30)
tick
withdraw(30)
tick
pay_commision
tick
rejected(wit
hdraw(40)
withdraw(40)
deposit(10)
deposit(20)
deposit(40)
tick
deposit(30)
destroy: false
number: 101
name: pato
balance: 60
times: 3
rank: 0
good_balance: false
withdraw(10)
tick
destroy: false
deposit(40)
number: 101
name: pato
balance: 100
times: 4
rank: 0
good balance: true
tick
destroy: false
withdraw(10) number: 101
name: pato
balance: 90
times: 5
rank: 0
good balance: false
withdraw(20)
destroy: false
tick
withdraw(30) self::pay_comm number: 101
name: pato
ision
balance: 90
times: 0
rank: 0
good_balance: false
withdraw(30)
tick
destroy: false
withdraw(30) number: 101
name: pato
balance: 70
times: 1
rank: 0
good_balance: false
tick
destroy: false
withdraw(30) number: 101
name: pato
balance: 40
times: 2
rank: 0
good_balance: false
tick
destroy: false
pay commision number: 101
name: pato
balance: 39
times: 2
rank: 0
good_balance: false
destroy: false
deposit(20)
tick
rejected(withdr number: 101
name: pato
aw(40))
deposit(10)
balance: 49
times: 3
rank: 0
good balance: false
En t6 times=5,good_balance=false y rank=0 con lo cual se satisface la
condición de disparo para la acción ::pay_commision. En el mismo tick, los
eventos withdraw(20) y withdraw(30) están en conflicto con pay_commision
(todos ellos afectan el atributo balance) por lo tanto son postergados para el
siguiente tick.
206
APÉNDICE D. UNA SESION CON ENTRADA POR LOTES
(t12 - t13] destroy: false
tick
deposit(20)
-
(t13 - t14]
tick
change_rank(1)
-
tick
deposit(30)
-
tick
withdraw(20)
-
tick
withdraw(40)
-
tick
deposit(30)
-
tick
withdraw(30)
-
tick
rejected(wit
hdraw(40)
withdraw(40)
change_rank(2)
-
(t14 - t15]
(t22 - t23]
(t26 - t27]
(t28 - t29]
(t30 - t31]
(t32 - t33]
number: 101
name: pato
balance: 49
times: 3
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 69
times: 4
rank: 0
good_balance: false
destroy: false
number: 101
name: pato
balance: 69
times: 4
rank: 1
good_balance: false
destroy: false
number: 101
name: pato
balance: 99
times: 5
rank: 1
good_balance: false
destroy: false
number: 101
name: pato
balance: 79
times: 6
rank: 1
good_balance: false
destroy: false
number: 101
name: pato
balance: 39
times: 7
rank: 1
good_balance: false
destroy: false
number: 101
name: pato
balance: 69
times: 8
rank: 1
good_balance: false
destroy: false
number: 101
name: pato
balance: 39
times: 9
rank: 1
good balance: false
tick
deposit(20)
destroy: false
number: 101
name: pato
balance: 69
times: 4
rank: 0
good_balance: false
tick
destroy: false
change rank(1) number: 101
name: pato
balance: 69
times: 4
rank: 1
good_balance: false
tick
destroy: false
deposit(30)
number: 101
name: pato
balance: 99
times: 5
rank: 1
good_balance: false
tick
destroy: false
withdraw(20) number: 101
name: pato
balance: 79
times: 6
rank: 1
good_balance: false
tick
destroy: false
withdraw(40) number: 101
name: pato
balance: 39
times: 7
rank: 1
good_balance: false
tick
destroy: false
deposit(30)
number: 101
name: pato
balance: 69
times: 8
rank: 1
good_balance: false
tick
destroy: false
withdraw(30) number: 101
name: pato
balance: 39
times: 9
rank: 1
good_balance: false
tick
destroy: false
rejected(withdr number: 101
aw(40))
name: pato
change rank(2) balance: 39
times: 9
rank: 2
good balance: false
207
(t36 - t37] destroy: false
tick
withdraw(40)
-
tick
withdraw(40)
(t38 - t39]
number: 101
name: pato
balance: 39
times: 9
rank: 2
good_balance: false
destroy: false
number: 101
name: pato
balance: -1
times: 10
rank: 2
good_balance: false
tick
stop
-
tick
stop
Statei
Triggersi
-
tick
open(...202...)
(t4 - t5] destroy: false
tick
deposit(40)
-
tick
deposit(40)
(t9 - t10]
tick
withdraw(30)
-
tick
withdraw(30)
tick
deposit(40)
-
tick
deposit(40)
tick
withdraw(20)
-
tick
withdraw(20)
(ti-1 - ti]
t0
(t13 t14]
(t15 t16]
number: 202
name: bicho
balance: 0
times: 0
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 40
times: 1
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 10
times: 2
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 50
times: 3
rank: 0
good_balance: false
Object Account 202
Servicesi
Conflictsi
destroy: false
number: 101
name: pato
balance: -1
times: 10
rank: 2
good_balance: false
destroy: false
number: 101
name: pato
balance: -1
times: 10
rank: 2
good_balance: false
Executedi
Statei+1
tick
open(202)
destroy: false
number: 202
name: bicho
balance: 0
times: 0
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 40
times: 1
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 10
times: 2
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 50
times: 3
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 30
times: 4
rank: 0
good_balance: false
208
APÉNDICE D. UNA SESION CON ENTRADA POR LOTES
(t19- t20] destroy: false
tick
rejected(clo
se)
close
withdraw(30)
(t20- t21]
tick
self::pay_co
mmision
-
-
tick
rejected(wit
hdraw(10))
withdraw(10)
-
tick
deposit(40)
stop
stop
tick
pay_commision
stop
-
(t21 t22]
(t23 t24]
(t24 t25]
number: 202
name: bicho
balance: 30
times: 4
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 0
times: 5
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 0
times: 0
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 0
times: 0
rank: 0
good_balance: false
destroy: false
number: 202
name: bicho
balance: 40
times: 1
rank: 0
good_balance: false
tick
withdraw(30)
destroy: false
number: 202
name: bicho
balance: 0
times: 5
rank: 0
good_balance: false
tick
destroy: false
self::pay_comm number: 202
ision
name: bicho
balance: 0
times: 0
rank: 0
good_balance: false
tick
destroy: false
rejected(withdr number: 202
aw(10)
name: bicho
balance: 0
times: 0
rank: 0
good_balance: false
tick
destroy: false
deposit(40)
number: 202
name: bicho
balance: 40
times: 1
rank: 0
good_balance: false
destroy: false
tick
pay commision number: 202
stop
name: bicho
balance: 39
times: 1
rank: 0
good_balance: false
Bibliografía
[1] Agha G.A. ACTORS: A Model of Concurrent Computation in Distributed Systems. The MIT Press, 1986.
[2] Åqvist L. Deontic Logic. In D.M. Gabbay and F.Guenthner (Eds.),
Handbook of Philosophical Logic II, pages 605-714, Reidel, 1984.
[3] Balzer R., Cheatham T.E. Green C. Software Technology in the 1990’s:
Using a New Paradigm. IEEE Computer, pages 39-45, November 1983.
[4] Balzer R. A 15 Year Perspective on Automatic Programming. IEEE
Transactions on Software Engineering, vol.11, num.11, pages 1257-1268,
November 1985.
[5] Bell R. Code Generation from Object Models. Embedded Systems Programming, March 1998. http://www.embedded.com/98/9803fe3.html.
[6] Boer F.S., Kok J., Palamidessi C. On the Asynchronous Nature of Communication in Concurrent Logic Languages: A Fully Abstract Model
based on Sequences. In J.C.Baeten and J.W.Klop (Eds.), CONCUR’90,
pages 99-114, Springer-Verlag, 1990.
[7] Börger E., Riccobene E. Logical Operational Semantics of Parlog, Part
I: And-Parallelism. In Harold Boley, Michael M. and Richter (Eds.),
International Workshop on Processing Declarative Knowledge, PDK’91,
LNCS 1567, pages 191-198, Springer-Verlag, 1991.
[8] Börger E., Riccobene E. Logical Operational Semantics of Prolog. Part
II: Or-Parallelism. In Andrei Voronkov (Ed.), Proceedings of First
Russian Conference on Logic Programming, LNCS 592, pages 27-34,
Springer-Verlag, 1990.
[9] Boehm B.W. Software Engineering: R & D Trends and Defense Needs.
In Wegner, P. (Ed.), Research Directions in Software Technology, Cambridge MA: MIT Press, 1979.
209
210
BIBLIOGRAFÍA
[10] Booch G. Análisis y Diseño Orientado a Objetos con Aplicaciones.
Addison-Wesley/Díaz de Santos, 1996.
[11] Coleman D., Hayes F., Bear S. Introducing Objectcharts or How to use
Statecharts in Object-Oriented Design. IEEE Transactions on Software
Engineering, vol.18, num.1, January 1992.
[12] Conlon T. Programming in PARLOG. Addisson-Wesley, 1989.
[13] Corchuelo R., Ruiz D., Toro M., Arjona J. and Prieto M. Prototyping
IPC on a Network Computer. Proceedings of the IV MENHIR Workshop, pages 41-45, Burgos, 1999.
[14] Chikayama, T. KLIC User’s Manual. Institute for New Generation Computer Tecnology, Tokyo, March 1995.
[15] Craigen D., Gerhart S., Ralston T. Formal Methods Reality Check:
Industrial Usage. IEEE Transactions on Software Engineering, vol.21,
num.2, pages 90-98, February 1995.
[16] Davis A. Software Requirements: Objects, Functions, and States. Prentice Hall International, 1993.
[17] Davis A., Hsia P. Giving Voice to Requirements Engineering. IEEE Software, pages 12-16, March 1994.
[18] Davison A. Polka: A Parlog Object-Oriented Language. PhD Thesis, Departament of Computer Science, Imperial Collegue Londres, 1989.
[19] Dubois E., Du Bois P., Petit M. O-O Requirements Analysis: An Agent
Perspective. In Proceedings of the 7th.European Conference on Object
Oriented Programming, ECOOP’93, pages 458-481, 1993.
[20] Dubois E., Hagelstein J., Rifaut A. A Formal Language for the Requirements Engineering of Computer Systems. In André Thayse (Ed.), From
Natural Language Processing to Logic for Expert Systems, chapter 6,
Wiley, 1991.
[21] Dubois E., Du Bois P., Dubru F. Animating Formal Requirements Specifications of Cooperative Information Systems. In Proceedings of the
Second International Conference on Cooperative Information Systems,
pages 101-112, Toronto, Mayo 1994.
[22] Feenstra R.B., Wieringa R.J. LCM 3.0: A Languaje for Describing Conceptual Models. Technical Report IR-344, Faculty of Mathematics and
Computer Science, Vrije Universiteit, Amsterdam, 1993.
BIBLIOGRAFÍA
211
[23] Filippidou, D. and P. Loucopoulos. Using Scenarios to Validate Requirements in a Plausibility-centred Approach. In Proceedings of the 9th International Conference on Advanced Information Systems Engineering,
CAiSE’97, pages 47-60, Barcelona, 1997.
[24] Fuchs N. Specifications are (Preferably) Executable. Software Engineering Journal, September 1992.
[25] Garlan D., Perry D.E. Introduction to the Special Issue on Software
Architecture. IEEE Transactions on Software Engineering, vol.21, num.4,
pages 269-274, April 1995.
[26] Gogolla M., Conrad S., Denker G., Herzig R., Vlachantonis N. A Development Environment for an Object Specification Language. IEEE Transactions on Knowledge and Data Engineering, vol.7, num.3, pages 505—
508, June 1995.
[27] Goldsack S.J., Kent S.J.H. (Eds). Formal Methods and Object Technology. Springer-Verlag, 1996.
[28] Grau A. Validating Object-Oriented Specifications through Animation. Workshop “Grundlagen von Datenbanken”, Workshop des GIArbeitskreises in Königslutter, Technischer Bericht, Universität Dortmund, pages 26-30, May 1997.
[29] Hammer M., McLeod D. Database Descriptions with SDM: A Semantic
Database Model. ACM Transactions on Database Systems, vol.6, num.3,
pages 251-386, September 1981.
[30] Harel D. Dynamic Logic. D.M.Gabbay, F.Guenthner (Eds.), Handbook
of Philosophical Logic II, pages 497-694, Reidel 1984.
[31] Harel D., Gery E. Executable Object Modeling with Statecharts. IEEE
Computer, vol.30, num.7, pages 31-42, July 1996.
[32] Hartmann T., Saake G. Abstract Specification of Object Interaction.
Informatik-Bericht 93-08, TU Braunschweig, 1993.
[33] Hartmann T., Jungclaus R., Saake G. Animation Support for a Conceptual Modelling Language. V. In Proc. of the 4th Int. Conf. on Database
and Expert Systems Applications, DEXA’93, LNCS 720, pages 56—67,
Springer-Verlag, Prague, September 1993.
[34] Haumer P., Heymans P., Pohl K. An Integration of Scenario-Based
Requirements Elicitation and Validation Techniques. Technical Report
CREWS 98-28, Cooperative Requirements Engineering with Scenarios,
212
BIBLIOGRAFÍA
ftp://sunsite.informatik.rwth-aachen.de/pub/CREWS/reports98.html.
[35] Hayes I.J., Jones C.B. Specifications are Not (Necessarily) Executable.
Technical Report Nro.148, Key Centre for Software Technology, Departament of Computer Science, University of Queensland, 1990.
[36] Herzig R., Gogolla M. An Animator for the Object Specification Language TROLL Light. In Proceedings of the Colloquium on Object Orientation in Databases and Software Engineering, COODBSE’94, pages
156-170, Montreal, May1994.
[37] Heymans P. Some Thoughts about the Animation of Formal Specifications written in the ALBERT II Language. Technical Report
CREWS 97-04, Cooperative Requirements Engineering with Scenarios,
http://sunsite.informatik.rwth-aachen.de/CREWS/reports97.html.
[38] Heymans P. The Albert II Specification Animator. Technical Report
CREWS 97-13, Cooperative Requirements Engineering with Scenarios,
http://sunsite.informatik.rwth-aachen.de/CREWS/reports97.html.
[39] Hinchey M.G., Bowen J.P. To Formalize or Not to Formalize?. In “An
Invitation to Formal Methods”, IEEE Computer, vol.29, num.4, pages
18-19, April 1996.
[40] Hull R., King R. Semantic Database Modelling. ACM Computing Surveys, vol.19, n.3, September 1987.
[41] Jackson M. System Development. Prentice-Hall, 1983.
[42] Jacobson I., Christerson M., Jonsson P., Övergaard G. Object-Oriented
Software Engineering: A Use Case Driven Approach. ACM Press y
Addison-Wesley, 1992.
[43] Jungclaus R., Saake G., Hartmann T., Sernadas C. TROLL - A Language for Object-Oriented Specification of Information Systems. ACM
Transactions on Information Systems, vol.14, num.2, pages 175-211,
April 1995.
[44] Koskimies K., Systä T., Tuomi J., Männistö T. Automated Support for
Modelling OO Software. IEEE Software, pages 87-94, January 1998.
[45] LaBudde E. Why is Requirements Engineering Underused?. IEEE Software, pages 6-8, March 1994.
BIBLIOGRAFÍA
213
[46] Letelier P., Sánchez P., Ramos I. Conceptos Básicos de Especificaciones
OASIS Implementados usando Progamación Lógica Concurrente. Informe Técnico DSIC-II/32/96, DSIC-Universidad Politécnica de Valencia, 1996.
[47] Letelier P., Ramos I. Un Metamodelo Estático para Especificaciones OASIS y su Implementación en una Base de Datos Relacional. Informe Técnico DSIC-II/19/96, DSIC-Universidad Politécnica de Valencia, 1996.
[48] Letelier P., Sánchez P., Ramos I. Modelización de la Perspectiva Cliente
en Especificaciones OASIS. Informe Técnico DSIC-II/9/97, DSICUniversidad Politécnica de Valencia, 1997.
[49] Letelier P., Sánchez P., Ramos I. Guías para la Generación Automática
de un Programa Lógico Concurrente que sirve de Prototipo para una Especificación OASIS. Informe Técnico DSIC-II/26/97, DSIC-Universidad
Politécnica de Valencia, 1997.
[50] Letelier P., Sánchez P., Ramos I. Animación de Modelos Conceptuales
para Ayudar en la Validación de Requisitos. In Proceedings of Argentine
Symposium on Object Orientation, ASOO´97, páginas 100-110, Buenos
Aires, Argentina, 1997.
[51] Letelier P., Sánchez P., Ramos I. Animation of System Specifications using Concurrent Logic Programming. Symposium on Logical Approaches
to Agent Modeling and Design, ESSLLI’97, Aix-en-Provence, France,
1997.
[52] Letelier P., Sánchez P., Ramos I. Un Modelo Abstracto para la Ejecución
de Especificaciones OASIS 3.0. Actas de las II Jornadas de Trabajo
MENHIR, páginas 63-74, Murcia, 1998.
[53] Letelier P., Sánchez P., Ramos I., Pastor O. Formalización de OASIS en
Lógica Dinámica incluyendo Especificaciones de Proceso. Informe Técnico DSIC-II/2/98, Universidad Politécnica de Valencia, 1998.
[54] Letelier P., Sánchez P., Ramos I. Animación de Especificaciones OASIS en Entornos Concurrentes. Actas de las II Jornadas de Trabajo de
MENHIR, páginas 121-134, Valencia, 1998.
[55] Letelier P., Sánchez P., Ramos I.. Especificaciones de Proceso para Objetos y su Representación en Lógica Dinámica. Actas de las III Jornadas
de Ingeniería del Software, JIS’98, páginas 281-292, Murcia, 1998.
214
BIBLIOGRAFÍA
[56] Letelier P., Sánchez P., Ramos I., Pastor O. OASIS versión 3.0: Un Enfoque Formal para el Modelado Conceptual Orientado a Objeto. Servicio
de Publicaciones de la Universidad Politécnica de Valencia, SPUPV98.4011, 1998.
[57] Letelier P., Sánchez P., Ramos I. Prototyping a Requirements Specification Through an Automatically Generated Concurrent Logic Program. In
Gopal Gupta (Ed.), Practical Aspects of Declarative Languages, LCNS
1551, pages 31-45, Springer-Verlag, Texas, USA, 1998.
[58] Letelier P., Sánchez P., Ramos I. Un Ambiente para Especificacion Incremental y Validacion de Modelos Conceptuales. Actas del 2o Workshop Iberoamericano de Ingeniería de Requisitos y Ambientes Software,
IDEAS’99, páginas 216-228, Costa Rica, 1999.
[59] Letelier P., Sánchez P., Ramos I. Animation of Conceptuals Models using two Concurrent Environments: An overview. Por publicar en Proceedings of 3rd IMACS/IEEE International Multiconference on Circuits,
Systems, Communication and Computers, Grecia, 1999.
[60] Luqi, Goguen J.A. Formal methods: Promises and Problems. IEEE Software, pages 73-85, January 1997.
[61] Maiden
N.A.M.
CREWS-SAVRE: Scenarios for Acquiring
and Validating Requirements. Technical Report CREWS 9803, Cooperative Requirements Engineering with Scenarios,
http://sunsite.informatik.rwth-aachen.de/CREWS/reports98.html.
[62] Martin J., Odell J. Object-Oriented Methods: A Foundation. Prentice
Hall, 1998.
[63] Participantes del Proyecto Menhir. MENHIR: Modelos, Entornos y
Nuevas Herramientas para la Ingeniería de Requisitos. Actas de las III
Jornadas de Investigación y Docencia en Bases de Datos, JIDBD’98,
Valencia, 1998.
[64] Meyer J.-J.Ch. A Different Approach to Deontic Logic: Deontic Logic
viewed as a Variant of Dynamic Logic. In Notre Dame Journal of Formal
Logic, vol.29, pages 109-136, 1988.
[65] Milner R. Communication and Concurrency. C.A.R. Hoare Series Editor, Prentice Hall Series in Computer Science, 1989.
BIBLIOGRAFÍA
215
[66] National Aeronautics and Space Administration (NASA). Formal Methods Specification and Verification Guidebook for Software and Computer
Systems. Volume I: Planning and Technology Insertion, NASA-GB-00295 release 1.0, 1995, http://www.ivv.nasa.gov.
[67] OBLOG Software S.A. The OBLOG Software Development Approach
(White Paper). 1999, http://www.oblog.pt/Download/Documentation.exe
[68] Ousterhout J. Tcl and the Tk Toolkit. Addison-Wesley, 1994.
[69] Pastor O. Diseño y Desarrollo de un Entorno de Producción Automática
de Software basado en el modelo OO. Tesis Doctoral, DSIC-UPV, 1992.
[70] Pastor O., Ramos I. OASIS versión 2 (2.2) : A Class-Definition Language to Model Information Systems Using an Object-Oriented Approach. Servicio de Publicaciones Universidad Politécnica de Valencia,
SPUPV-95.788, 1995.
[71] Pastor O., Pelechano V., Romero J. y Barberá J.M. Descripción del Entorno Gráfico de la Herramienta CASE OO-METHOD. Informe Técnico
ITI-UPV, 1996.
[72] Pastor O., Insfrán E., Pelechano V., Romero J., Merseguer J. OOMETHOD: An OO Software Production Environment Combining Conventional and Formal Methods. Proceedings of Conference on Advanced
Information Systems Engineering, CAiSE ’97, pages 145-158, Barcelona,
1997.
[73] Pastor O., Pelechano V., Insfrán E. and Gómez J. From Object Oriented
Conceptual Modeling to Automated Programming in Java. In Proceedings of 17th International Conference on Conceptual Modeling, ER’98,
pages 183-196, Singapur, 1998.
[74] Pimentel E. L2||O2: Un Lenguaje Lógico Concurrente Orientado a Objetos. Tesis Doctoral, Facultad de Informática, Universidad de Málaga,
1993.
[75] Pohl K. Requirements Engineering: An Overview. Encyclopedia of Computer Science and Technology, A. Kent, J. Williams (Eds.), vol.36, supplement 21, Marcel Dekker, Inc., New York, 1997.
[76] Popkin Software & Systems. The User Guide for the System Architect
Family of Tools. 1997.
216
BIBLIOGRAFÍA
[77] Proyecto ESPILL. Un Modelo Estático para Especificaciones OASIS v.3
y su Implementación en una Base de Datos Relacional. Informe Técnico
DSIC-II/1/99, DSIC-Universidad Politécnica de Valencia, 1999.
[78] Rational Software Corporation. UML Notation Guide. Versión 1.1.
September 1997, http://www.rational.com/uml.
[79] Rational Software Corporation. Manual of Rational Rose 98: Using Rose
C++, 1998.
[80] Rolland C., Ben Achour C., Cauvet C., Ralyté J., Sutcliffe A., Maiden
N.A.M., Jarke M., Haumer P., Pohl K., Dubois E., Heymans P. A
Proposal for a Scenario Classification Framework. Technical Report
CREWS 96-01, Cooperative Requirements Engineering with Scenarios,
http://sunsite.informatik.rwth-aachen.de/CREWS/reports96.html.
[81] Rumbaugh J., Blaha M., Premerlani W., Eddy F., Lorenzen W. ObjectOriented Modeling and Design. Prentice Hall, 1991.
[82] Sánchez P., Letelier P., Ramos I. Representación de Objetos en Teorías
y su Traducción a un Modelo de Concurrencia. Revista Computación y
Sistemas, vol.1, núm.2, páginas 101-111, 1997.
[83] Sánchez P., Letelier P., Ramos I., Pastor O. Modelado Conceptual con
un Lenguaje Formal y Orientado a Objeto. Por aparecer en Actas de la
XXV Conferencia Latinoamericana de Informática, CLEI’99, Asunción,
Agosto 1999.
[84] Shapiro E., Takeuchi A. Object Oriented Programming in Concurrent
Prolog. New Generation Computing, vol.1, pages 25-48, 1983.
[85] Shapiro E. The Family of Concurrent Logic Programming Languages.
ACM Computing Surveys, vol.21, pages 413-510, 1989.
[86] Shipman D. The Functional Data Model and the Data Language
DAPLEX. ACM Transactions on Database Systems, vol.6, n.1, pages
140-173, March 1981.
[87] Shlaer S., Mellor S.J. Object Lifecycles: Modeling the Worl in States.
Yourdon Press/Prentice Hall, 1992.
[88] Siddiqi J. Challenging Universal Truths of Requirements Engineering.
IEEE Software, pages 18-19, March 1994.
BIBLIOGRAFÍA
217
[89] Siddiqi J., Morrey I.C., Roast C.R., Ozcan M.B. Towards Quality Requirements via Animated Formal Specifications. Annals of Software Engineering, Vol.3, pages 131-155, 1997.
[90] Somé S., Dssouli R., Vaucher J. Towards an Automation of Requirements
Engineering using Scenarios. Journal of Computing and Information,
vol.2, n.1, pages 1110-1132, 1996.
[91] Sommerville I. Software Engineering. Addison-Wesley, 1995.
[92] Teorey T., Yang D., Fry J. A Logical Design Methodology for Relational Databases using the Extended Entity-Relationship Model. Computing
Surveys, vol.18, n.2, pages 197-222, Junio 1988.
[93] Torres J. Especificaciones Orientadas a Objetos Basadas en Restricciones: Prototipado Basado en un Lenguaje Orientado a Procesos. Tesis
Doctoral, Depto. Lenguajes y Sistemas Informáticos, Universidad de
Sevilla. 1997.
[94] Proyect 2RARE: 2 Real Applications for Requirements Engineering. Deliverable D12:
“Final Rreport on User’s Results”
and Deliverable 13: “Final Report on Supplier’s Results”, 1996,
http://www.info.fundp.ac.be/~phe/2rare.html.
[95] Ueda K. Guarded Horn Clauses. Technical Report TR-103, ICOT, 1985.
[96] Wieringa R.J. A Conceptual Model Specification Language (CMSL Version 2). Technical Report IR-248, Departament of Mathematics and
Computer Science, Vrije Universiteit, The Netherlands, May 1992.
[97] Wieringa R.J., Meyer J.-J.Ch. Actors, Actions and Initiative in Normative System Specification. Annals of Mathematics and Artificial Intelligence, vol.7, pages 289-346, 1993.
[98] Wieringa R.J. Requirements Engineering: Frameworks for understanding. John Wiley & Sons, 1996.
[99] Wing J.M. A Specifier’s Introduction to Formal Methods. IEEE Computer, vol.23, num.9, pages 8-24, September 1990.
[100] Yoshida K., Chikayama T. A’UM: A String Based Concurrent ObjectOriented Language. In Proceedings of the International Conference on
Fifth Generation Computer Systems, Institute for New Generation Computer Systems (ICOT), pages 638-649, Tokio, December 1988.
[101] Yourdon E. Modern Structured Analysis. Yourdon Press/Prentice Hall,
1989.
Índice alfabético
control, 41
en OASIS 2.2, 69
repetición, 32
acción, 63
conflicto, 65
conjunto consistente, 25
definición, 24
efecto, 25
obligatoria, 26
ocurrencia, 25
permitida, 26
action calling, 78
action sharing, 79
ACTORS, 89
ALBERT, 10, 21
animación, 13
arquitecturas software, 80
escenarios, 9, 20
estado de violación, 27
eventos compartidos, 70
everyone, 37
guardas profundas, 126
ingeniería de requisitos, 7
LCM, 10
mecanismo de comunicación
action calling, 78
action sending, 76
action sharing, 79
action waiting, 77
MENHIR, 2, 140
modelo de ejecución, 92
algoritmo, 102
ejemplo, 103
mundo, 29
buzón, 94
call/return, 80
cambio de estado, 25
ciclo de vida del objeto, 24
cliente, 24, 36, 38, 64
comunicación
acción, 75
asíncrono, 76
ocurrencia forzada, 76
ocurrencia no forzada, 76
síncrono, 76
concurrencia, 64
intra-objeto, 95
CREWS, 9
objeto
atributo, 24, 25
atributo evaluado, 25
estado del, 25
evento, 24
mecanismo de identificación, 35
oid, 35
vida o traza del, 26
obligación, 29
diagrama de vida del objeto, 33, 42,
44, 95, 103
disparos
218
ÍNDICE ALFABÉTICO
OBLOG, 10, 19, 20, 145
OO-METHOD, 10, 19, 21
operación, 26, 63
acción de inicio, 64
acción de término, 64
operación, 24, 49
paso, 26, 63
permiso, 29
perspectiva cliente, 31, 39
proceso, 26
en Lógica Dinámica, 54
en OASIS 2.2, 48
en OASIS 3.0, 49
estado del, 51
grafo de transición, 51
paso, 63
procesos anidados, 65
procesos perpetuos, 125
programación automática, 14
prohibición, 29
protocolo, 24, 26, 49
relación afecta, 96
repositorio, 139, 173
self, 37, 99
semántica, 28
fórmulas de obligación, 29
fórmulas de permiso, 29
transición válida, 28
servicio, 24
servidor, 24, 36, 38, 63
someone, 37
TESORO, 10, 20, 21
timeout, 78
traductor OASIS-KL1, 141
transacción, 50
transición válida, 29
TROLL, 10, 21, 69, 72, 73
UML, 9, 10, 16, 173
219
verificación y validación, 11

Documentos relacionados