escuela superior de ingeniería - Rodin

Anuncio
E SCUELA S UPERIOR DE I NGENIERÍA
INGENIERÍA EN INFORMÁTICA
GA MERA HOM, UN GENERADOR DE MUTANTES DE
ORDEN SUPERIOR PARA COMPOSICIONES WS-BPEL
Emma Blanco Muñoz
Cádiz, Enero del 2012
E SCUELA S UPERIOR DE I NGENIERÍA
INGENIERÍA EN INFORMÁTICA
GA MERA HOM, UN GENERADOR DE MUTANTES DE
ORDEN SUPERIOR PARA COMPOSICIONES WS-BPEL
Departamento:
Lenguajes y Sistemas Informáticos
Directores del Proyecto:
Juan José Domínguez Jiménez
Antonio García Domínguez
Autora del Proyecto:
Emma Blanco Muñoz
Cádiz, Enero del 2012
Fdo.: Emma Blanco Muñoz
c
Copyright 2011
Emma Blanco Muñoz
Licensed under the Apache License, Version 2.0 (the “License”); you may not
use this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES
OR CONDITIONS OF ANY KIND, either express or implied. See the License for
the specific language governing permissions and limitations under the License.
Agradecimientos
...
Índice general
1. Introducción
7
1.1. Motivación . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.2. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.3. Alcance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.4. Glosario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
1.4.1. Acrónimos . . . . . . . . . . . . . . . . . . . . . . . . .
10
1.4.2. Definiciones . . . . . . . . . . . . . . . . . . . . . . . .
12
1.5. Visión general . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
2. Desarrollo del Calendario
17
2.1. Iteraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
2.1.1. Estudio del dominio del problema . . . . . . . . . . . . .
18
2.1.2. Elicitación de requisitos . . . . . . . . . . . . . . . . . .
20
2.1.3. Implementación del algoritmo principal . . . . . . . . . .
20
2.1.4. Implementación de operadores . . . . . . . . . . . . . . .
20
2.1.5. Pruebas & Calidad . . . . . . . . . . . . . . . . . . . . .
21
2.1.6. Documentación . . . . . . . . . . . . . . . . . . . . . . .
21
2.2. Diagrama de Gantt . . . . . . . . . . . . . . . . . . . . . . . . .
21
2.3. Esfuerzos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
2
ÍNDICE GENERAL
3. Antecedentes
25
3.1. Servicios Web . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
3.2. El lenguaje WS-BPEL . . . . . . . . . . . . . . . . . . . . . . .
27
3.3. Algoritmos genéticos . . . . . . . . . . . . . . . . . . . . . . . .
31
3.3.1. Elementos y operadores de un AG . . . . . . . . . . . . .
33
3.3.2. Esquema de un AG básico . . . . . . . . . . . . . . . . .
39
3.3.3. Renovación de la población de los AG . . . . . . . . . . .
40
3.4. Prueba de mutaciones . . . . . . . . . . . . . . . . . . . . . . . .
41
3.4.1. Mutación evolutiva . . . . . . . . . . . . . . . . . . . . .
43
4. Descripción general del Proyecto
45
4.1. Perspectiva del producto . . . . . . . . . . . . . . . . . . . . . .
45
4.1.1. Entorno de los productos . . . . . . . . . . . . . . . . . .
45
4.1.2. Interfaces de sistema . . . . . . . . . . . . . . . . . . . .
48
4.1.3. Interfaces de usuario . . . . . . . . . . . . . . . . . . . .
48
4.2. Funciones del producto . . . . . . . . . . . . . . . . . . . . . . .
48
4.3. Características de los usuarios . . . . . . . . . . . . . . . . . . .
49
4.4. Restricciones generales . . . . . . . . . . . . . . . . . . . . . . .
50
4.4.1. Control de versiones . . . . . . . . . . . . . . . . . . . .
50
4.4.2. Lenguajes de programación y tecnologías . . . . . . . . .
51
4.4.3. Herramientas de desarrollo . . . . . . . . . . . . . . . . .
55
4.4.4. Sistemas operativos y hardware . . . . . . . . . . . . . .
55
4.4.5. Bibliotecas y módulos usados . . . . . . . . . . . . . . .
56
4.5. Requisitos para futuras versiones . . . . . . . . . . . . . . . . . .
57
5. Desarrollo del Proyecto
5.1. Metodología de desarrollo . . . . . . . . . . . . . . . . . . . . .
59
59
ÍNDICE GENERAL
3
5.1.1. Origen . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
5.1.2. Características . . . . . . . . . . . . . . . . . . . . . . .
61
5.2. Herramientas de modelado usadas . . . . . . . . . . . . . . . . .
68
5.2.1. BOUML . . . . . . . . . . . . . . . . . . . . . . . . . .
68
5.3. Especificación de los requisitos del sistema . . . . . . . . . . . .
68
5.3.1. Requisitos de interfaces externas . . . . . . . . . . . . . .
69
5.3.2. Requisitos funcionales . . . . . . . . . . . . . . . . . . .
69
5.3.3. Requisitos de información . . . . . . . . . . . . . . . . .
70
5.3.4. Requisitos de reglas de negocio . . . . . . . . . . . . . .
70
5.3.5. Atributos del sistema software . . . . . . . . . . . . . . .
71
5.4. Análisis del sistema . . . . . . . . . . . . . . . . . . . . . . . . .
71
5.4.1. Historias de usuario . . . . . . . . . . . . . . . . . . . . .
72
5.4.2. Casos de uso . . . . . . . . . . . . . . . . . . . . . . . .
75
5.4.3. Modelo conceptual de datos del dominio . . . . . . . . .
80
5.5. Diseño del sistema . . . . . . . . . . . . . . . . . . . . . . . . .
82
5.5.1. Arquitectura del sistema . . . . . . . . . . . . . . . . . .
82
5.5.2. Detalles de diseño . . . . . . . . . . . . . . . . . . . . .
83
5.6. Implementación . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
5.7. Evaluación de la calidad . . . . . . . . . . . . . . . . . . . . . . 107
5.7.1. Sonar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.7.2. Jenkins . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
5.8. Plan de pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
6. Resultados
119
7. Conclusiones
123
A. Manual del usuario
125
4
ÍNDICE GENERAL
B. Manual del desarrollador
127
B.1. Instalación de herramientas . . . . . . . . . . . . . . . . . . . . . 127
B.2. Puesta a punto del proyecto . . . . . . . . . . . . . . . . . . . . . 128
B.3. Ejecución del proyecto . . . . . . . . . . . . . . . . . . . . . . . 129
C. Ejemplos
131
C.1. Fichero BPEL de LoanRPC . . . . . . . . . . . . . . . . . . . . . 131
C.2. Fichero de pruebas BPTS de LoanRPC . . . . . . . . . . . . . . . 134
C.3. Análisis de LoanRPC.bpel . . . . . . . . . . . . . . . . . . . . . 141
Bibliografía
147
Índice de figuras
2.1. Modelo de ciclo de vida incremental . . . . . . . . . . . . . . . .
18
2.2. Diagrama de Gantt . . . . . . . . . . . . . . . . . . . . . . . . .
22
2.3. Actividades desarrolladas por esfuerzos . . . . . . . . . . . . . .
23
3.1. Comparación entre orquestación y coreografía de servicios . . . .
28
3.2. Cruce de un punto . . . . . . . . . . . . . . . . . . . . . . . . . .
38
3.3. Cruce de dos puntos . . . . . . . . . . . . . . . . . . . . . . . . .
38
3.4. Cruce uniforme . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
3.5. Mutación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
4.1. Componentes de GAmera . . . . . . . . . . . . . . . . . . . . . .
47
5.1. Diagrama de casos de uso de GAmeraHOM . . . . . . . . . . . .
75
5.2. Diagrama de casos de uso de operadores genéticos . . . . . . . .
76
5.3. Modelo conceptual de datos . . . . . . . . . . . . . . . . . . . .
81
5.4. Diagrama de actividades del AG . . . . . . . . . . . . . . . . . .
84
5.5. Diagrama de clases del lanzador del AG . . . . . . . . . . . . . .
86
5.6. Diagrama de clases del executor . . . . . . . . . . . . . . . . . .
88
5.7. Diagrama de clases del análisis inicial y el HOF . . . . . . . . . .
90
5.8. Diagrama de clases del resultado de la ejecución . . . . . . . . . .
91
5.9. Diagrama de clases de los individuos y su población . . . . . . . .
92
6
ÍNDICE DE FIGURAS
5.10. Primer orden (A) y orden superior (B) . . . . . . . . . . . . . . .
93
5.11. Individuos idénticos . . . . . . . . . . . . . . . . . . . . . . . . .
94
5.12. Diagrama de clases de los operadores genéticos . . . . . . . . . .
95
5.13. Diagrama de clases de los generadores de individuos . . . . . . . 100
5.14. Diagrama de clases de los operadores de selección . . . . . . . . . 101
5.15. Diagrama de secuencia de generación de individuos . . . . . . . . 102
5.16. Diagrama de secuencia de selección de individuos . . . . . . . . . 103
5.17. Diagrama de clases de las condiciones de parada . . . . . . . . . 104
5.18. Diagrama de clases de los loggers . . . . . . . . . . . . . . . . . 106
5.19. Sonar - Cuadro de mandos . . . . . . . . . . . . . . . . . . . . . 109
5.20. Sonar - Pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
5.21. Sonar - Violación . . . . . . . . . . . . . . . . . . . . . . . . . . 111
5.22. Sonar - Evolución de gamera2-core . . . . . . . . . . . . . . 111
5.23. Sonar - Distribuciones . . . . . . . . . . . . . . . . . . . . . . . 112
5.24. Sonar - Nube con el método Quickwins . . . . . . . . . . . . . . 112
5.25. Sonar - Diseño de gamera2-core . . . . . . . . . . . . . . . . 113
5.26. Sonar - Librerías externas de gamera2-core . . . . . . . . . . 114
5.27. Jenkins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Listados de código
3.1.
5.1.
5.2.
5.3.
5.4.
5.5.
5.6.
6.1.
Proceso BPEL: Hola mundo . . . . . . . . . . . . . . .
Fichero de configuración YAML . . . . . . . . . . . . .
Configuración YAML para los operadores genéticos . . .
Configuración YAML para los generadores de individuos
Configuración YAML para los operadores de selección .
Configuración YAML para las condiciones de parada . .
Configuración YAML para los loggers . . . . . . . . . .
HOF de la ejecución de LoanRPC . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
87
95
100
104
105
105
121
Capítulo 1
Introducción
Este Proyecto Fin de Carrera se desarrolla gracias a una Beca de Colaboración
con el Departamento de Lenguajes y Sistemas Informáticos, concedida por el
Ministerio de Educación durante el curso académico 2010/11. Esta beca ha
permitido tomar contacto con las tareas de investigación del grupo UCASE de
Ingeniería del Software (TIC-025), en régimen de compatibilidad con los estudios
del último curso de Ingeniería Informática.
1.1.
Motivación
Los primeros computadores sólo podían ejecutar un único programa al mismo
tiempo. Con su evolución, posibilitando la ejecución de varias tareas simultáneas,
unido a la aparición de las redes, hizo necesario contar con un sistema
de comunicación entre ellos, de modo que dos computadores distintos que
ejecutasen dos programas diferentes pudieran comunicarse entre sí. La unión entre
computadores se salvó gracias a Internet, pero el que dos programas diferentes
se comunicasen estaba sujeto a que su estructura interna fuese perfectamente
compatible, y en caso de que así no lo fuera, no habría interacción posible.
A raíz de lo anterior, surgieron los Web Services (WS, en adelante) que permiten
que un programador pueda crear un WS para transferir datos sin necesidad de
conocer las aplicaciones que harán uso de él, ni los programas de los que depende.
Únicamente deberá ser utilizado por aquellas aplicaciones que quieran recibir esos
datos, lo que quiere decir que podrán existir transferencias de datos entre distintas
aplicaciones que funcionen en distintos computadores, con distintos sistemas
operativos y que pertenezcan a diferentes empresas.
10
Introducción
Una definición más precisa para los WS, según el W3C [1], es que son
aplicaciones software identificadas por un URI, cuyas interfaces se pueden
definir, describir y descubrir mediante documentos XML. Un WS soporta
interacciones directas con otros agentes software utilizando mensajes XML
intercambiados mediante protocolos basados en Internet. Los WS nos permiten
trabajar colaborativamente, en donde el software puede estar distribuido en
diferentes servidores.
Dentro de este contexto, surge el lenguaje WS-BPEL, un estándar definido por
OASIS [2] que permite especificar interacciones entre WS y ofrecerlos a su vez
como WS, siendo éstos sus únicos métodos de entrada y/o salida.
La maduración y la adopción de los WS por parte de muchas empresas es la
culminación de décadas de avance tecnológico. Muchas organizaciones, como
los bancos, les brindan a sus socios WS que pueden utilizar para combinar sus
negocios de manera más efectiva que antes. Los beneficios de esta cooperación
cercana entre las organizaciones son evidentes cada vez que uno compra por
Internet. Está claro que el futuro de la informática comercial se encuentra en la
colectividad.
Si nos detenemos a pensar el amplio uso que los WS tienen hoy en día [3],
es condición sine qua non prestar especial atención a la prueba de este tipo de
software, una de las áreas que abarca el grupo UCASE.
La prueba de mutaciones [4, 5, 6] es una técnica de prueba que ha sido
ampliamente utilizada en una gran diversidad de lenguajes de programación.
De hecho, ya existen varios sistemas de generación de mutantes [7], como por
ejemplo: MuJava [8], SQLMutation [9], entre otros [10, 11]. Sin embargo, la
mayoría de estas herramientas son de primer orden, únicamente Milu genera
mutantes de orden superior para C [12].
Este trabajo se enmarca dentro de la línea de investigación dedicada a las técnicas
de prueba de software para composiciones WS-BPEL y en la que se dispone de
las siguientes herramientas:
Un conjunto de operadores de mutación para WS-BPEL [13, 14].
MuBPEL, un sistema de generación y ejecución de mutantes.
La mutación evolutiva, una técnica de reducción del coste computacional
de la prueba de mutaciones [15].
GAmera, un generador de mutantes de primer orden que implementa la
técnica de la mutación evolutiva para WS-BPEL [16].
1.2 Objetivos
11
GAmera, el primer generador de mutantes basado en un algoritmo genético [17],
es una herramienta realizada previamente por UCASE [16]. Escrito en C++
y con una estructura correspondiente a la de un sistema monolítico, dificulta
el mantenimiento del código, impide que se amplíe el algoritmo fácilmente y,
además, el formato de configuración depende del diseño. Junto a ésto, el uso de
aritmética de precisión limitada puede dar problemas a la larga y el lenguaje C++
y Make no se integran adecuadamente con el resto de los proyectos.
1.2.
Objetivos
Teniendo en cuenta que un mutante de orden superior se crea aplicando una
secuencia de operadores de primer orden al programa original [18], nuestro
objetivo será:
Desarrollar el primer generador de mutantes de orden superior para
composiciones WS-BPEL que implemente la mutación evolutiva y que
bautizaremos como GAmeraHOM. Deberá realizarse bajo Java SE 6, usar
Maven como sistema de compilación, emplear el uso de aritmética arbitraria
y usar un formato YAML para la configuración.
Para todo ello, se necesita:
Un algoritmo genético lo suficientemente genérico para que sea fácilmente
adaptable a otros lenguajes de programación.
Componentes intercambiables y configurables.
Fichero YAML configurable para posteriores estudios del algoritmo.
Definir la nueva estructura de los individuos que compongan la población.
Adaptar los operadores de cruce y de mutación a la nueva estructura.
1.3.
Alcance
Por limitaciones de tiempo, el presente trabajo recoge únicamente el desarrollo del
algoritmo genético con sus nuevos operadores, dejando para un posterior estudio
de investigación las estadísticas sobre la efectividad de la técnica y sobre la calidad
de los mutantes generados.
12
Introducción
1.4.
Glosario
1.4.1.
Acrónimos
AG Algoritmo Genético
API Application Programming Interface
BSD Berkeley Software Distribution
BPEL Business Process Execution Language
BPTS BPELUnit Test Suite
CASE Computer Aided Software Engineering
CPAN Comprehensive Perl Archive Network
CSV Comma-Separated Values
CVS Concurrent Versions System
DPX Double Point Crossover
EMT Evolutionary Mutation Testing
FTP File Transfer Protocol
GPL GNU General Public License
GNU GNU is Not Unix
HOF Hall of Fame
HOM Higher Order Mutants
HTTP Hypertext Transfer Protocol
IBM International Business Machines
ICE-B International Conference on e-Business
ICETE International Joint Conference on e-Business and Telecommunications
IDE Integrated Development Environment
IEEE Institute of Electrical and Electronics Engineers
1.4 Glosario
13
INVEST Independent, Negotiable, Valuable, Estimable, Small and Testable
J2SE Java 2 Standard Edition
JDT Java Development Toolkit
JISBD Jornadas de Ingeniería del Software y Bases de Datos
LCOM Lack of Cohesion of Methods
MIME Multipurpose Internet Mail Extensions
MVJ Máquina Virtual de Java
OASIS Organization for the Advancement of Structured Information Standards
PEAR PHP Extension and Application Repository
PHP PHP Hypertext Pre-processor
POM Project Object Model
RAM Random Access Memory
RFC Request For Comments
RPC Remote Procedure Call
SCM Software Configuration Management
SCV Sistema de Control de Versiones
SLF4J Simple Logging Facade for Java
SMTP Simple Mail Transfer Protocol
SOA Arquitectura Orientada a Servicios
SOAP Simple Object Access Protocol
SPM Single Point Mutation
SPX Single Point Crossover
SQUALE Software Quality Assessment based on Lifecycle Expectations
StAX Streaming API for XML
UDDI Universal Description, Discovery and Integration
14
Introducción
UML Unified Modeling Language
UPX Uniform Point Crossover
URI Uniform Resource Identifier
URL Uniform Resource Locator
UTF Unicode Transformation Format
W3C World Wide Web Consortium
WS Web Service
WS-BPEL Web Services Business Process Execution Language
WS-CDL Web Services Choreography Description Language
WSDL Web Services Description Language
WSFL Web Services Flow Language
WSS Web Services Security
XLANG XML Language
XML eXtensible Markup Language
XML-RPC XML Remote Procedure Call
XP eXtreme Programming
XPath XML Path Language
XSLT Extensible Stylesheet Language Transformations
YAML YAML Ain’t Another Markup Language
1.4.2.
Definiciones
ActiveBPEL Motor que implementa la versión 2.0 del estándar WS-BPEL
licenciado bajo GPLv2.
Algoritmos genéticos Técnicas de búsqueda probabilística basadas en la teoría
de la evolución y la selección natural, es decir, supervivencia de los mejores
y carácter hereditario de las características. Se favorecen a los mejores y se
generan nuevos individuos (recombinación y mutación de información).
1.4 Glosario
15
Aptitud Evaluación cuantitativa de cada individuo del algoritmo genético, de
modo que sirva de comparación de cuán bueno es un individuo con respecto
a otro.
Codificación Procedimiento en el que se define la correspondencia de cada punto
del dominio del problema con cada individuo del algoritmo genético, es
decir, es la forma de especificar la representación de una solución del
problema dentro del algoritmo genético.
Fitness Véase aptitud.
Individuo Posible solución al problema que se pretender resolver por medio del
algoritmo genético.
Inicialización Proceso mediante el que se construye la población inicial con la
que se arranca el bucle básico del algoritmo genético.
Jetty Servidor HTTP 100 % basado en Java y un contenedor de Servlets escrito
en Java.
Mutante Código resultante de hacer pequeñas modificaciones sintácticas en el
programa original.
Mutantes de orden superior Mutantes que contienen más de una diferencia con
respecto al programa original.
Mutantes de primer orden Mutantes que contienen una única diferencia con
respecto al programa original.
Mutantes equivalentes Mutantes que siempre provocan la misma salida que el
programa original.
Operadores genéticos Operadores con los que se lleva a cabo la reproducción
en un algoritmo genético. Todos los algoritmos genéticos utilizan como
mínimo el operador de cruce y de mutación, aunque no son los únicos
posibles.
Mutaciones Conjunto de reglas predefinidas que introducen pequeños cambios
sintácticos en un programa, sin que éste pierda su validez sintáctica,
basados en los errores que suelen cometer los programadores, o bien con
la pretensión de forzar ciertos criterios de cobertura del código.
Parada Condiciones por las que se considera que el algoritmo genético ha dado
con una solución aceptable, o, en su defecto, ha fracasado en la búsqueda y
no tiene sentido continuar.
16
Introducción
Proceso de negocio Conjunto de tareas relacionadas lógicamente llevadas a cabo
para lograr un resultado de negocio definido. Cada proceso de negocio tiene
sus entradas, funciones y salidas. Las entradas son requisitos que deben
tenerse antes de que una función pueda ser aplicada. Cuando una función es
aplicada a las entradas de un método tendremos ciertas salidas resultantes.
Pruebas de caja blanca Técnica de prueba que consiste en centrarse en la
estructura interna (implementación) del programa para elegir los casos de
prueba. Constituye el llamado enfoque estructural, frente al denominado
enfoque funcional o de caja negra.
Pruebas de caja negra Técnica de prueba que consiste en centrarse en lo que se
espera de un módulo, es decir, intenta encontrar casos en que el módulo
no se atiene a su especificación. El probador se limita a suministrarle datos
como entrada y estudiar la salida, sin preocuparse de lo que pueda estar
haciendo el módulo por dentro. Las pruebas de caja negra se apoyan, por
tanto, en la especificación de requisitos del módulo. Constituye el llamado
enfoque funcional, frente al denominado enfoque estructural o de caja
blanca.
Pruebas de mutaciones Técnica de prueba de caja blanca del software basada en
errores. Consiste en generar un gran número de programas, denominados
mutantes, a partir de un programa original aplicando al código fuente los
llamados operadores de mutación.
Salón de la fama Registro de los mejores individuos encontrados por el algoritmo genético desde la primera generación.
Selección Proceso con el que se van eligiendo los individuos más aptos para que
vayan participando de las distintas generaciones del algoritmo genético.
Servicio Web Permiten el intercambio de información en sistemas distribuidos
heterogéneos. Forman una arquitectura que permite describir, publicar, descubrir, solicitar e invocar diferentes servicios empleando la infraestructura
de Internet. El lenguaje WS-BPEL, especifica el comportamiento de un proceso de negocio basado en interacciones con WS.
1.5.
Visión general
Tras esta introducción, hemos conocido cuáles son los objetivos que se pretenden
cubrir con este proyecto, el problema que se quiere resolver y una lista de
1.5 Visión general
17
acrónimos y definiciones utilizadas a lo largo de este documento y que nos
ayudarán a su comprensión.
El resto del PFC se encuentra estructurado tal y como se explica a continuación:
1. En la sección Antecedentes se explicarán los conocimientos básicos sobre
los que se asienta este proyecto, para que cualquier persona pueda
comprender el contenido de esta memoria.
2. A continuación, en el Desarrollo del Calendario se explica cómo se han
planificado y se han ido desarrollando las tareas a lo largo del período de
desarrollo del proyecto, así como la cantidad de esfuerzo que se ha dedicado
aproximadamente a cada una de las etapas.
3. Le sigue la Descripción general del Proyecto que responde a la pregunta
“qué hace” este proyecto, en donde encontraremos la perspectiva y
funciones principales de GAmeraHOM, las características de los usuarios
que vayan a utilizar la aplicación, las restricciones generales, dependencias
y requisitos para futuras versiones.
4. El Desarrollo del Proyecto profundizará en la respuesta a “cómo lo hace”,
detallando la metodología de desarrollo empleada, la especificación de
requisitos y análisis del sistema, resumirá los aspectos más destacables de
la implementación del software y hará mención especial a la calidad del
software.
5. La sección Resultados mostrará el desarrollo de la ejecución de una
composición con GAmeraHOM.
6. Por último, se incluirán las conclusiones, una serie de anexos a la memoria
y manuales para la puesta en marcha de la aplicación.
Capítulo 2
Desarrollo del Calendario
El presente PFC ha sido realizado en un periodo aproximado de catorce meses,
concretamente desde noviembre del 2010 hasta enero del 2012. Ha requerido
un gran esfuerzo de planificación, debido a que no se ha tenido una dedicación
exclusiva a su elaboración. Durante los primeros seis meses, el Proyecto se
compaginó con los estudios del segundo ciclo de Ingeniería Informática, en los
dos meses siguientes se le unió una jornada laboral y durante el tiempo restante,
únicamente se compatibilizó con el trabajo.
La Beca de Colaboración con el grupo UCASE de Ingeniería del Software fue
relevante en esta tarea, ya que además del esfuerzo diario dedicado al desarrollo
de GAmeraHOM, se realizaban una serie de seminarios semanales formativos o
magistrales, en los que se impartían cursos sobre herramientas útiles y afines al
espíritu del grupo, o sesiones en las que se exponían los avances o dificultades
encontradas en cada uno de los proyectos que se llevan a cabo.
2.1.
Iteraciones
En este Proyecto se ha aplicado el modelo de ciclo de vida incremental [19]
(figura 2.1) ya que al no conocer el dominio del problema, fue necesario ir
cumpliendo pequeños hitos e ir ampliando los requisitos en cada fase hasta
completar el producto final. Bajo este modelo se entrega software por partes
funcionales más pequeñas, pero reutilizables, llamadas incrementos.
Este modelo brinda cierta flexibilidad para que durante el desarrollo se incluyan
cambios en los requisitos por parte del usuario, como por ejemplo, un cambio que
20
Desarrollo del Calendario
Figura 2.1: Modelo de ciclo de vida incremental
se produjo en la estructura de elementos básicos del algoritmo genético, cuando ya
se había comenzado el desarrollo. Un cambio de requisitos propuesto y aprobado
puede analizarse e implementarse como un nuevo incremento o, eventualmente,
podrá constituir una mejora de uno ya planeado.
A continuación, se especifican y enumeran las distintas tareas que se han llevado
a cabo para la elaboración del PFC. Estas tareas se pueden solapar en el tiempo
y el comienzo de una tarea no tiene que coincidir necesariamente con el inicio de
otra.
2.1.1.
Estudio del dominio del problema
Esta fase constituye casi todo el tiempo de realización del Proyecto, aunque
es cierto que fue más intenso en los primeros meses, debido al bajo nivel de
conocimiento sobre la materia. Podemos destacar las siguientes etapas:
1. Fue necesario buscar información sobre el funcionamiento de los algoritmos
genéticos, que si bien en la carrera estos conocimientos se dan en la
asignatura de Aprendizaje Automático, no fue hasta el segundo cuatrimestre
cuando se impartió dicha asignatura.
2. Una vez comprendido este paso elemental, se dedicó un periodo de tiempo
a leer artículos realizados por otros miembros del grupo de investigación
que fueran en sintonía con el trabajo que se tendría que realizar para este
Proyecto.
2.1 Iteraciones
21
3. El lenguaje de implementación a usar, Java, se conocía previamente gracias
a la asignatura de Diseño de Sistemas Software, por lo que no fue necesario
emplear tiempo en este apartado. Aunque se tomó contacto con algunos
lenguajes que de alguna manera afectarían al proyecto, tales como YAML,
BPEL, entre otros.
4. En este punto, llegó el momento de comprender cómo trabajaba GAmera,
el generador de mutantes de primer orden para composiciones WS-BPEL,
escrito en C++.
5. Una vez entendido todo el estado del arte, comenzamos a desarrollar el
presente Proyecto.
Artículos de investigación
Podemos destacar la presentación y aceptación de dos artículos, que versan sobre
este PFC, en dos congresos que tuvieron lugar en el año 2011:
El artículo Towards higher-order mutant generation for WS-BPEL [20],
aceptado como artículo reducido en el ICE-B, celebrado en Sevilla del 18
al 21 de julio, el cual se tuvo el honor de presentar personalmente en una
sesión oral de veinte minutos.
ICE-B es parte de ICETE y tiene como objetivo reunir a investigadores y
profesionales interesados en la tecnología del comercio electrónico y sus
aplicaciones actuales.
La tecnología mencionada se refiere no sólo a cuestiones más tecnológicas
de bajo nivel, tales como plataformas tecnológicas y servicios web, sino
también a algunas cuestiones de más alto nivel, como el conocimiento
del contexto y los modelos de empresa y también las peculiaridades de
las diferentes posibles aplicaciones de esta tecnología. Éstas son todas las
áreas de importancia teórica y práctica en el ámbito amplio de e-Business,
cuya creciente importancia puede verse en el aumento del interés de la
comunidad de investigación de las tecnologías de la información.
Según datos publicados en la propia Web [21], el ICE-B 2011 recibió
70 aportaciones, de las cuales el 10 % fueron aceptadas como artículos
completos, el 23 % se presentó como artículos reducidos y el 16 % como
pósteres.
El artículo Propuesta de una arquitectura para la generación de mutantes
de orden superior en WS-BPEL [22], aceptado como trabajo de investiga-
22
Desarrollo del Calendario
ción emergente en las XVI JISBD, celebrado en La Coruña del 5 al 7 de
septiembre.
Las Jornadas de Ingeniería del Software y Bases de Datos (JISBD)
constituyen el foro de encuentro imprescindible para quienes trabajan
en uno de estos dos temas en la península o en Iberoamérica. Las
JISBD se organizan de modo que proporcionen un marco propicio para
debatir, intercambiar ideas, compartir experiencias y divulgar resultados,
fomentando así la colaboración entre los distintos sectores y grupos de
trabajo de estas áreas.
2.1.2.
Elicitación de requisitos
Esta iteración se dedica a establecer el flujo que va a seguir el algoritmo
genético desde su población inicial, también conocida como generación cero, en
el transcurso de las poblaciones sucesivas o generaciones próximas, hasta que se
cumpla alguna condición de parada.
Además, en esta etapa se estudia la estructura de los elementos básicos, tales como
la forma de almacenar los individuos y las propias poblaciones. A medida que
avanzaba el desarrollo del algoritmo, fue necesario modificar los componentes
internos de ciertos elementos o ampliarlos conforme a las nuevas características
que iban surgiendo.
2.1.3.
Implementación del algoritmo principal
En esta fase nos enfrentamos al núcleo de este Proyecto, donde se definirá el
curso que seguirá el algoritmo genético durante su ejecución. Ha sufrido bastantes
cambios para generalizar el algoritmo lo máximo posible, de modo que ante
posibles ampliaciones o modificaciones, no se vea afectado.
2.1.4.
Implementación de operadores
GAmera contaba con un operador de mutación y un operador de cruce, pero al
introducir la estructura de mutantes de orden superior, estos operadores tuvieron
que ser modificados y ampliados para dar cabida a todas las posibilidades.
2.2 Diagrama de Gantt
2.1.5.
23
Pruebas & Calidad
Esta etapa es muy importante, las pruebas son algo esencial en este Proyecto y
hay que prestar especial atención a ellas. Por eso, ocupa gran parte del tiempo de
realización de este PFC.
Todo proyecto tiene como objetivo producir software de la mejor calidad posible,
que cumpla, y si puede, supere las expectativas de los usuarios. Tendremos
especial cuidado en lo que se refiere a funcionalidad, eficiencia, mantenibilidad
y escalabilidad, ya que éste será un Proyecto que tendrá continuidad dentro del
grupo de investigación y que se integrará con otras herramientas.
2.1.6.
Documentación
La memoria, si bien se ha intensificado su desarrollo durante los últimos meses,
se ha ido recopilando desde que comenzó el estudio del dominio del problema, ya
que siempre se ha tenido a mano para consultar dudas, refrescar ideas o para el
desarrollo de los artículos de investigación.
2.2.
Diagrama de Gantt
Para representar las diferentes fases, tareas y actividades programadas como parte
del Proyecto y para mostrar las lineas de tiempo de las diferentes actividades, se
ha elaborado un diagrama de Gantt (figura 2.2) para poder visualizar con mayor
facilidad el desarrollo del PFC con la duración de cada una de las actividades.
Se ha considerado que un día ideal equivale a la cantidad de trabajo que
puede realizarse en un día por una persona, sin distracción alguna y a máximo
rendimiento.
Se ha empleado la herramienta Gantt Project para dibujar el diagrama. Dicha
aplicación está escrita en Java y se puede encontrar bajo la dirección .
Puede observarse como la barra de progreso de la última actividad, marca
aproximadamente un 90 %, pues en el momento en que se realizó la captura, la
documentación no estaba completa.
24
Desarrollo del Calendario
Figura 2.2: Diagrama de Gantt
2.3 Esfuerzos
2.3.
25
Esfuerzos
En la siguiente tabla (figura 2.3) podemos encontrar de forma detallada el esfuerzo
que se ha dedicado a cada tarea. La actividad que ha requerido más esfuerzo es la
relacionada con el estudio del dominio del problema y la propia implementación,
pues los requisitos nos estaban muy definidos desde el principio y había que hacer
cambios de diseño frecuentemente.
Figura 2.3: Actividades desarrolladas por esfuerzos
Capítulo 3
Antecedentes
3.1.
Servicios Web
El W3C define un Servicio Web (WS) como una aplicación software identificada
por un URI cuyas interfaces se pueden definir, describir y descubrir mediante
documentos XML [1].
Podemos decir que designa una tecnología que permite que las aplicaciones se
comuniquen en una forma que no depende de la plataforma, ni del lenguaje de
programación. Un WS es una interfaz de software que describe un conjunto de
operaciones a las cuales se puede acceder por la red a través de mensajería XML
estandarizada. Usa protocolos basados en el lenguaje XML con el objetivo de
describir una operación para ejecutar o intercambiar datos con otro WS. Un grupo
de Servicios Web que interactúa de esa forma define la aplicación de un WS
específico en una Arquitectura Orientada a Servicios. SOA establece un marco de
diseño para la integración de aplicaciones independientes, de manera que desde la
red pueda accederse a sus funcionalidades, las cuales se ofrecen como servicios.
Según Thomas Erl [23], el paradigma de la arquitectura orientada a servicios se
basa en los siguientes principios:
1. Los servicios deben ser construidos pensando en su reutilización, dentro de
la misma aplicación o fuera.
2. Los servicios deben proporcionar un contrato formal, de forma que el
consumidor del servicio accederá a éste mediante el contrato, sin conocer
nada sobre la implementación del propio servicio. En el caso de los WS,
este contrato se logrará con la definición de interfaces con WSDL.
28
Antecedentes
3. Los servicios tiene que tener un bajo acoplamiento, es decir deben ser
independientes entre ellos.
4. Todo servicio debe ser construido de tal manera que pueda ser utilizado para
construir servicios genéricos de más alto nivel, el cual estará compuesto de
servicios de más bajo nivel. En el caso de los WS, esto se logrará mediante
el uso de los protocolos para orquestación (WS-BPEL) y coreografía (WSCDL).
5. Los servicios deberán tener su propio entorno de ejecución.
6. Los servicios no deberán guardar información, sólo contendrán lógica.
7. Los servicios deben darse a conocer, para no realizar servicios cuya
funcionalidad ya exista. En el caso de los WS, se logra publicando los
interfaces de los servicios en registros UDDI.
Los WS son la forma más habitual de implementar SOA. Son aplicaciones que
utilizan estándares para el transporte, codificación y protocolo de intercambio
de información permitiendo la intercomunicación entre sistemas de cualquier
plataforma.
Los WS se construyen a partir de varios estándares abiertos basados en XML,
proporcionando una integración perfecta e interoperabilidad entre aplicaciones
software a través la red [24], de los que podemos destacar los siguientes:
WS Protocol Stack Conjunto de servicios y protocolos utilizados para definir,
localizar, implementar y hacer que un WS interactúe con otro.
XML Formato estándar para los datos que se vayan a intercambiar.
SOAP/XML-RPC Protocolos sobre los que se establece el intercambio de datos.
WSDL Lenguaje de la interfaz pública para describir las funcionalidades de
un WS. Es una descripción basada en XML de los requisitos funcionales
necesarios para establecer una comunicación con los WS.
UDDI Protocolo para publicar la información de los WS. Permite comprobar qué
WS están disponibles, al ser accedido por los mensajes SOAP y dar paso a
documentos WSDL, en los que se describen los requisitos del protocolo y
los formatos del mensaje solicitado para interactuar con los WS del catálogo
de registros.
3.2 El lenguaje WS-BPEL
29
WSS Protocolo de comunicaciones, aceptado como estándar por OASIS, que
suministra un medio para aplicar seguridad a los WS. El protocolo garantiza
la autenticación de los actores y la confidencialidad de los mensajes
enviados.
Orquestación vs. Coreografía de servicios
La orquestación y la coreografía se suelen ver como dos aproximaciones para la
composición de WS, que tienen mucha relación con los conceptos musicales y
por eso, se han heredado sus significados. Sin embargo, hay mucha confusión con
estos términos hasta llegar a tomarlos como sinónimos.
La tarea de componer WS básicos para crear WS más complejos se conoce como
composición de WS. Aquí es donde entra en juego la coreografía, con foco
en la interacción entre servicios (equivalente a los bailarines) y la orquestación
(equivalente a los instrumentos de la orquesta), con foco en la implementación y
ejecución de servicios.
Podemos deducir que la principal diferencia entre orquestación y coreografía es
el alcance:
La orquestación trata de la descripción y ejecución de un mismo y único
punto de vista global del modelo (instrumentación).
La coreografía trata de la descripción y guía de un modelo global proyectado
en base a cada participante (bailarines).
En la figura 3.1, podemos ver cómo la orquestación permite diseñar procesos
de negocio ejecutables que pueden interactuar (a nivel de mensaje) tanto con
software interno como externo, y la coreografía, que permite trazar las secuencias
de mensajes que se suceden entre todas las partes participantes del proceso de
negocio en lugar de centrarse en los mensajes que se intercambian entre los
diversos programas de software que implementan los procesos de negocio.
3.2.
El lenguaje WS-BPEL
WS-BPEL, o especificación del lenguaje de ejecución de procesos de negocio en
WS, pertenece a la capa de componentes establecida en SOA y es, en conjunto
con WS-CDL, una alternativa para la implementación y manejo de WS.
30
Antecedentes
Figura 3.1: Comparación entre orquestación y coreografía de servicios
WS-BPEL surge como necesidad de ser el integrador o el engranaje para
las diversas tecnologías que funcionan bajo SOA, pero que no logran una
interoperabilidad al 100 %, lo que restringe su funcionamiento y adaptabilidad.
WS-BPEL nace tomando propiedades de dos lenguajes propietarios: WSFL
desarrollado por IBM y XLANG desarrollado por Microsoft, ambos lenguajes
orientados a la descripción de WS. WS-BPEL 2.0 fue elegido estándar oficial por
OASIS en Abril de 2007. Puesto que WS-BPEL es un lenguaje formal, se supone
que la semántica es inequívoca. Por tanto, la codificación es esencial para lograr
dicha portabilidad.
Por esta razón, WS-BPEL se basa en el lenguaje de marcado extensible (XML),
que fue diseñado especialmente para ofrecer la portabilidad a través de una
codificación de plataforma neutral.
WS-BPEL tiene como objetivo primordial la “orquestación” de WS, es decir, la
definición de un nuevo WS a partir de WS existentes, en la que el motor BPEL
utilizado es el responsable del control. El motor que respeta el estándar WS-BPEL
2.0 es ActiveBPEL.
La estructura de un proceso WS-BPEL se divide en cuatro secciones:
1. La definición de relaciones con los socios externos (partnerLinks), que
incluye los clientes que utilizan el proceso de negocio y los WS a los que
llama el proceso.
2. La definición de las variables que usa el proceso, usadas para guardar los
mensajes recibidos y enviados por el proceso de negocio y para almacenar
los resultados intermedios de la lógica de las composiciones.
3.2 El lenguaje WS-BPEL
31
3. La definición de los distintos tipos de manejadores que puede utilizar el
proceso, tales como manejadores de fallos y de eventos.
4. La descripción del comportamiento del proceso de negocio
A continuación, se presenta el típico ejemplo “Hola mundo” como proceso de
negocio que llamará a un WS con una variable de entrada con el nombre del
consumidor del servicio y dicho servicio responderá saludando al interesado.
Listado 3.1: Proceso BPEL: Hola mundo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<process
name="HolaMundoBPEL"
targetNamespace="http://enterprise.netbeans.org/bpel/
HolaMundoBPEL"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/
executable"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://enterprise.netbeans.org/bpel/HolaMundoBPEL">
<import
namespace="http://j2ee.netbeans.org/wsdl/HolaMundoBPEL"
location="HolaMundoBPEL.wsdl"
importType="http://schemas.xmlsoap.org/wsdl/"/>
<import
namespace="http://sw.ati.org/"
location="HolaMundoWSService.wsdl"
importType="http://schemas.xmlsoap.org/wsdl/"/>
<!-////////////////////////////////////////////////////////////
PARTNERLINKS
Lista de servicios que participan en este proceso BPEL
////////////////////////////////////////////////////////////
-->
<partnerLinks>
<partnerLink name="HolaMundoWSPL"
xmlns:tns="http://sw.ati.org/"
partnerLinkType="tns:HolaMundoWSPL" partnerRole="
receptorRole"/>
<partnerLink name="HolaMundiBPELPL"
xmlns:tns="http://j2ee.netbeans.org/wsdl/HolaMundoBPEL"
partnerLinkType="tns:HolaMundoBPELPL"
myRole="HolaMundoBPELPortTypeRole"/>
</partnerLinks>
32
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
Antecedentes
<!-////////////////////////////////////////////////////////////
VARIABLES
Lista de mensajes y documentos XML usados dentro de este
proceso BPEL
////////////////////////////////////////////////////////////
-->
<variables>
<variable name="varObtenerCadenaSalida"
xmlns:tns="http://sw.ati.org/"
messageType="tns:obtenerCadenaResponse"/>
<variable name="varObtenerCadenaEntrada"
xmlns:tns="http://sw.ati.org/"
messageType="tns:obtenerCadena"/>
<variable name="varBPELSalida"
xmlns:tns="http://j2ee.netbeans.org/wsdl/HolaMundoBPEL"
messageType="tns:HolaMundoBPELOperationReply"/>
<variable name="varBPELEntrada"
xmlns:tns="http://j2ee.netbeans.org/wsdl/HolaMundoBPEL"
messageType="tns:HolaMundoBPELOperationRequest"/>
</variables>
<!-////////////////////////////////////////////////////////////
ORQUESTACION
Conjunto de actividades que coordinan el flujo de mensajes
a traves de los servicios integrados en este proceso de
negocio
////////////////////////////////////////////////////////////
-->
<sequence>
<receive name="inicio" createInstance="yes"
partnerLink="HolaMundiBPELPL"
operation="HolaMundoBPELOp"
xmlns:tns="http://j2ee.netbeans.org/wsdl/HolaMundoBPEL"
portType="tns:HolaMundoBPELPortType" variable="
varBPELEntrada"/>
<assign name="Asignacion-01">
<copy>
<from>
$varBPELEntrada.entrada/h
</from>
<to>
$varObtenerCadenaEntrada.parameters/h
</to>
</copy>
<copy>
3.3 Algoritmos genéticos
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
33
<from>
$varBPELEntrada.entrada/m
</from>
<to>
$varObtenerCadenaEntrada.parameters/m
</to>
</cop1y>
</assign>
<invoke name="obtenerCadena"
partnerLink="HolaMundoWSPL" operation="obtenerCadena"
xmlns:tns="http://sw.ati.org/"
portType="tns:HolaMundoWS"
inputVariable="varObtenerCadenaEntrada"
outputVariable="varObtenerCadenaSalida"/>
<assign name="Asignacion-02">
<copy>
<from>
$varObtenerCadenaSalida.parameters/return
</from>
<to>
$varBPELSalida.salida/return
</to>
</copy>
</assign>
<reply name="fin"
partnerLink="HolaMundiBPELPL"
operation="HolaMundoBPELOp"
xmlns:tns="http://j2ee.netbeans.org/wsdl/HolaMundoBPEL"
portType="tns:HolaMundoBPELPortType"
variable="varBPELSalida"/>
</sequence>
</process>
3.3.
Algoritmos genéticos
Los Algoritmos Genéticos (AG) son métodos adaptativos que pueden usarse
para resolver problemas de búsqueda y optimización. Se llaman así porque se
inspiran en la evolución biológica y su base genético-molecular. A lo largo de las
generaciones, las poblaciones evolucionan siguiendo los principios de la selección
natural y la supervivencia de los más fuertes, postulados por Darwin [25].
En la naturaleza los individuos de una población compiten entre sí en la
búsqueda de recursos tales como comida, agua y refugio. Incluso los miembros
de una misma especie compiten a menudo en la búsqueda de un compañero.
34
Antecedentes
Aquellos individuos con más éxito en la supervivencia y perpetuación de la
especie generarán un gran número de descendientes. Por el contrario, individuos
poco dotados producirán un menor número de descendientes. Ésto significa
que los genes de los individuos mejor adaptados se propagarán en sucesivas
generaciones hacia un número de individuos creciente. La combinación de
buenas características provenientes de diferentes ancestros puede a veces producir
superindividuos, cuya adaptación es mucho mayor que la de cualquiera de
sus antepasados. De esta manera, las especies evolucionan logrando unas
características cada vez mejor adaptadas al entorno en el que viven.
Los principios básicos de los Algoritmos Genéticos fueron establecidos por Holland [26] y básicamente consiste en una población de individuos o soluciones
potenciales al problema bajo análisis oportunamente codificadas, se hace evolucionar hacia una solución óptima en base a la presión que ejercen los operadores
de selección, mutación y cruce, utilizando una función de aptitud, coste o fitness
para medir la calidad de las soluciones y proceder iterativamente al reemplazo
generacional.
Los conceptos que pueden resumir a los AG son la supervivencia de los mejores
y el carácter hereditario de las características. Esto significa que, por un lado, los
AG favorecen a los mejores individuos, y por otro lado, generan nuevos individuos
a través de la recombinación y la mutación de la información de los individuos
existentes. Los AG no son aproximaciones secuenciales que consideran una única
solución cada vez, sino que trabajan con una población de soluciones y procesan
toda la información que ésta contiene de forma paralela.
El aumento de interés por los AG se debe a que constituyen un método
global y robusto de búsqueda de soluciones de problemas. De hecho, se han
convertido en la técnica metaheurística más empleada [27], existiendo multitud
de estudios previos referidos a su empleo, parametrización e implantación, así
como herramientas informáticas genéricas adaptables a diferentes problemas [28,
29, 30].
Como puntos favorables a los AG se encuentran las siguientes características:
Buen equilibrio alcanzado entre la eficiencia y eficacia para resolver
problemas de grandes dimensiones.
Trabajan con una codificación de parámetros, no con los parámetros
propios.
Utilizan un subconjunto del espacio total para obtener información sobre el
universo de búsqueda, a través de las evaluaciones de la función a optimizar.
3.3 Algoritmos genéticos
35
No están sujetos a restricciones, es decir, no se necesitan conocimientos
específicos sobre el problema a resolver.
Utilizan operadores probabilísticos, en vez de los típicos operadores
determinísticos de las técnicas tradicionales.
Fácil ejecución en arquitecturas paralelas.
Sin embargo, también tienen algunas limitaciones, aunque se pueden superar sin
afectar a la validez de la evolución biológica:
La representación del problema debe ser robusta para que tolere cambios
aleatorios.
La función objetivo debe considerarse cuidadosamente para que se pueda
alcanzar una mayor aptitud y verdaderamente signifique una solución
óptima para el problema dado.
El tamaño de la población y los parámetros de reproducción deben ser
adecuados. Si el tamaño de la población es demasiado pequeño, puede que
el AG no explore suficientemente el espacio de soluciones para encontrar
buenas soluciones. Si el ritmo de cambio genético es demasiado alto o
el sistema de selección se escoge inadecuadamente, puede alterarse el
desarrollo de esquemas beneficiosos y la población puede llegar a ser
errónea, al cambiar demasiado rápido para que la selección llegue a producir
convergencia.
Por último, destacar que los AG no son recomendados para problemas
resolubles de forma analítica, ya que el tiempo de computación sería mucho
más bajo usando los métodos analíticos tradicionales.
3.3.1.
Elementos y operadores de un AG
Una vez comprendido qué es un algoritmo genético, sus pros y sus contras,
es necesario entender una serie de conceptos para poder realizar un algoritmo
genético.
Codificación de las variables
Buscando una analogía con la biología, los AG requieren que las posibles
soluciones al problema, conocido como el conjunto de individuos, se codifique
36
Antecedentes
en un cromosoma. Cada cromosoma tiene varios genes que corresponden a
sendos parámetros del problema. Para poder trabajar con estos genes, es necesario
codificarlos de alguna forma entendible para el ordenador. Este esquema de
codificación es altamente dependiente de las características del problema que
intentemos resolver.
Podemos destacar los siguientes tipos de codificaciones:
Binaria La información se codifica mediante una representación binaria.
Punto flotante Los individuos quedan representados por números reales.
Permutación La información de los individuos se representa mediante una
secuencia ordenada de valores.
La mayoría de las veces, una codificación correcta es la clave de una buena
resolución del problema.
Normalmente, la codificación es estática, pero en casos de optimización numérica,
el número de bits dedicados a codificar un parámetro puede variar, o incluso lo
que representen los bits dedicados a codificar cada parámetro. Algunos paquetes
de algoritmos genéticos adaptan automáticamente la codificación según van
convergiendo los bits menos significativos de una solución.
Población inicial
Habitualmente la población inicial se genera aleatoriamente, formando un
conjunto de cromosomas que representan las posibles soluciones del problema.
En caso de no hacerlo aleatoriamente es importante garantizar que, dentro de la
población inicial, se tenga la diversidad estructural de estas soluciones para tener
una representación de la mayor parte de la población posible o al menos evitar la
convergencia prematura.
Función de evaluación
A cada uno de los cromosomas o individuos de la población se aplicará la función
de evaluación de la aptitud para saber qué tan “buena” es la solución que se está
codificando.
La regla general para construir una buena función de evaluación es que debe
reflejar el valor del individuo de una manera real, pero en muchos problemas
3.3 Algoritmos genéticos
37
de optimización combinatoria, donde existe gran cantidad de restricciones, buena
parte de los puntos del espacio de búsqueda representan individuos no válidos.
Para estos casos, se han propuesto varias soluciones.
Una de ellas es la absolutista, en la que los individuos que no verifican las
restricciones, no son considerados como tales, y se siguen efectuando cruces y
mutaciones hasta obtener individuos válidos, o bien, a dichos individuos se les
asigna una función objetivo igual a cero.
Otra opción, consiste en reconstruir aquellos individuos que no verifican las
restricciones por medio de un nuevo operador que se acostumbra a denominar
reparador.
Otro enfoque consiste en dividir la función de evaluación del individuo por una
penalización que guarda relación con las restricciones que dicho individuo viola.
Dicha cantidad puede simplemente tener en cuenta el número de restricciones
violadas o bien el denominado costo esperado de reconstrucción, es decir el
coste asociado a la conversión de dicho individuo en otro que no viole ninguna
restricción.
Si la computación de la función de evaluación fuese muy compleja, se realizaría
una evaluación aproximada de la función de evaluación.
Operador de selección
Los algoritmos de selección serán los responsables de escoger los individuos que
van a tener oportunidades de reproducirse y cuáles no. Además, como se trata
de imitar lo que ocurre en la naturaleza, se ha de otorgar un mayor número de
oportunidades a los individuos más aptos.
Tras saber la aptitud de cada individuo, se procede a elegir los cromosomas que
serán cruzados en la siguiente generación. Los cromosomas con mejor aptitud
tienen mayor probabilidad de ser seleccionados. Existen varios mecanismos de
selección, las más frecuentemente utilizadas son presentadas a continuación:
Selección por ruleta También llamada selección proporcional a la función de
aptitud o selección de Montecarlo, es la más habitual y permite que
los mejores individuos sean elegidos con una mayor probabilidad, pero
al mismo tiempo permite a los peores individuos ser elegidos, lo cual
puede ayudar a mantener la diversidad de la población, en contraste con
la selección por truncamiento.
Sea N el número de individuos existentes y fi la aptitud o fitness del i-ésimo
38
Antecedentes
individuo. La probabilidad asociada a su selección está dada por:
fi
pi = PN
j=1
fj
El funcionamiento de selección de un individuo por este método es el
siguiente:
1. Cálculo acumulado de las aptitudes de los individuos de la población,
tal que así:
2. Generación de un número aleatorio r[0, 1)
3. Selección del individuo Ii que cumpla que qi−1 < r < qi .
Un problema de la selección de ruleta se presenta ante los superindividuos,
aquellos que poseen una aptitud excesivamente superior al resto. Esto
provoca pérdida de diversidad y puede conducir a convergencia prematura,
pues la mayor parte de los individuos seleccionados será una copia de los
pocos predominantes. En este caso, es preferible utilizar selección basada
en ranking o selección por torneo.
Selección por truncamiento En esta selección los individuos son ordenados
según su función de evaluación y se selecciona una proporción p de los
individuos con mejor aptitud que es reproducida 1/p veces.
Selección basada en ranking Los individuos se ordenan según su función de
evaluación y luego son asignados con una segunda medida, inversamente
proporcional a su posición en el ranking. Los valores de esta segunda
asignación pueden ser lineales o exponenciales. Finalmente, los individuos
son seleccionados proporcionalmente a esta probabilidad.
Este método disminuye el riesgo de convergencia prematura que se produce
cuando se utiliza selección por ruleta en poblaciones con unos pocos
individuos con medidas de desempeño muy superiores a las del resto.
Selección por torneo Esta selección se efectúa mediante un torneo o comparación entre un pequeño subconjunto de individuos, llamado el tamaño del
torneo, elegidos al azar desde la población y donde se va eligiendo al mejor individuo de ese grupo hasta que el número de individuos seleccionados
coincida con el tamaño de la población. Variando el número de individuos
que participan en cada torneo se puede modificar la presión de selección.
Cuando participan muchos individuos en cada torneo, la presión de selección es elevada y los peores individuos apenas tiene oportunidades de reproducción.
3.3 Algoritmos genéticos
39
Los beneficios de este tipo de selección son la velocidad de aplicación, dado que no es necesario evaluar ni comparar la totalidad de la población, y la
capacidad de prevenir, en cierto grado, la convergencia prematura. La principal desventaja es la necesidad de establecer el parámetro correspondiente
al tamaño del subconjunto.
Operador de reproducción
Una vez elegidos los progenitores, en esta fase tiene lugar la reproducción de los
cromosomas, utilizando los operadores genéticos de cruce y de mutación, para
formar la nueva población de individuos.
Operador de cruce Este operador genera dos individuos nuevos, denominados
hijos, a partir de dos individuos seleccionados previamente, denominados
padres o progenitores. Tiene como objetivo que los hijos hereden parte de
la información almacenada en cada uno de los dos padres. Al compartir las
características buenas de dos individuos, la descendencia, o al menos parte
de ella, debería tener una aptitud mayor que cada uno de los padres por
separado.
Generalmente este operador no se aplica a todos los pares de individuos
que han sido seleccionados para reproducirse, sino que se aplica con una
probabilidad aleatoria entre 0.5 y 1.0, denominada probabilidad de cruce.
Si el operador de cruce no llega a aplicarse, entonces la descendencia se
obtiene duplicando a los padres.
Existen varios algoritmos de cruce, sin embargo los más utilizados se
detallan a continuación:
Cruce de un punto También conocida como SPX, consiste en cortar los
cromosomas por un punto aleatoriamente seleccionado para formar
dos partes diferenciadas, la cabeza y la cola, dando lugar a dos nuevos
descendientes. De esta manera, ambos hijos heredan información de
los progenitores como puede observarse en la figura 3.2.
Cruce de dos puntos También llamada DPX, consiste en cortar los cromosomas por dos puntos aleatorios, los cuales no pueden corresponderse
con los extremos de ninguno de los dos cromosomas. De modo que
los descendientes estarán formados por la parte central de uno de los
progenitores y el resto, por los laterales del otro progenitor (figura 3.3).
Se pueden añadir más puntos de cruce dando lugar a operadores
de cruce multipunto, pero diversos estudios desaconsejan esta técnica [31].
40
Antecedentes
Figura 3.2: Cruce de un punto
Figura 3.3: Cruce de dos puntos
Cruce uniforme Comúnmente conocido como UPX, se basa en la realización de una máscara de cruce con valores binarios que nos servirá de
base para generar a los dos descendientes (figura 3.4). Para generar el
primero de ellos, si la primera posición de la máscara es un 1, el primer valor del descendiente se corresponderá con el primer valor del
progenitor A, y en caso contrario, sería el primer valor del progenitor
B, y así sucesivamente. Para generar el segundo descendiente, bastaría
intercambiar los progenitores.
Figura 3.4: Cruce uniforme
Operador de mutación El operador de mutación se aplica a cada hijo de
manera individual y consiste en la alteración aleatoria (normalmente con
probabilidad pequeña) de cada gen componente del cromosoma (figura 3.5).
Al igual que el operador de cruce, el diseño de este operador también está
3.3 Algoritmos genéticos
41
Figura 3.5: Mutación
asociado al esquema de codificación empleado en el AG. En este sentido, el
operador más empleado consiste en cambiar el valor de un gen por otro del
rango de valores permitidos para ese gen. Si se trabaja con codificaciones
binarias, bastaría con negar un bit y sino, bien se podría incrementar o
decrementar a un gen una pequeña cantidad generada aleatoriamente, o
multiplicar un gen por un valor aleatorio próximo a 1.
3.3.2.
Esquema de un AG básico
Los AG trabajan sobre una población de individuos, en la que cada uno de ellos
representa una posible solución al problema que se desea resolver. Todo individuo
tiene asociado un ajuste de acuerdo a la bondad con respecto al problema de
la solución que representa (en la naturaleza el equivalente sería una medida de
eficiencia del individuo en la lucha por los recursos).
El funcionamiento del Algoritmo Genético Simple, también conocido como
Canónico, se presenta en el pseudocódigo 1.
Partimos de un contador de generaciones t que irá actualizándose conforme
vayan surgiendo nuevas generaciones. En primer lugar, se crea una población
inicial Pt cuyo tamaño vendrá determinado por TP y será la que nos proporcione
información para obtener la aptitud de los individuos. Las generaciones irán
realizándose hasta que se cumpla un criterio de parada G. La población Pt creada
anteriormente, sufrirá varios cambios al someterse a un proceso de selección
para determinar los progenitores que se van a reproducir y por otro lado,
mediante el uso de operadores genéticos, como el cruce y la mutación, que serán
aplicados conforme a su probabilidad de aplicación, pc y pm , respectivamente. Los
descendientes resultantes, se insertarán en la población, junto con un individuo
escogido de la población anterior Pt−1 . De este modo, el principio de selección
natural se realiza por selección de progenitores (selección) y selección de
42
Antecedentes
supervivientes para la próxima generación (sustitución). El siguiente paso sería
evaluar la aptitud de la población en conjunto, y finalmente, tras cumplirse la
condición de parada, escoger el mejor individuo ind que representará la mejor
solución x̄ al problema. Las condiciones de parada más usuales son las siguientes:
Los mejores individuos de la población representan soluciones suficientemente buenas para el problema que se desea resolver.
La población ha convergido, es decir, cuando el 95 % de la población tiene
el mismo valor para él o dentro de un rango especificado.
Se ha alcanzado el número de generaciones máximo.
Pseudocódigo 1 Algoritmo genético canónico
Entrada: TP × pc × pm × G × N
Salida: x̄
1: t ← 0
2: Pt ← crear_población_inicial(TP )
3: evaluar_aptitud(Pt )
4: mientras t < G hacer
5:
t←t+1
6:
mientras | Pt |< N hacer
7:
P rogenitores ← selección_individuos_reproducción(Pt−1 )
8:
Descendientes ← realizar_cruce(pc , P rogenitores)
9:
Descendientes_mutados ← realizar_mutación(Pm , Descendientes)
10:
insertar_descendientes(Pt , Descendientes_mutados)
11:
fin mientras
12:
mientras | Pt |< TP hacer
13:
Superviviente ← seleccionar_individuo()
14:
insertar_individuo(Pt , Superviviente)
15:
fin mientras
16:
evaluar_aptitud(Pt )
17: fin mientras
18: ind ← mejor_Individuo()
19: devolver IN D
3.3.3.
Renovación de la población de los AG
Los modos en que los individuos de la población de un AG van evolucionando se
basan en distintas metáforas de la naturaleza:
3.4 Prueba de mutaciones
43
AG generacionales En cada generación se reemplaza la población por la nueva
resultante de aplicar cruces y mutaciones con la población inicial.
Es similar a la forma de reproducción de los insectos, en la que una
generación pone huevos, se aleja geográficamente o muere y es sustituida
por una nueva.
AG permanente En cada generación se sustituyen solamente uno o dos miembros de la población.
Utilizan el esquema generacional de los mamíferos, en el cual coexisten
padres y sus descendientes, lo que permite que los hijos sean educados por
sus progenitores, pero también, que a la larga, se genere competencia entre
ellos.
AG paralelos La población tiene una estructura espacial y tanto la reproducción,
como la selección, se realizan de forma localmente distribuida.
Es muy común en la naturaleza que no sólo exista una población
evolucionando, sino que varias, normalmente aisladas geográficamente,
vayan evolucionando de forma diferente y concurrente.
Modelo de islas La población total se divide en subpoblaciones que
evolucionan independientemente con un AG. Cada cierto número
de generaciones, ocurren migraciones entre ellas, lo que les permite
intercambiar material genético. Esta variación representa una fuente
de diversidad genética. Sin embargo, si un gran número de individuos
emigran en cada generación, ocurre una mezcla global y se eliminan
las diferencias locales. Si la migración no es frecuente, es probable
que se produzca convergencia prematura en las subpoblaciones.
Modelo celular Se basa en colocar a cada miembro en una matriz, de modo
que sólo podrá reproducirse con aquellos que tenga a su alrededor,
generalmente de forma aleatoria o el más apto. El descendiente
generado, pasará a ocupar una posición cercana.
3.4.
Prueba de mutaciones
La prueba de mutaciones [4, 5, 6] es una técnica de pruebas basada en introducir
pequeños fallos sintácticos en el programa original mediante la aplicación de
operadores de mutación. Los programas resultantes se reconocen como mutantes.
Cada operador de mutación modela un tipo de errores que pueden cometer los
44
Antecedentes
programadores. De modo que si una instrucción general es valor > 1000 y
le aplicamos el operador relacional, que cambia el tipo de operador relacional,
podemos obtener como mutante la instrucción valor < 1000. Si un caso de prueba
es capaz de distinguir el programa original del mutante (sus salidas son diferentes)
se dice que ese caso de prueba en particular, mata al mutante. Asimismo, si un caso
de prueba no puede diferenciar el mutante del programa original, podemos decir
que el mutante permanece vivo. En este caso donde el mutante produce la misma
salida que el programa original, estamos ante un mutante equivalente.
Para medir la calidad de un conjunto de casos de pruebas podemos usar su tasa de
mutación que representa el porcentaje de mutantes muertos. La tasa de mutación
viene dada por el cociente entre el número de mutantes muertos y el número de
mutantes no equivalentes.
T asa de M utación =
K
× 100
M −E
Donde K es el número de mutantes muertos, M es el número de mutantes
producidos y la E es el número de mutantes equivalentes. Cuanto mayor sea
el valor de la tasa de mutación, mayor calidad tendrá ese conjunto de casos de
pruebas, ya que significará que será el que mate más mutantes. Sin embargo,
el valor de E no se conoce a priori y es necesario estudiar los mutantes para
identificar aquellos que sean equivalentes.
Por otro lado, también podemos usar la prueba de mutaciones para generar nuevos
casos de prueba que maten a los mutantes que sobrevivan y así, mejorar la calidad
del conjunto de casos de prueba inicial. Esto permitiría aumentar nuestra tasa de
mutación hasta el 100 %, lo que significaría que el conjunto de casos de prueba es
adecuado para detectar todos los fallos modelados por los mutantes.
Uno de los problemas de aplicar la prueba de mutaciones es la existencia de
mutantes equivalentes, ya que no pueden diferenciarse del programa original
al producir la misma salida que éste. Los mutantes equivalentes no deben ser
confundidos con los mutantes resistentes, producidos al no encontrar un caso de
prueba óptimo para detectarlos.
La prueba de mutaciones es una técnica que implica un alto coste computacional
debido a que existen bastantes operadores de mutación que generan muchos
mutantes que luego tienen que ser comparados con el programa original y por
ello surge la Mutación evolutiva [15].
3.4 Prueba de mutaciones
3.4.1.
45
Mutación evolutiva
La prueba de mutaciones evolutiva o EMT está basada en un algoritmo evolutivo
que no genera todos los mutantes, sino sólo aquellos de alta calidad conforme vaya
necesitando el proceso de selección. Ésto reduce su número, favoreciendo a los
vivos o potencialmente equivalentes y dificultando el proceso de matar mutantes.
Estos mutantes de alta calidad pueden usarse para mejorar la calidad el conjunto
de casos de prueba inicial.
Como herramienta de prueba de la mutaciones evolutiva, el grupo UCASE desarrolló GAmera [16], el primer sistema generador de mutantes para composiciones
WS-BPEL basado en un algoritmo genético. Como resultado de las pruebas, se
pudo constatar que el uso de la mutación evolutiva es más efectivo que la mutación tradicional, especialmente en composiciones complejas [15].
Capítulo 4
Descripción general del Proyecto
4.1.
Perspectiva del producto
4.1.1.
Entorno de los productos
El presente Proyecto está formado por GAmeraHOM, un sistema generador de
mutantes de orden superior para composiciones WS-BPEL. Se basa en GAmera
(se verá en detalle en el apartado §4.1.1), una herramienta desarrollada por el
grupo UCASE [16] que consiste en un generador de mutantes de primer orden
para composiciones WS-BPEL, escrito en C++ y que en lugar de generar todos
los mutantes posibles, sólo genera un subconjunto de ellos, es decir, implementa
la técnica de la mutación evolutiva.
GAmeraHOM es una herramienta genérica escrita en Java SE 6, que además de
generar mutantes de orden superior y estar basado en la EMT, permite que el
generador sea extensible y adaptable a cualquier otro lenguaje de programación
con la mínima intervención del desarrollador.
GAmeraHOM está dividido en tres componentes relacionados entre sí:
gamera2-api Modelo de datos e interfaces genéricas.
gamera2-bpel Soporte de WS-BPEL 2.0 para GAmeraHOM.
gamera2-core Núcleo genérico y lanzador por línea de órdenes.
Esta división garantiza que gamera2-bpel sólo dependa de gamera2-api y que
gamera2-core no dependa en absoluto de gamera2-bpel.
48
Descripción general del Proyecto
GAmeraHOM no termina con este proyecto, continuará progresando, añadiendo
nuevas características e incorporando nuevas fases que permitan realizar una
herramienta más eficiente aún, con el posterior estudio de los parámetros que
hagan el algoritmo más óptimo.
GAmera
GAmera [16, 32] es la herramienta para la generación y ejecución automática
de mutantes para composiciones de Servicios Web en WS-BPEL [2]. Incorpora
un mecanismo de optimización que permite seleccionar un subconjunto de los
mutantes totales que pueden generarse. Esto se logra mediante la utilización
de un algoritmo genético que genera y selecciona sólo los mutantes de mayor
calidad, reduciendo el coste computacional que implicaría la ejecución de todos
los mutantes. Los resultados que proporciona esta herramienta permiten mejorar
la calidad de los casos de prueba.
GAmera está constituida por tres componentes principales cuya interacción
podemos observar en la figura 4.1:
Analizador: es el componente de la herramienta que actúa primero.
Recibe como entrada la composición WS-BPEL a probar y determina los
operadores de mutación que se le pueden aplicar.
Generador de mutantes: es el siguiente componente que entra en acción,
partiendo de la información que se recibe del analizador. La herramienta
nos da la posibilidad de generar todos los mutantes posibles, o bien un
subconjunto de éstos que va a ser seleccionado por el ya citado algoritmo
genético.
En este último caso, se llamará al componente denominado “Generador
genético de mutantes”, que está compuesto a su vez por dos elementos.
El primero es el algoritmo genético en sí, denominado “Búsqueda genética
de mutantes”, en el que cada individuo representa a un mutante, capaz de
generar y seleccionar de forma automática un conjunto de mutantes. Esta
selección se realiza aplicando una función de aptitud que mide su calidad
en función de si hay o no casos de prueba que lo matan.
El segundo elemento es el “Conversor”, que transforma un individuo del
algoritmo genético en un mutante WS-BPEL. Para realizar esta conversión,
se utilizan hojas de estilos XSLT, una por cada operador de mutación.
4.1 Perspectiva del producto
49
Analizador
Original WS−BPEL 2.0 program
Contador operadores mutación
GENERADOR DE MUTANTES
Mutantes
potencial.
Mutantes
muertos
Mutantes
erróneos
Algoritmo genético
Conversor
equivalente
Casos de
prueba
Sistema de ejecución
Mutante WS−BPEL 2.0
Figura 4.1: Componentes de GAmera
Sistema de ejecución: a medida que se van generando los mutantes, este
tercer componente los ejecuta frente a un conjunto de casos de prueba,
distinguiéndose tres posibles estados para cada mutante según la salida que
producen:
Muerto La salida del mutante es diferente a la del proceso original para al
menos un caso de prueba.
Vivo La salida del mutante es la misma que la del proceso original para
todos los casos de pruebas suministrados.
Equivalente La salida del mutante y la del programa original es
siempre la misma para todos los casos de prueba.
Resistente El conjunto de casos de prueba no es suficiente para
detectarlo.
Erróneo Se ha producido un error en el despliegue del mutante y no se ha
podido ejecutar. La existencia de este estado permite determinar si el
diseño e implementación de los operadores de mutación es adecuado,
o bien, si se están generando mutantes que no se pueden desplegar.
Para la ejecución del programa original y los mutantes, GAmera emplea
el motor WS-BPEL 2.0, ActiveBPEL 4.1 [33] y BPELUnit [34], una
biblioteca de pruebas unitarias para WS-BPEL que utiliza ficheros XML
para describir los casos de prueba.
GAmera permite visualizar los resultados obtenidos en la ejecución de los
mutantes. Muestra el número total de mutantes generados, el de mutantes muertos,
vivos y erróneos. También muestra estos valores para cada operador de mutación
utilizado. A partir de estos valores se puede medir la calidad del conjunto de casos
de prueba utilizado.
50
Descripción general del Proyecto
4.1.2.
Interfaces de sistema
GAmeraHOM interacciona con MuBPEL, antes conocido como mutationtool, un
sistema de generación y ejecución de mutaciones para WS-BPEL. Puede usarse
para evaluar la calidad del conjunto de casos de prueba al comprobar si existen
diferencias entre el programa original y el mutante generado. Los mutantes son
versiones del programa original pero con alguna pequeña modificación sintáctica.
4.1.3.
Interfaces de usuario
La herramienta GAmeraHOM actualmente no presenta una interfaz gráfica. Para
interactuar con esta herramienta se utilizará la terminal de GNU mediante líneas
de órdenes.
No obstante, uno de los próximos objetivos del grupo es adaptar la interfaz gráfica
de MuBPEL a GAmeraHOM.
4.2.
Funciones del producto
Analizar una composición WS-BPEL para identificar qué instrucciones o
elementos del programa original pueden mutarse.
Parametrizar el algoritmo genético siguiendo una serie de características
incluidas en un archivo de configuración.
Aplicar varios operadores a la composición WS-BPEL original para generar
tantos mutantes como se fijen en la configuración.
Aplicar los operadores de selección, reproducción y generación aleatoria de
individuos para producir individuos optimizados.
Ejecutar la composición WS-BPEL sobre el conjunto de casos de prueba,
para obtener si ha pasado con éxito o no cada uno de los casos.
Ejecutar los mutantes y comparar hasta que se encuentre la primera
diferencia entre la salida de la composición original y las salidas de las
ejecuciones de las mutaciones.
Ejecutar todos los mutantes y comparar la salida de la composición original
con las salidas de las ejecuciones de las mutaciones.
4.3 Características de los usuarios
51
Normalizar los individuos, es decir, obtener una forma canónica de éstos.
Generar información de carácter estadístico que proporcione información
sobre el número de generaciones realizadas, el número de mutantes
generados y un salón de la fama con los mejores individuos que se hayan
generado durante el algoritmo genético.
4.3.
Características de los usuarios
Como ya hemos comentado, GAmeraHOM es un proyecto orientado a la
investigación, así que los usuarios de esta aplicación serán aquellos que necesiten
aplicar algoritmos genéticos para la prueba de software. En principio para
composiciones WS-BPEL, pero extensible a otros lenguajes.
Los usuarios, gracias a este proyecto, podrán analizar el comportamiento de
mutar individuos aplicándole más de un operador de mutación sobre la misma
composición, dando lugar a mutantes de orden superior. Este aspecto tiene gran
interés, porque no existe ninguna otra herramienta que genere mutantes de orden
superior para composiciones WS-BPEL. De hecho, en términos de generadores de
mutantes de orden superior, únicamente se encuentra Milu para el lenguaje C [12].
Aunque el manejo de esta herramienta no es complicado, puede que una persona
inexperta en este dominio no sepa lo que se hace en cada momento o no interprete
correctamente los resultados proporcionados tras la finalización del algoritmo
genético. Por ello, la sección §3 recoge todos los aspectos necesarios para iniciarse
en el tema: Servicios Web (véase §3.1), el lenguaje WS-BPEL (véase §3.2), los
algoritmos genéticos (véase §3.3) y la prueba de mutaciones (véase §3.4).
Tal y como se comentó en la introducción, este proyecto está elaborado dentro del
grupo UCASE de Ingeniería del Software de la Universidad de Cádiz, y aunque
GAmeraHOM puede ser utilizado por cualquier persona, los más indicados serán
los investigadores que estudien el ámbito de los mutantes, en especial con el
lenguaje WS-BPEL y por consiguiente, los miembros de UCASE.
52
Descripción general del Proyecto
4.4.
Restricciones generales
4.4.1.
Control de versiones
El grupo UCASE gestiona la mayoría de sus proyectos mediante Redmine1 [35],
una herramienta para la gestión de proyectos y el seguimiento de errores.
Soporta múltiples proyectos, diferentes roles, seguimiento de errores, diagramas
de Gantt, administración de documentos y lo que es más importante, la gestión de
configuración de software (SCM).
El SCM trata y controla:
La elaboración de código fuente por varios desarrolladores de forma
simultánea.
El seguimiento del estado de las versiones y sus cambios.
La conducción de la integración de las partes del software en un solo
producto de software.
Estos sistemas permiten almacenar todas las versiones de un árbol de ficheros
pudiendo manipular todas las revisiones de cualquier fichero en cualquier
momento. Además de servir como una medida de seguridad contra la pérdida
de información accidental, agilizan los cambios drásticos ya que no hay que
establecer medidas especiales por si fallaran: se pueden revertir los cambios
hechos en cualquier momento.
Se utilizó Subversion [36, 37] como sistema de control de versiones, diseñado
específicamente para reemplazar al popular CVS. Es software libre bajo una
licencia de tipo Apache/BSD.
A diferencia de CVS los archivos versionados no tienen cada uno un número de
revisión independiente, sino que todo el repositorio tiene un único número de
versión que identifica un estado común de todos los archivos del repositorio en un
instante determinado.
El hecho de que se pueda acceder al repositorio a través de la red permite que
varias personas trabajen sobre el mismo repositorio.
Esto fomenta la colaboración, y la calidad no se resiente, ya que si algún cambio
es incorrecto siempre se puede volver a una versión anterior a dicho cambio.
1
https://neptuno.uca.es/redmine/projects
4.4 Restricciones generales
53
Entre las ventajas del uso de Subversion están:
Mantenemos la historia de los archivos y directorios, incluso después de
realizar copias y renombramientos.
Todo los cambios subidos de una sola vez a la forja cuentan como una única
modificación, aunque afecte a varios archivos.
Permite la creación de ramas de una forma mucho mas eficiente que en
CVS.
Al contrario que en CVS, sólo se mandan los cambios que han sufrido los
ficheros, y no el fichero completo.
Maneja los ficheros binarios de forma eficiente.
Permite el bloqueo de archivos para que no sean editados por más de una
persona al mismo tiempo.
Cuando se integra con Apache se puede usar todas las opciones que este
servidor posee para autentificar archivos.
4.4.2.
Lenguajes de programación y tecnologías
Java
Todos los componentes que integran GAmeraHOM han sido desarrollados en
Java, además de por todas las ventajas que presenta su uso, por lograr integridad
con el resto de sistemas con los que se comunica.
Java [38] es un lenguaje de programación orientado a objetos, desarrollado por
Sun Microsystems a principios de los años 90. El lenguaje en sí mismo toma
mucha de su sintaxis de C y C++, pero tiene un modelo de objetos más simple
y elimina herramientas de bajo nivel que suelen inducir a muchos errores, como
la manipulación directa de punteros o memoria. Con respecto a la memoria, su
gestión no es un problema ya que ésta es gestionada por el propio lenguaje y no
por el programador.
Una de las ventajas que ofrece Java es el mecanismo de la “introspección” [39].
Es una técnica bastante potente que permite generar aplicaciones que realizan
operaciones que de otra forma no serían posibles. A través de la introspección,
un programa Java puede cargar un objeto del cual no sabe nada, encontrar sus
variables de instancia, métodos y constructores, y empezar a trabajar con ellos.
54
Descripción general del Proyecto
Para ello utilizamos la API reflection que representa las clases, interfaces y objetos
en la MVJ donde están corriendo. Con esta API se puede saber el nombre de
la clase de un objeto, obtener información sobre los modificadores de clase, sus
campos, métodos, constructores y superclases, saber que declaraciones de método
de una clase pertenecen a una u otra interfaz y crear una instancia de una clase
cuyo nombre no se conoce hasta su ejecución. El hecho de que Java no funcione
directamente sobre el hardware y que tenga una máquina virtual por encima de
éste hace posible esta técnica, cosa que en otros lenguajes no es posible.
Los casos en los que suelen usarse esta herramienta son:
Características de extensibilidad: Una aplicación puede usar clases definidas por el usuario de forma externa para crear instancias de objetos extensibles usando sus nombres totalmente calificados.
Los navegadores de clases y entornos de desarrollo visuales: Un navegador
de clases debe ser capaz de enumerar los miembros de las clases.
Los entornos de desarrollo visuales se pueden beneficiar del uso de la
información que esta herramienta aporta para ayudar a los desarrolladores
a escribir un código más correcto.
Debuggers y herramientas de testeo: Los debuggers deben ser capaces de
examinar los miembros privados de las clases. Las herramientas de testeo
pueden usar esta herramienta para llamar sistemáticamente a la API de una
clase determinada, para asegurar un alto nivel de cobertura en la prueba.
YAML
Los ficheros de configuración que usa GAmeraHOM están escritos siguiendo el
formato YAML. Se ha elegido su uso porque es muy sencillo de utilizar.
YAML [40] es un formato de serialización de datos legible por humanos, fácil
de procesar por las máquinas y fácil de interactuar con los lenguajes de scripts,
inspirado en lenguajes como XML, C, Python, Perl, así como el formato para
correos electrónicos especificado por el RFC 2822. YAML fue propuesto por
Clark Evans en 2001, quien lo diseñó junto a Ingy döt Net y Oren Ben-Kiki.
Este formato fue creado bajo la creencia de que todos los datos pueden ser
representados adecuadamente como combinaciones de listas, hashes (mapeos)
y datos escalares (valores simples). La sintaxis es relativamente sencilla y fue
diseñada teniendo en cuenta que fuera muy legible pero que a la vez fuese
fácilmente mapeable a los tipos de datos más comunes en la mayoría de los
4.4 Restricciones generales
55
lenguajes de alto nivel. Además, YAML utiliza una notación basada en el
indentación y/o un conjunto de caracteres Sigil distintos de los que se usan en
XML, haciendo que sea fácil componer ambos lenguajes.
Sus principales características son las siguientes:
Utiliza la tabulación para indicar su estructura.
Los elementos que forman una secuencia utilizan un guión medio.
La estructura del documento se denota indentando con espacios en blanco;
sin embargo no se permite el uso de caracteres de tabulación para indentar.
Los contenidos en YAML se describen utilizando el conjunto de caracteres
imprimibles de Unicode, bien en UTF-8 o UTF-16.
Los miembros de las listas se denotan encabezados por un guión con un
miembro por cada línea, o bien entre corchetes y separados por una coma y
un espacio.
Los arrays asociativos se representan usando los dos puntos seguidos por
un espacio en la forma clave : valor, bien uno por línea o entre llaves y
separados por coma seguida de espacio.
Un valor de un array asociativo viene precedida por un signo de interrogación, lo que permite que se construyan claves complejas sin ambigüedad.
Los valores sencillos (o escalares) por lo general aparecen sin entrecomillar,
pero pueden incluirse entre comillas dobles o comillas simples.
En las comillas dobles, los caracteres espaciales se pueden representar con
secuencias de escape similares a las del lenguaje de programación C, que
comienzan con una barra invertida.
Se pueden incluir múltiples documentos dentro de un único flujo, separándolos por tres guiones. Los tres puntos indican el fin de un documento dentro
de un flujo.
Los nodos repetidos se pueden denotar con un ampersand y ser referidos
posteriormente usando el asterisco.
Los comentarios vienen encabezados por la almohadilla y continúan hasta
el final de la línea.
56
Descripción general del Proyecto
Los nodos pueden etiquetarse con un tipo o etiqueta utilizando el signo de
exclamación seguido de una cadena que puede ser expandida en una URL.
Los documentos YAML pueden ser precedidos por directivas compuestas
por un signo de porcentaje seguidos de un nombre y parámetros delimitados
por espacios.
Maven
Maven [41] es una herramienta diseñada para la gestión y construcción de
proyectos Java. Fue creada por Jason van Zyl, de Sonatype, en 2002. Su
funcionalidad es parecida a Apache Ant, y en menor medida a PEAR de PHP
y CPAN de Perl, pero tiene un modelo de construcción más simple, basado en
XML. Inicialmente estaba dentro del proyecto Jakarta, pero actualmente es un
proyecto de nivel superior de la Apache Software Foundation.
Usa un fichero POM para describir el proyecto software a construir. En él se
indican sus dependencias de otros módulos y componentes externos; y el orden de
construcción de los elementos. La diferencia fundamental con Apache Ant es que
se escriben de forma declarativa, en vez de en forma imperativa; es decir, en vez
de indicar cómo construir algo, se dice qué hay que construir, y la convenciones
de Maven controlarán el proceso de construcción.
Maven está listo para usar en red, ya que su motor puede descargar dinámicamente
los plugins de un repositorio. Dicho repositorio provee acceso a muchas
versiones de diferentes proyectos Open Source en Java, de Apache y de otras
organizaciones. Este repositorio y su sucesor reorganizado, Maven 2, intentan
ser el mecanismo por defecto de distribución de aplicaciones en Java, pero su
adopción está siendo lenta. Maven permite subir artefactos al repositorio al final
de la construcción de la aplicación, de forma que cualquier usuario tiene acceso a
ella.
Usa una arquitectura basada en plugins que permite que utilice cualquier
aplicación controlable a través de la entrada estándar. En teoría, esto permite que
cualquiera pueda escribir sus propios plugins para su interfaz con herramientas
como compiladores, herramientas de pruebas unitarias, etc. para cualquier otro
lenguaje; pero en la realidad, Maven apenas soporta otros lenguajes distintos
a Java. Está construido alrededor de la idea de reutilización de la lógica de
construcción: los proyectos se construyen generalmente con patrones similares;
una elección lógica sería reutilizar los procesos de construcción. La idea no
es reutilizar el código o funcionalidad, sino cambiar la configuración el código
escrito.
4.4 Restricciones generales
57
Los proyectos en Maven cuentan con una serie de etapas, llamadas ciclo de vida.
Para pasar de etapa, es necesario haber completado con éxito las etapas anteriores.
Estas etapas representan las distintas fases por las que un proyecto software ha de
pasar: compile, test, package, install y deploy.
4.4.3.
Herramientas de desarrollo
Eclipse
Eclipse [17] es un entorno de desarrollo integrado de código abierto. Fue
creado originalmente por IBM como el sucesor de VisualAge. Actualmente es
desarrollado por la Fundación Eclipse, una organización independiente sin ánimo
de lucro que fomenta una comunidad de código abierto y un conjunto de productos
complementarios. Se liberó originalmente bajo la Common Public License, pero
después fue relicenciado bajo la Eclipse Public License; Sin embargo, la Free
Software Foundation ha determinado que ambas licencias, aún siendo software
libre, son incompatibles con la Licencia pública general de GNU.
El IDE de Eclipse emplea módulos para proporcionar toda su funcionalidad
al frente de la plataforma de cliente enriquecido, a diferencia de los entornos
monolíticos, donde todas las funcionalidades están incluidas, tanto si les son
útiles al usuario, como si no. Con este sistema de módulos, el usuario tiene un
entorno ligero, personalizado según sus necesidades. Con estos módulos, podemos
extender la funcionalidad de Eclipse a otros lenguajes de programación, como
C/C++ o Python; a lenguajes de procesado de texto, como LATEX; aplicaciones en
red como Telnet y sistemas de gestión de bases de datos.
Dispone de un editor de texto con resaltado de sintaxis; compilación en tiempo
real, pruebas unitarias con JUnit, control de versiones con CVS, integración
con Ant, asistentes para la creación de proyectos, clases, test, entre otros, y
refactorización. Haciendo uso de los plugins, se puede añadir control de versiones
con Subversion e integración con Hibernate.
4.4.4.
Sistemas operativos y hardware
GAmeraHOM ha sido desarrollado y probado sobre GNU/Linux, ejecutando la
versión 11.04 de la distribución Ubuntu.
En cuanto al hardware se recomienda disponer de una máquina con una memoria,
de al menos 1GB de RAM.
58
4.4.5.
Descripción general del Proyecto
Bibliotecas y módulos usados
activation Usado para gestionar datos de tipo MIME.
saaj-api Suministra una manera estándar de enviar documentos XML sobre
Internet desde la plataforma Java.
servlet-api Interfaz que permite que ciertos módulos java, servlets, extiendan las
capacidades de los servidores web.
cloning Pequeña biblioteca de código abierto que puede clonar cualquier objeto
Java.
commons-codec Destinado a codificar/decodificar algoritmos.
commons-collections Ampliación del framework de colecciones Java.
commons-io Colección de utilidades de E/S.
commons-lang Proporciona una funcionalidad extra a las clases de java.lang.
commons-logging Interfaz de una gran variedad de implementaciones de la API
de registro.
hamcrest-core Biblioteca que nos provee de una serie de matchers que podemos
utilizar para escribir tests con un lenguaje más cercano al natural, de manera
que se hace más sencillo comprender que están comprobando nuestros tests.
jdom Biblioteca de código abierto para manipulaciones de datos XML optimizados para Java.
jetty Servidor HTTP basado en Java y contenedor de Servlets escrito en Java.
jopt-simple Analizador de línea de comandos fácil de usar, guiado por pruebas,
especialmente diseñado para programas escritos en Java.
junit Framework que permite realizar la ejecución de clases Java de manera
controlada, para poder evaluar si el funcionamiento de cada uno de los
métodos de la clase se comporta como se espera.
log4j Biblioteca de código abierto desarrollada en Java por la Apache Software
Foundation que permite a los desarrolladores de software elegir la salida y
el nivel de granularidad de los mensajes o logs en tiempo de ejecución.
4.5 Requisitos para futuras versiones
59
mockito-core Biblioteca de código abierto para prueba de aplicaciones Java que
se basa en el principio de un objeto mock que simula el comportamiento
de otro objeto. Permite simular comportamientos complejos de objetos,
además facilita el desarrollo de test unitarios y la detección de errores.
objenesis Biblioteca para instanciar objetos Java.
saxon Procesador de XSLT y XQuery.
slf4j-api Proporciona una API de registro Java a través de un simple patrón de
fachada.
snakeyaml Procesador de YAML.
stax-api StAX sirve para leer y escribir documentos XML.
truezip Framework basado en Java que permite acceder a archivos ZIP, TAR y
derivados de una forma bastante transparente desde Java, como si se tratara
de directorios no comprimidos.
velocity Motor de plantillas basado en Java.
wsdl4j API que permite la creación, representación y manipulación de documentos WSDL.
xmlbeans Herramienta que permite acceder a todo el potencial de XML desde
Java de una forma amigable.
4.5.
Requisitos para futuras versiones
Gracias a que GAmeraHOM se ha hecho lo más extensible y adaptable posible,
si se quiere utilizar para un lenguaje distinto de WS-BPEL tan sólo tendríamos
que sustituir el componente gamera2-bpel por gamera2-java, gamera2-ecl, o
cualquier otro, siendo independiente del núcleo gamera2-core.
Del mismo modo, si se quieren crear nuevos generadores de individuos, nuevos
operadores de selección, nuevas condiciones de parada o incluso nuevos loggers,
para que el algoritmo genético los use, sólo tendríamos que reflejarlo en el fichero
de configuración YAML para su posterior uso.
Capítulo 5
Desarrollo del Proyecto
5.1.
Metodología de desarrollo
La elaboración de un producto software de calidad requiere la aplicación de
una metodología durante todo su desarrollo. Aunque no existe una definición
estricta del concepto metodología de desarrollo, ésta puede considerarse como
un conjunto de pasos y procedimientos que deben seguirse para desarrollar un
producto software.
El tipo de metodología que se ha seguido con este proyecto corresponde a las
llamadas metodologías ágiles [42], que se basan en la adaptabilidad de cualquier
cambio como medio para aumentar las posibilidades de éxito de un proyecto. Los
principios de esta filosofía se reúnen en el conocido Manifiesto Ágil:
1. Valorar más a los individuos y su interacción que a procesos y herramientas.
Es obvio que los procesos ayudan al trabajo y que las herramientas son una
guía de operación. Sin embargo, el apoyo que se ha tenido por parte de los
miembros del grupo UCASE ha sido incondicional, influyendo de manera
notable en este Proyecto. Los seminarios que se hacían semanalmente dan
la oportunidad de comentar el estado del proyecto que cada persona estaba
llevando a cabo y comentar problemas que habían surgido o simplemente,
atender sugerencias.
2. Valorar más el software que funciona que la documentación exhaustiva.
El hecho de poder ver anticipadamente cómo se comportan algunas de las
funcionalidades del producto que se está desarrollando ofrece un feedback
muy enriquecedor que genera ideas y posibilidades imposibles de concebir
62
Desarrollo del Proyecto
en un primer momento, y difícilmente podrían haber sido incluidas en
un documento de especificación de requisitos. De hecho, así ha ocurrido
durante la realización de GAmeraHOM en la que hemos tenido que
modificar varias veces la estructura interna de los elementos, conforme se
avanzaba en el desarrollo del algoritmo genético.
3. Valorar más la colaboración con el cliente que la negociación contractual.
Este punto se encuentra íntimamente relacionado con el punto 1. La
metodología ágil está especialmente indicada para productos difíciles de
definir con detalle en el principio y en este caso, GAmeraHOM así lo era.
Aunque se tenía la idea de lo que debía hacer, en sus inicios no estaba muy
claro el cómo. Por ello, fue necesario gente experta tanto en el campo de la
algoritmia genética, como en el lenguaje de programación elegido para tal
fin.
4. Valorar más la respuesta al cambio que el seguimiento de un plan.
Como se comentó en el punto 2, GAmeraHOM sufrió varios cambios
importantes durante su desarrollo. Dichos cambios eran trascendentales
porque lo que se modificaba era la estructura interna. Ésto no supuso un
gran problema, ya que se tuvo más en cuenta la capacidad de respuesta, que
la de seguimiento y aseguramiento de planes preestablecidos.
En particular, dentro del grupo de metodologías que ofrece la metodología
ágil, nos hemos guiado por la eXtreme Programming que explicaremos en los
siguientes apartados.
5.1.1.
Origen
La metodología XP es un enfoque de la ingeniería del software formulado por
Kent Beck. Es el más destacado de los procesos ágiles de desarrollo de software.
Al igual que éstos, XP se diferencia de las metodologías tradicionales principalmente en que pone más énfasis en la adaptabilidad que en la previsibilidad.
Las raíces de la XP yacen en la comunidad de Smalltalk, y en concreto de la
colaboración entre Kent Beck, Ward Cunningham y Ron Jeffries que, desde finales
de los 80, fueron extendiendo sus ideas de un desarrollo de software adaptable y
orientado a la gente.
El paso crucial de la práctica informal a una metodología ocurrió en la primavera
de 1996. A Kent se le pidió revisar el progreso del proyecto de nómina C3
5.1 Metodología de desarrollo
63
para Chrysler. El proyecto estaba siendo llevado en Smalltalk por una compañía
contratista y estaba en problemas. Debido a la baja calidad de la base del código,
Kent recomendó empezar desde cero. El proyecto entonces reinició bajo su
dirección, convirtiéndose en el campo de entrenamiento de la metodología XP.
Las ideas primordiales de su sistema las comunicó en la revista C++ Magazine en
una entrevista que ésta le hizo el año 1999. En ésta decía que estaba convencido
que la mejor metodología era un proceso que enfatizase la comunicación dentro
del equipo, que la implementación fuera sencilla, que el usuario tenía que estar
muy informado e implicado y que la toma de decisiones tenía que ser muy rápida
y efectiva.
Kent Beck, Ward Cunningham y Ron Jeffries fueron a la web Portland Pattern
Repository y empezaron a hablar de la metodología XP y promocionarla, de lo que
era y cómo realizarla. Sin embargo, este hecho llegó a molestar a buena parte de
la comunidad que intentaba discutir sobre temas de programación. Fue tanta esta
molestia que nació el fenómeno XP Free Zone (zona libre de XP) en determinadas
webs como petición de no hablar de Programación Extrema en ella.
No obstante, en 1999, la popularidad de XP aumentó con la publicación del primer
libro sobre la materia [43] escrito por Kent.
5.1.2.
Características
XP es una metodología ágil de desarrollo de software, aplicable por lo general a
proyectos de pequeño y medio tamaño, en un equipo de hasta 12 personas.
En los métodos ágiles, se descarta todo documento o procedimiento innecesario
para el proyecto, permitiendo al equipo avanzar rápidamente concentrándose en
lo importante y sin perder tiempo en formalismos.
En XP, los detalles se comunican en conversaciones directas entre las partes
implicadas (incluyendo al cliente), aclarando confusiones y dudas en el momento.
Así, XP se dirige más a las personas que al proceso, y más a la obtención de
software útil que al seguimiento de un proceso rígido y burocrático.
En cada iteración, se entrega una versión funcional del software que el cliente
puede probar para ampliar la información disponible en la siguiente iteración.
Una idea que se suele tener respecto a XP es que no se realiza documentación
en absoluto, sea lo que sea. El requisito de documentación externa al proyecto es
muy común, por ejemplo, y debe ser atendido. Ron Jeffries trata de corregir éste
y otros malentendidos en [44].
64
Desarrollo del Proyecto
A diferencia de otras metodologías, donde el cliente es una entidad externa al
proyecto con el que se sólo se comunica el analista, en XP es una parte integral del
equipo. Se ocupa de formular los requisitos a nivel conceptual, darles su prioridad,
y resolver dudas que pueda tener el resto del equipo.
XP nos recuerda así que el software existe para dar un valor añadido al cliente, y
no por sí mismo. Así, las decisiones acerca de la funcionalidad deseada son del
cliente, y las decisiones técnicas y el calendario lo establecen los desarrolladores.
Valores
Los valores originales de la programación extrema son: simplicidad, comunicación, retroalimentación y coraje. Un quinto valor, respeto, fue añadido en la segunda edición de Extreme Programming Explained [43].
Simplicidad Se simplifica el diseño para agilizar el desarrollo y facilitar el
mantenimiento. Para mantener la simplicidad es necesaria la refactorización
del código, ésta es la manera de mantener el código simple a medida que
crece. También se aplica la simplicidad en la documentación, de esta manera
el código debe comentarse en su justa medida, intentando eso sí que el
código esté auto documentado. Para ello se deben elegir adecuadamente
los nombres de las variables, métodos y clases. Los nombres largos no
decrementan la eficiencia del código ni el tiempo de desarrollo gracias a las
herramientas de auto completado y refactorización que existen actualmente.
Aplicando la simplicidad junto con la autoría colectiva del código y la
programación por parejas se asegura que cuanto más grande se haga el
proyecto, todo el equipo conocerá más y mejor el sistema completo.
Comunicación Para los programadores el código comunica mejor cuanto más
simple sea. Si el código es complejo hay que esforzarse para hacerlo legible.
El código auto documentado es más fiable que los comentarios ya que
éstos últimos pronto quedan desfasados con el código a medida que es
modificado. Debe comentarse sólo aquello que no va a variar, por ejemplo
el objetivo de una clase o la funcionalidad de un método. Las pruebas
unitarias son otra forma de comunicación, ya que describen el diseño de
las clases y los métodos al mostrar ejemplos concretos de como utilizar
su funcionalidad. Los programadores se comunican constantemente gracias
a la programación por parejas. La comunicación con el cliente es fluida
ya que el cliente forma parte del equipo de desarrollo. El cliente decide
que características tienen prioridad y siempre debe estar disponible para
solucionar dudas.
5.1 Metodología de desarrollo
65
Retroalimentación Los desarrolladores reciben a menudo correcciones o modificaciones por parte de los clientes. Los clientes, además, deben comprobar
que el software es adecuado de acuerdo con sus necesidades establecidas
de antemano. Todo esto conllevará constantes revisiones del código de los
programas. Las parejas de programadores y el equipo deben mostrar resultados al cliente y el cliente indicar si el proceso es el correcto. Se realizan
bloques de test para la práctica totalidad de los módulos de los programas,
lo que garantiza su funcionamiento y posteriormente se integran unos programas con otros que se implementan. Por otra parte, los errores deben de
ser detectados con la máxima antelación posible.
Coraje El coraje es un valor que se aplica a varios aspectos, al diseñar y codificar
para las necesidades actuales en lugar de las futuras, al alentar a los
programadores a mejorar el código sin afectar el comportamiento externo
(refactoring), al reconocer cuando alguna parte del código ya no sirve, al
ser persistente al buscar la solución de un problema.
Respeto En XP los miembros del equipo de trabajo deben respetarse entre si, para
nunca incorporar cambios que hagan fallar las pruebas o retrasen el trabajo
de otra persona. Una forma de respeto al trabajo propio es siempre buscar la
mas alta calidad y las mejores soluciones al desarrollar el producto. Nadie
en el equipo de trabajo debe sentirse despreciado o ignorado ya que esto
mejora la motivación de todos para conseguir los objetivos del proyecto.
Para seguir esos valores, se proponen una serie de principios, que se concretan a
través de una serie de prácticas recomendadas.
Principios
XP se fundamenta en doce principios básicos agrupados en cuatro categorías:
Retroalimentación
Principio de pruebas Período de tiempo de pruebas de aceptación del programa en el que se establecerán los resultados esperados. Estas pruebas tienen que estar automatizadas de manera que permitan realizar
múltiples simulaciones del sistema una vez que esté funcionando. Un
ejemplo de este tipo ambientes para Java es JUnit.
Proceso de planificación El usuario deberá escribir todas sus necesidades,
especificando las actividades concretas que realizará sistema. Se
66
Desarrollo del Proyecto
elaborará un documento llamado Historias del usuario (User Stories).
Durante esta fase serán necesario ir realizando reuniones periódicas
con todo el equipo de desarrollo si se estima conveniente.
Cliente en el sitio Al cliente se le dará el permiso para establecer la
funcionalidad, determinar los requisitos, matizar las prioridades y
responder a las preguntas de los programadores. De esta manera se
conseguirá una fuerte interacción cara a cara con el programador,
reduciendo drásticamente el tiempo de comunicación y la cantidad de
documentación, así como los altos costes de su elaboración.
Programación en parejas Consiste en que todos los programadores deberán escribir su código en parejas, compartiendo una única máquina. Se
producirán aplicaciones más buenas, consistentes y a bajo coste. Este
constituye uno de los principios más polémicos y radicales de XP, y
mucha gente duda de su efectividad.
Proceso continuo
Integración continua Los programadores pueden resumir su código y
reconstruir el sistema varias veces al día. Se reducen los problemas
de integración comunes en proyectos largos y estilo cascada.
Refactorización Los programadores evalúan continuamente el diseño y
recodifican lo necesario, obteniéndose un sistema que minimice el
código duplicado e ineficiente. A través de todo el proceso de
desarrollo, los programadores mejoran el diseño del sistema.
Entregas pequeñas Consiste en establecer un sistema simple y sencillo
de entregas que se actualice constantemente, de manera que estas
entregas no puedan pasar las dos o tres semanas como máximo. Se
permite que el verdadero valor del negocio del producto sea evaluado
en un ambiente real.
Entendimiento compartido
Diseño simple Consiste en desarrollar programas lo más sencillos posibles,
que cumplan en todo momento con los requisitos, de manera que se
proporcione un sistema que satisfaga las necesidades inmediatas del
cliente. Se rejuvenecen los diseños obsoletos de forma sencilla y se
eliminan redundancias.
Metáfora Define una historia de como funciona el sistema completo.
Gracias a este principio, se logra sustituir los sistemas tradicionales
de diagramas y modelos UML por breves descripciones de un trabajo
de un sistema.
5.1 Metodología de desarrollo
67
Propiedad colectiva del código Defiende el tener un código con propiedad compartida, de manera que nadie es el propietario de nada, y todos
son el propietario de todo. Cuanta más gente haya trabajando en una
pieza, menos errores aparecerán.
Estándar de codificación Define una serie de reglas para escribir y
documentar el código, así como la comunicación entre diferentes
piezas de código desarrolladas por equipos diferentes. El código en
el sistema se verá como si hubiera sido escrito por una sola persona.
Bienestar del programador
Semana de 40 horas Consiste en minimizar las horas extras de los programadores, de manera que se mantengan frescos, pues los programadores cansados escriben código de menor calidad. Así, se genera un
código de mayor calidad.
En este proyecto no ha sido posible cumplir con todos los principios comentados
en el apartado anterior.
La “programación en parejas” que consiste en que dos programadores
trabajen juntos en el mismo ordenador, no se cumplió por la propia filosofía
del PFC. No obstante, se han llevado a cabo revisiones del código aunque
no de forma simultánea.
La “semana de 40 horas” tampoco ha sido posible, ya que tal y como
se comentó en la sección §2, la elaboración del PFC nunca ha tenido
dedicación exclusiva al compatibilizarse con otras actividades, lo que ha
aumentado el cómputo total de horas semanales dedicadas a alguna tarea
que requiera esfuerzo.
En el siguiente apartado, se comentan los principios que sí se han seguido y la
forma en la que se han llevado a cabo.
Prácticas
Historias de usuario Describen una funcionalidad o propiedad deseada del
sistema, en palabras del usuario y no del desarrollador. Mediante ellos se
pueden expresar todo tipo de requisitos, no sólo los funcionales, y en ellos
se basan las pruebas de aceptación.
68
Desarrollo del Proyecto
Es una técnica completamente diferente de la de casos de uso, ya que una
historia es algo mucho más concreto, generalmente pequeño y fácilmente
estimable. Un caso de uso se podría ver como una clase de interacciones
concretas que el sistema debe plasmar. Ambos describen el qué, pero lo
hacen bajo distintos enfoques. XP contempla la utilización de los diagramas
de casos de usos como una posible herramienta de apoyo, que sirva de
generalización de una o varias historias de usuario particulares.
El equipo de desarrollo puede realizar estimaciones del esfuerzo que
requeriría una historia y presentárselas al cliente, dándole más información
para decidir qué historias quiere implementadas en cada iteración. Puede
que se decida posponer una historia, o dividirla en varias.
En lo que respecta a este PFC, los directores de este proyecto han sido los
“clientes”, y por consiguiente, los usuarios potenciales del proyecto.
Modelo INVEST El modelo INVEST es la clave para pensar y escribir
buenas historias de usuario:
Independiente: Las historias deben ser independientes de otras para
que sea más fácil la planificación, priorización y estimación.
Negociable: La tarjeta de la historia es tan sólo una descripción corta
que no incluye detalles.
Valiosa: Cada historia tiene que tener valor para el cliente.
Estimable: Las historias deben ser estimables para permitir su
priorización y planificación.
Pequeña: Las historias deben ser pequeñas en esfuerzo, no suponiendo
más de 2-3 personas/semana de trabajo.
Testeable: Las historias deben poder probarse.
Integración continua La prueba e integración de los cambios se realiza de forma
continua y a pequeños pasos. Esto se sigue del hecho de que corregir los
fallos introducidos en el software es tanto más complicado cuanto más
amplios sean los cambios.
Ciclo quincenal La planificación se ha realizado en ciclos cortos, de duración
aproximada de quince días, y se ha mantenido una comunicación asidua
con los “clientes”, en este caso los directores del proyecto vía presencial y
online.
Compilación en diez minutos La idea consiste en mantener siempre el tiempo
de compilación y ejecución de todas las pruebas automáticas pertinentes por
5.1 Metodología de desarrollo
69
debajo de 10 minutos, para poder realizar integración continua del código
de todo el equipo y evitar tanto problemas de integración de última hora
como esperas innecesarias.
Desarrollo orientado a pruebas Los componentes más importantes de GAmeraHOM han sido desarrollados de esta forma usando JUnit. La secuencia
seguida cada vez que queremos dotar al sistema de una nueva característica
es la siguiente:
1. Diseñar y añadir una prueba: Esta prueba fallará porque se escribe
antes de que se haya implementado la característica en sí. Para
escribir una prueba, el desarrollador debe entender claramente la
especificación y los requisitos de la característica. Esto se puede llevar
a cabo a través de casos de uso e historias de usuario que cubran los
requisitos y las condiciones de excepción.
2. Ejecutar las pruebas y comprobar que la última que se ha añadido falla:
Ésto valida que las pruebas están funcionando correctamente y que
las pruebas añadidas no pasan inesperadamente, sin la necesidad de
código nuevo.
3. Implementar la característica: Se añade o modifica el código para
que se puedan pasar las pruebas añadidas. El código escrito en esta
etapa no será perfecto y puede, por ejemplo pasar la prueba de una
forma poco elegante. Esto es aceptable porque en pasos sucesivos se
mejorará y perfeccionará. Es importante resaltar que el código escrito
sólo se diseña para pasar la prueba.
4. Ejecutar las pruebas automatizadas: Si todas las pruebas tienen éxito,
el programador puede estar seguro de que el código cumple todos los
requisitos probados. En caso contrario, retrocederá al paso anterior
para hacer las modificaciones pertinentes, y así hasta que el código
pase todas las pruebas.
5. Mejorar el diseño: se refactoriza el código para mejorar la calidad
del diseño. Una vez modificado el código, se vuelven a ejecutar las
pruebas para comprobar que la refactorización no ha dañado ninguna
funcionalidad existente.
Diseño incremental Las metodologías tradicionales intentaban realizar el análisis y diseño de antemano, siguiendo el modelo de la ingeniería tradicional.
Se realizaba la analogía entre la construcción de una casa y la de un proyecto
software: una vez estaban implantados los cimientos, cambiar la estructura
del edificio era varios órdenes de magnitud más caro. Sin embargo, para la
70
Desarrollo del Proyecto
metodología XP, el diseño del programa no es algo que se haga una sola vez
y quede fijo por el resto de la vida del programa. Sino que se debe refinar
continuamente en función de las necesidades del momento.
Por ello, para evitar el aumento del coste de las modificaciones, se dispone
de otras prácticas además de ésta, como el uso de pruebas automáticas,
la compartición de código, la programación en parejas y la comunicación
fluida con el resto del equipo.
5.2.
Herramientas de modelado usadas
5.2.1.
BOUML
BOUML es una aplicación UML 2.0 que permite definir y generar código en C++,
Java, Idl, PHP y Python a partir de diagramas UML, realiza ingeniería inversa de
Java/C++, y permite dibujar diversos diagramas UML 2.0, como los diagramas de
clases, despliegue, componentes o casos de uso, entre otros. Es compatible con
Unix/Linux/Solaris, MacOS X y Windows en la web http://bouml.free.fr,
es muy rápido y no requiere mucha memoria para manejar varios miles de clases.
Está escrito en C++ usando la versión 3.3.8 de la biblioteca Qt de la compañía
Trolltech, conocida por ser la biblioteca sobre la cual se halla implementado el
gestor de escritorio KDE.
5.3.
Especificación de los requisitos del sistema
La parte más crítica en la construcción de un sistema software es decidir cómo
construirlo. La ingeniería de requisitos facilita el mecanismo apropiado para
comprender lo que quiere el cliente, analizando necesidades, confirmando su
viabilidad, negociando una solución razonable, especificando la solución sin
ambigüedad, validando la especificación y gestionando los requisitos para que
se transformen en un sistema operacional.
Un requisito puede definirse como una condición que debe cumplir o poseer un
sistema o alguno de sus componentes para satisfacer un contrato, una norma o una
especificación o, dicho de otra manera más simple, una propiedad que debe tener
para poder solucionar un problema del mundo real.
5.3 Especificación de los requisitos del sistema
5.3.1.
71
Requisitos de interfaces externas
Esta sección incluye una descripción detallada de los requisitos de conexión a
otros sistemas con los que el sistema debe interactuar.
En primer lugar, todos los parámetros de configuración de GAmeraHOM son
recogidos por un fichero YAML. Tendremos que asegurarnos de que esté bien
escrito y que cumpla con las normas de generación de documentos de este tipo
(véase §4.4.2).
Para que esta herramienta pueda funcionar necesita los operadores de mutación
definidos para WS-BPEL 2.0 [45, 46]. Sin estos operadores, esta herramienta no
podría generar los mutantes a partir del código original escrito en WS-BPEL y,
por tanto, no se podría llevar a cabo el análisis de mutaciones, proceso que mide
la calidad conjuntos de casos de prueba.
Los resultados obtenidos de ejecutar GAmeraHOM deben poder almacenarse por
el uso de un Logger que bien imprimirá por pantalla, o volcará los resultados a un
fichero de texto determinado.
5.3.2.
Requisitos funcionales
Un requisito funcional define el comportamiento interno del software: cálculos,
detalles técnicos, manipulación de datos y otras funcionalidades específicas que
muestran cómo los casos de uso serán llevados a la práctica. Los requisitos
funcionales establecen los comportamientos del sistema.
Los requisitos funcionales de GAmeraHOM son los siguientes:
Analizar una composición WS-BPEL, es decir, identificar qué instrucciones
o elementos del programa original pueden mutarse. El resultado de este
análisis debe contener para cada operador de mutación las instrucciones en
las que el operador puede ser aplicado, así como sus atributos.
Aplicar un operador a la composición WS-BPEL original para generar un
mutante. Para ello, deberá indicarse el operador, la localidad (instrucción) y,
en algunos casos, también el valor del atributo. El operador, la instrucción
y el valor del atributo representan a un individuo.
Generar un determinado número de mutantes a través de los generadores de
individuos definidos.
72
Desarrollo del Proyecto
Aplicar operadores de selección para escoger individuos dentro de la
población de soluciones.
Aplicar operadores genéticos para mutar individuos y completar la población con individuos más aptos.
Ejecutar la composición WS-BPEL sobre el conjunto de casos de prueba,
para obtener si ha pasado con éxito o no cada uno de estos casos.
Ejecutar todos los mutantes y comparar la salida de la composición original
con las salidas de las ejecuciones de las mutaciones.
Normalización de individuos.
5.3.3.
Requisitos de información
Este tipo de requisitos describen qué información debe almacenar el sistema
para satisfacer las necesidades de clientes y usuarios. Identifican los conceptos
relevantes sobre los que se debe almacenar información y los datos específicos
que serán de interés.
Cada individuo será representado por tripletas compuestas por el operador,
la localidad y el atributo. Existirán tantas tripletas como se definan en la
configuración. Cada tripleta representa una mutación aplicada al programa
original. Mientras que GAmera manejaba mutantes con un único cambio,
GAmeraHOM trabaja con mutantes con más de un cambio, por eso se les
conoce como mutantes de orden superior.
Los individuos deben normalizarse antes de su ejecución, para que el
sistema reciba su valor real dentro del rango correspondiente.
La composición WS-BPEL original, el conjunto de casos de prueba, las
salidas de ejecución y los mutantes del HOF podrán almacenarse en ficheros
indicando la ubicación deseada en el fichero YAML de configuración.
5.3.4.
Requisitos de reglas de negocio
Las reglas de negocio definen restricciones, reglas o políticas del negocio que
deben ser respetadas por el sistema a desarrollar.
5.4 Análisis del sistema
73
Siempre se realizarán mutaciones de orden superior, es decir, cada mutante
se generará al aplicar uno o varios operadores sobre la composición WSBPEL original. Tantos como se especifiquen en el fichero YAML de
configuración.
5.3.5.
Atributos del sistema software
A continuación se especifican las propiedades que debe tener GAmeraHOM.
Rendimiento: El sistema debe tener un alto rendimiento porque ahora
estamos tratando con mutantes de orden superior, lo que requerirá una gran
esfuerzo al generar mutantes y al comparar las salidas de ejecución.
Fiabilidad: Todas las mutaciones deben realizarse correctamente y las
comparaciones entre salidas deben ser muy fiables, puesto que serán
fundamentales para realizar el análisis de mutaciones.
Mantenibilidad: Es fundamental para que posteriores ampliaciones y
correcciones se hagan de forma rápida y sencilla. De ahí que la división
de componentes comentada en §4.1.1 se mantenga durante todo el ciclo de
vida de GAmeraHOM.
Facilidad de instalación: Controlando el número de dependencias externas
y, cuando esto no sea posible, reduciendo su impacto en la complejidad de
la instalación.
Licencia libre: Se desea que la aplicación tenga el mejor uso público posible
y ésta es la mejor manera de conseguirlo. GAmeraHOM se ha liberado bajo
Apache License v2.0 [47].
5.4.
Análisis del sistema
Esta sección establece un puente de conexión entre los requisitos capturados
en §5.3 y la futura implementación de GAmeraHOM (véase §5.6). En este punto,
el texto pretende aproximar el sistema a un posible desarrollador, sin entrar en la
implementación técnica del proyecto.
74
Desarrollo del Proyecto
5.4.1.
Historias de usuario
Como ya se adelantó en §5.1.2, los proyectos basados en XP se estructuran en
torno a las historias de los usuarios, que describen un comportamiento o propiedad
deseada del sistema en sus propias palabras. Mientras se redactan, el equipo
de desarrolladores, tras realizar un análisis superficial del trabajo implicado con
ayuda del cliente, asigna a cada historia un tiempo estimado de finalización en
días ideales y un riesgo. El cliente puede, en función de esos factores y de sus
intereses, marcar la prioridad de una historia.
Una historia de usuario puede ser de muy alto nivel o de muy bajo nivel, pudiendo
unirse varias historias de bajo nivel en una sola, o dividirse una de alto nivel en
varias más sencillas.
Pasaremos a listar las historias de usuario que se han ido acumulando a lo largo
de la comunicación con los clientes durante el desarrollo del PFC, es decir, en
los seminarios con el grupo UCASE y las distintas reuniones con los tutores. En
concreto, la interacción de este proyecto con el usuario es mínima, ya que pese
al trabajo de implementación que hay por detrás, el programa tiene una finalidad
muy concreta de cara al usuario.
1. “Crear una población de individuos de forma aleatoria del orden especificado y mostrar la lista de operadores del orden asociado a cada individuo”.
ID: 1
Descripción:
• Ampliar el fichero de configuración el máximo orden de la
población que especifique el número de tripletas o mutaciones
que va a sufrir cada individuo.
• Ampliar el fichero de configuración con el tamaño máximo de la
población.
• Generar de forma aleatoria valores para los operadores, localidades y atributos de cada individuo, respetando los límites. Esto
implica tener bien definida la estructura del individuo.
• Generar tantos individuos aleatorios, como se indique en el
tamaño de la población.
2. “A partir del análisis de un fichero BPEL, crear una población con
individuos dentro de los rangos establecidos”.
ID: 2
5.4 Análisis del sistema
75
Descripción:
• Del análisis de ese fichero BPEL se obtiene una lista de los
operadores disponibles, donde se puede aplicar ese operador y
con qué atributos.
• Definir el rango de operadores válidos codificados entre 1 y el
número total del operadores.
• Definir el rango de localidades válidas codificadas entre 1 y el
mínimo común múltiplo de las localidades.
• Definir el rango de atributos válidos codificados entre 1 y el
mínimo común múltiplo de los atributos aplicables, es decir,
aquellos atributos correspondientes a instrucciones a las que se
le puede aplicar algún operador.
3. “Mostrar el individuo codificado (genotipo) y su correspondiente valor real
(fenotipo)”.
ID: 3
Descripción:
• El genotipo se corresponderá con el valor codificado.
• El fenotipo surgirá de la normalización del individuo.
• Se construye una fase de normalizado para los individuos para
poder ejecutar y comparar los mutantes con sus valores reales.
4. “Hacer generaciones donde cada generación produzca una nueva población
completa”.
ID: 4
Descripción:
• Crear varias generaciones donde los individuos sean diferentes a
los anteriores.
• Aunque más adelante sufrirán cambios por aplicación de varios
operadores, en este momento lo que interesa es ir cambiando los
individuos conforme se pasa de generación.
5. “Usar una segunda población con objeto de que los nuevos individuos se
vayan introduciendo en esta población”.
ID: 5
Descripción:
76
Desarrollo del Proyecto
• Crear una población paralela en cada generación para mantener la
población nueva (población actual) con los individuos nuevos y la
anterior con los individuos producidos en la generación previa.
6. “Llevar un HOF con el registro de los individuos que se vayan produciendo
en el algoritmo”.
ID: 6
Descripción:
• Generar un registro para introducir los individuos más aptos.
• Verificar que los individuos del HOF son únicos.
7. “Generar la matriz de ejecución de una población”.
ID: 7
Descripción:
• Comparar los mutantes con el programa original.
• Cada mutante tendrá un valor resultante para cada caso de prueba:
◦ Cero, si sobrevive.
◦ Uno, si está muerto.
◦ Dos, si es erróneo.
8. “Hacer generaciones donde se produzca un determinado porcentaje de
nuevos individuos”.
ID: 8
Descripción:
• Ampliar el fichero de configuración con generadores de individuos que indiquen el porcentaje determinado de individuos que
necesitan producirse en relación al tamaño total de la población.
9. “Implementar los operadores de selección, cruce y mutación”.
ID: 9
Descripción:
• Los operadores de selección quedan definidos por elección
aleatoria o siguiendo el método de la ruleta.
• El operador genético de cruce, dada la filosofía de los mutantes
de orden superior, queda dividido en dos operadores, el operador
de cruce de individuo y el operador de cruce de orden.
5.4 Análisis del sistema
77
• El operador genético de mutación, dada la filosofía de los
mutantes de orden superior, queda dividido en dos operadores,
el operador de mutación de individuo y el operador de mutación
de orden.
5.4.2.
Casos de uso
Los casos de uso especifican el comportamiento deseado del sistema, representan
los requisitos funcionales (véase §5.3.2) y nos permiten analizar de manera
general y abstracta qué requiere nuestro sistema.
Los casos de uso describen la secuencia de acciones, incluyendo variantes, que
ejecuta un sistema y que producen unos resultados observables para un actor
particular.
La notación gráfica que utiliza UML para representar los casos de uso es lo
que conocemos como diagramas de casos de uso. El diagrama correspondiente
a GAmeraHOM podemos encontrarlo en la figura 5.1.
Los diagramas de casos de usos son una mera representación, lo realmente
importante en el modelado de casos de uso es la especificación de éstos.
Figura 5.1: Diagrama de casos de uso de GAmeraHOM
Si observamos con más detalle el diagrama de casos de uso de aplicar
los operadores de reproducción (figura 5.2) podemos detectar los operadores
genéticos de mutación y cruce (explicados anteriormente en la sección §3.3.1).
78
Desarrollo del Proyecto
Figura 5.2: Diagrama de casos de uso de operadores genéticos
Estos operadores ha tenido que adaptarse a la nueva estructura de mutantes de
orden superior y por ello, han tenido que subdividirse en dos operadores nuevos
por cada uno de ellos: de orden y de individuo.
Operador de mutación de orden A partir del individuo padre se obtiene un hijo
idéntico, el cuál únicamente sufre cambios en el valor de su orden.
Operador de mutación de individuo Se elige del individuo un punto de mutación que identifique la mutación elegida y de ella, una de las características
del mutante (operador, localidad o atributo), dicho valor será modificado
por una serie de operaciones.
Operador de cruce de orden Dados dos progenitores, se elige un punto de cruce
a partir del cual intercambiar todos los elementos del individuo.
Operador de cruce de individuo Dados dos progenitores, se elige un punto
intermedio que identifique la mutación elegida y de ella, una de las
características del mutante (operador, localidad o atributo), dicho valor será
intercambiado entre los dos padres.
Estos operadores serán tratados con más detalle en la sección §5.6.
5.4 Análisis del sistema
79
A continuación se especifica el funcionamiento de cada uno de los casos de uso
representados en la figura 5.1.
A NALIZAR UNA COMPOSICIÓN ORIGINAL WS-BPEL
Actor principal Algoritmo genético.
Precondiciones El fichero de la composición WS-BPEL debe existir y estar
declarado en el fichero de configuración.
Postcondiciones Se muestra una lista con los operadores existentes, indicando
para cada uno el número de instrucciones donde puede aplicarse y asimismo, los
atributos aplicables.
Escenario principal
1. El algoritmo genético solicita la realización del análisis de la composición
WS-BPEL.
2. Se consultan las características necesarias del fichero de configuración.
3. El sistema analiza la composición y genera los resultados deseados: un
listado con el número de operandos disponibles para cada operador en
la definición de proceso WS-BPEL especificado. Para cada operador se
especifica su nombre, el número de operandos y el valor máximo del
atributo.
G ENERAR MUTANTES ALEATORIOS
Actor principal Algoritmo genético.
Precondiciones El fichero de configuración está cargado.
Postcondiciones Genera n individuos de forma aleatoria y dentro de los rangos
establecidos
Escenario principal
1. El algoritmo genético solicita generar mutantes aleatorios para tener la
población inicial de individuos.
2. Consultar el tamaño total de la población y el orden máximo (número
máximo de tripletas por individuo) del fichero de configuración.
80
Desarrollo del Proyecto
3. Generar un individuo por cada generador de individuos establecido, hasta
que se complete la población.
Variaciones Si se trata de poblaciones sucesivas, se crea un determinado número
de individuos indicado por un porcentaje:
1. Consultar el tamaño total de la población y el orden máximo (número
máximo de tripletas por individuo).
2. Calcular cuantos individuos tienen que ser generados, atendiendo al
porcentaje indicado.
3. Generar un individuo por cada generador de individuos establecido, hasta
que se complete el número de individuos que teníamos que generar.
C OMPARAR Y EJECUTAR MUTANTES
Actor principal Algoritmo genético.
Precondiciones El fichero de la composición WS-BPEL debe existir y estar
declarado en el fichero de configuración. Además, en dicho fichero también debe
encontrarse definida la ubicación del conjunto de casos de prueba y un fichero
para la salida de la ejecución de la composición original. Por último, debe existir
al menos un mutante con el que realizar la comparación.
Postcondiciones Se obtiene la comparación de la salida de la composición
original con las de todas las mutaciones, indicando si los mutantes están muertos,
vivos o son erróneos.
Escenario principal
1. El algoritmo genético solicita realizar la ejecución y la comparación de los
mutantes.
2. El sistema compara la salida de ejecutar el conjunto de casos de prueba de
la composición original con las de todas las mutaciones.
Indicará un cero si no hay ninguna diferencia entre ellos (mutante vivo), un
uno si existen diferencias (mutante muerto) y dos si el mutante es erróneo,
lo que quiere decir que no se ha encontrado un caso de prueba adecuado
para él.
5.4 Análisis del sistema
81
A PLICAR OPERADORES DE SELECCIÓN
Actor principal Algoritmo genético.
Precondiciones Debe existir al menos un operador de selección definido en el
fichero de configuración.
Postcondiciones Devuelve un individuo.
Escenario principal
1. El algoritmo genético solicita un individuo de una población determinada
por alguno de los operadores de selección disponibles del sistema.
2. Se consultan las características necesarias del fichero de configuración.
3. El sistema, ya sea aleatoriamente, por el método de la ruleta, o cualquier
otro, elige un individuo y lo devuelve al algoritmo.
A PLICAR OPERADORES DE REPRODUCCIÓN
Actor principal Algoritmo genético.
Precondiciones Debe existir al menos un operador de reproducción definido en
el fichero de configuración.
Postcondiciones Nuevos descendientes de los mutantes
Escenario principal
1. El algoritmo genético solicita la aplicación de los operadores de reproducción disponibles en el sistema.
2. Se consultan las características necesarias del fichero de configuración.
3. Según si el operador de reproducción es de tipo unario o binario, el
algoritmo genético solicita que se elijan tantos mutantes a reproducir como
hagan falta, por medio de los operadores de selección.
4. El algoritmo genético muta o cruza los mutantes elegidos por el paso
anterior.
82
Desarrollo del Proyecto
N ORMALIZAR INDIVIDUO
Actor principal Algoritmo genético.
Precondiciones El individuo o mutante codificado debe existir para poder
normalizarlo.
Postcondiciones El individuo toma valores reales.
Escenario principal
1. El algoritmo genético solicita la normalización de un individuo.
2. Se consultan las características necesarias del fichero de configuración.
3. El sistema le aplica una operación para normalizarlo y lo muestra.
C ONSULTAR CARACTERÍSTICAS DE CONFIGURACIÓN
Actor principal Algoritmo genético.
Precondiciones El fichero de configuración existe en el sistema y es accesible.
Postcondiciones Ninguna.
Escenario principal
1. El sistema devuelve al algoritmo genético todos las características del
fichero de configuración.
5.4.3.
Modelo conceptual de datos del dominio GAmeraHOM
El modelo conceptual de datos describe la estructura de datos de un sistema y las
relaciones estáticas que existen entre ellas. Es la representación de los conceptos
significativos del dominio del problema.
En la figura 5.3 se muestra el modelo conceptual de datos de GAmeraHOM, el
cual se ha realizando siguiendo la notación UML 2.0.
Configuración agrupará toda la parametrización de GAmeraHOM conteniendo
atributos tales como el orden máximo que pueda tener un individuo, el tamaño
máximo de la población, cuáles serán los generadores de nuevos individuos, los
operadores de selección de individuos, los operadores de reproducción, también
5.4 Análisis del sistema
83
conocidos como operadores genéticos, cuáles serán los criterios de parada del
algoritmo, la composición WS-BPEL con la que vamos a trabajar y el conjunto de
casos de prueba que usaremos.
Figura 5.3: Modelo conceptual de datos
OperadorSelección proporciona diversas maneras de poder elegir un individuo de
la población, por ejemplo siguiendo el método de la ruleta o de modo aleatorio.
OperadorGenetico cruzará y mutará individuos de la población consiguiendo
generar individuos cada vez más aptos.
ConjuntoCasosPrueba permitirá el análisis de los mutantes frente a la compo-
84
Desarrollo del Proyecto
sición original por medio de una serie de casos de prueba. Tras este análisis,
obtendremos unos resultados por mutante que nos indicará si dicho mutante ha
sobrevivido (representado por un cero), ha muerto (representado por un uno) o es
erróneo (representado por un dos).
GeneradorIndividuos indicará las distintas que formas que utilizaremos para
producir nuevos individuos siguiendo las directrices de los límites impuestos por
el fichero de configuración.
CriterioParada especificará múltiples condiciones que en caso de cumplirse
alguna de ellas, producirá el fin del algoritmo.
ComposiciónWSBPEL representa a la composición original que será modificada
por tantos individuos como se especifique en el tamaño máximo de la población.
Individuo codifica a tantos mutantes como indique el orden máximo mediante el
uso de operadores de mutación que se aplican a la composición original. Cada
mutación del individuo se representará por el operador que se aplica, la localidad
o instrucción donde se aplicará dicha modificación y un atributo que representa
información necesaria para la aplicación del operador de mutación.
Cada Operador tendrá un nombre, compuesto por tres letras, un valor numérico
que lo identificará comprendido entre 1 y 34 (el número máximo de operadores
definidos hasta ahora para WS-BPEL) y el máximo valor que puede tomar el
atributo, que dependerá de cada operador concreto.
5.5.
Diseño del sistema
5.5.1.
Arquitectura del sistema
Mientras que en la especificación el sistema se ve como una sola clase de objetos
que engloba toda la información y todas las operaciones, en la fase de diseño cada
clase de objetos tiene sus propias operaciones de manipulación de información, y
los objetos interactúan entre ellos para satisfacer las operaciones del sistema.
Para determinar el tipo de arquitectura del sistema debemos tener en cuenta tanto
la funcionalidad esperada del sistema, como los requisitos no funcionales antes
mencionados y otros factores de calidad del software, como son los siguientes:
La mantenibilidad requiere una arquitectura que evite la propagación
de cambios realizados sobre una parte del sistema, definiendo interfaces
5.5 Diseño del sistema
85
estables entre estas partes.
Dicha arquitectura debe ser además lo más sencilla posible para facilitar
cambios en su estructura y elementos, es decir, debe ser flexible.
La división en partes con límites e interfaces bien definidas mejora
también la reusabilidad y facilita las pruebas, evitando acoplamientos
innecesariamente complejos que dificulten el desarrollo de una aplicación
fiable y con la funcionalidad deseada.
La fiabilidad asegura el programa realice su objetivo satisfactoriamente en
un determinado periodo de tiempo y en un entorno concreto
5.5.2.
Detalles de diseño
Este apartado proporcionará los detalles de implementación necesarios para poder
continuar con este proyecto. Hay que decir que los componentes iniciales de
GAmera se conservan (véase la sección §4.1.1) y que lo que ha sido modificado
es el algoritmo genético.
Dado que el algoritmo genético aquí utilizado no es 100 % puro debido a que se ha
tenido que adaptar a las necesidades de la herramienta, se hace preciso tener muy
claro el proceso que va a seguir el algoritmo genético durante su desarrollo. En la
figura 5.4 nos encontramos con un diagrama de actividades con el flujo principal
que sigue GAmeraHOM.
Para empezar, y como marcan las bases de los algoritmos genéticos, es necesario
crear una primera generación donde se crea una población inicial de individuos.
Estos individuos iniciales tienen un valor de aptitud o fitness que debemos calcular
antes de empezar a optimizar la población.
Nuestro algoritmo, tendrá definidas ciertas condiciones de parada (como por
ejemplo, que se cumpla un determinado número de generaciones o que se haya
producido un determinado porcentaje de mutantes con respecto al tamaño de la
población), si se cumple alguna de ellas, el algoritmo finaliza su ejecución y en
caso contrario, es hora de reproducir a los individuos.
Por un lado, conservaremos un determinado número de individuos de la población
anterior con sus mismas características.
Otro porcentaje lo obtendremos de generar nuevos individuos, de la misma forma
que se crearon para la población inicial.
86
Desarrollo del Proyecto
Figura 5.4: Diagrama de actividades del AG
5.5 Diseño del sistema
87
Por último, el número de individuos restantes para completar la población surgirán
de reproducir los individuos entre ellos. De las formas posibles de reproducción
utilizamos el cruce, donde las características de dos individuos progenitores se
intercambian produciendo dos nuevos hijos, y la mutación, donde un valor es
modificado o mutado dando lugar a un nuevo descendiente.
Una vez completada la nueva población es necesario obtener de nuevo la aptitud
de los mismos y volvemos a comprobar las condiciones de parada para saber
si tenemos que volver a producir una nueva generación de individuos o si el
algoritmo tiene que parar.
Notación gráfica
Los diagramas de clase que se muestran en esta sección siguen una serie
de notaciones estándar, tanto en formato, como en diseño, que se detallan a
continuación.
Una clase será representada por una caja con su nombre y sus atributos. Se
ha decidido no mostrar las operaciones asociadas a la clase para una mayor
compresión del gráfico.
La clase naranja indica la más importante, ya que es la que lanza la
aplicación desde la línea de comandos.
Los objetos amarillos se corresponden con las clases pertenecientes al
componente gamera2-core.
Los objetos verdes pertenecen al componente gamera2-api.
Los objetos grises se encuentran dentro del componente gamera2-bpel.
Los objetos blancos son objetos que han sido o se van a explicar en alguna
parte de la sección y que por claridad se han suprimido tanto sus atributos,
como sus operaciones.
Una interfaz queda representado por el gráfico compuesto por un círculo,
doble línea y una lista de operaciones.
La línea continua es una asociación. Si termina con una flecha simple o
rellena, la asociación será direccional. En cambio, si la fecha está hueca
indica una generalización.
La línea discontinua si va acompañada de una flecha hueca está representando una implementación.
88
Desarrollo del Proyecto
Lanzador del algoritmo genético
La clase CLIRunner será la encargada de lanzar GAmeraHOM desde la línea de
comandos y únicamente necesitará conocer la ruta donde se encuentra el fichero
de configuración YAML.
Figura 5.5: Diagrama de clases del lanzador del AG
Gracias a la introspección toda la información obtenida de ese fichero se
depositará sobre la clase Configuration que será la base que usará el
algoritmo genético desde GAGenerator.
Podemos ver un ejemplo completo en el listado 5.1 donde apreciamos los
siguientes elementos:
1. Tamaño máximo de la población.
2. Orden máximo permitido para los individuos. El uso del ampersand,
seguido de un nombre, permite que podamos referenciar a ese valor por
el nombre de la variable definida.
3. Un executor encargado de preparar el entorno, limpiar, generar y comparar
los mutantes contra el programa original. Para ello, tenemos que informarle
5.5 Diseño del sistema
89
sobre la ubicación del conjunto de casos de prueba, la ubicación del
programa original y una ruta para un fichero de salida.
4. Operadores genéticos que usará el algoritmo, para completar una nueva población cruzando y mutando individuos de la población anterior, previamente seleccionados. Cada operador estará acompañado de una probabilidad que determinará si será aplicado o no. Por su lado, los operadores de
mutación también especificarán un modo de seleccionar los individuos de la
población anterior (por ejemplo, de manera aleatoria o siguiendo un criterio
uniforme), un factor de escala y un rango de aleatoriedad que serán usados
para la mutación en sí.
5. Generadores de individuos con el porcentaje de individuos que necesitará
ejecutar.
6. Operadores de selección de individuos que determinarán de qué forma o
siguiendo qué criterios se elegirán un determinado porcentaje de individuos
de la población anterior.
7. Criterios de parada para comprobar si el algoritmo debe continuar o no.
Cada uno tendrá sus propias variables parametrizables.
Listado 5.1: Fichero de configuración YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
populationSize: 5
maxOrder: &mO 5
executor: !!exec.BPELExecutor
testSuite: src/test/resources/loanRPC/loanRPC.bpts
originalProgram: src/test/resources/loanRPC/loanRPC.bpel
outputFile: target/loanApprovalProcess.bpel.out
geneticOperators:
!!genetic.OrderMutationOperator
{selector:
&rndSel !!select.UniformRandomSelection {seed: 5},
scaleFactor: &pOMop 0.1,
randomRange: *mO} : {probability: *pOMop}
!!genetic.IndividualMutationOperator
{selector: *rndSel,
scaleFactor: &pIMOp 0.3,
randomRange: 100} : {probability: *pIMOp}
!!genetic.OrderCrossoverOperator
{} : {probability: 0.2}
!!genetic.IndividualCrossoverOperator {} : {probability: 0.4}
individualGenerators:
90
23
24
25
26
27
28
29
30
31
32
33
34
Desarrollo del Proyecto
!!generate.UniformGenerator {} : {percent: 0.2}
selectionOperators:
!!select.RouletteSelection
{} : {percent: 0.4}
terminationConditions:
- !!term.PercentAllMutantsCondition {percent: 0.8}
- !!term.GenerationCountCondition
{count: 10}
loggers:
- !!log.MessageLogger {console: true, file: }
- !!log.HofLogger {console: false, file: hof.txt}
La suma de las probabilidades de los operadores genéticos no debe superar el
100 %. Asimismo, la suma de los porcentajes de los generadores de individuos y
de la selección de individuos tampoco debe superar el 100 %, ya que el porcentaje
restante corresponderá a la aplicación de los operadores genéticos.
Puesta a punto
Una vez cargada toda la información, es momento de que el executor (figura 5.6)
analice el programa original y detecte aquellos operadores aplicables (véase la
tabla 5.1 para ver todos los operadores de mutación de WS-BPEL definidos hasta
ahora), las instrucciones afectadas y los atributos posibles de cada operador.
Figura 5.6: Diagrama de clases del executor
Del análisis obtendremos para cada operador, la instrucción o localidad en la que
el operador puede aplicarse (cero si no se puede usar) y los atributos, ambos
identificados por locationCounts y fieldRanges, respectivamente.
Con estos datos podemos conocer información útil como el número total de
operadores aplicables, la última instrucción con probabilidades de sufrir cambios
y el valor máximo de atributo del operador que se aplica.
5.5 Diseño del sistema
91
Tabla 5.1: Operadores de mutación para WS-BPEL
Operador Valor Máx. valor del atributo
Atributos
ISV
EAA
EEU
ERR
ELL
ECC
ECN
EMD
EMF
ACI
AFP
ASF
AIS
AIE
AWR
AJC
ASI
APM
APA
XMF
XMC
XMT
XTF
XER
XEE
AEL
EIU
EIN
EAP
EAN
CFA
CDE
CCO
CDC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1
5
1
6
2
2
4
2
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
2
2
2
+, -, *, div, mod
<, >, >=, <=, =, ! =
and, or
/, //
+1, -1, añadir, eliminar
0, mitad
0, mitad
true, false
true, false
true, false
92
Desarrollo del Proyecto
Además, AnalysisResults también almacenará la información útil, es decir,
aquella información del operador que se pueda usar en una instrucción del
programa original, por lo que se descartarán aquellos de localidad igual a cero.
Por otro lado, en la figura 5.7 podemos observar la aparición de GAState que
llevará un control de algoritmo proporcionando información de interés a los
loggers definidos en el sistema, como por ejemplo: generación actual, número
de mutantes generados hasta el momento, etc.
Figura 5.7: Diagrama de clases del análisis inicial y el HOF
Comparación de individuos con el programa original
Cada individuo estará asociado con una serie de resultados fruto de la comparación con el programa original, ComparisonResults.
El mutante será desplegado, invocado una vez por cada caso de prueba. La
biblioteca de prueba unitaria, BPELUnit, despliega el servicio, y actúa como
cliente, invocando el servicio a probar, y como servidor para los mockups. A
continuación, se compara la salida de cada mutante con cada caso de prueba con
los del programa original, para decidir si el mutante está muerto o sigue vivo. El
operador de comparación es una estricta comparación uno-a-uno de sus mensajes
de respuesta SOAP.
A partir de estas comparaciones se obtendrá la matriz de ejecución, que permitirá
5.5 Diseño del sistema
93
calcular la aptitud de cada individuo. Los elementos de la matriz de ejecución
pueden ser:
mij = 0, si el mutante i no es matado por el caso de prueba j.
mij = 1, si el mutante i es matado por el caso de prueba j.
mij = 2, si el mutante i produce un error en la ejecución.
En el momento en que un caso de prueba produce un error en un determinado
mutante, ya no es necesario seguir comparando ese mutante y quedan inválidas
todas las comparaciones.
Figura 5.8: Diagrama de clases del resultado de la ejecución
Así que, siendo T el número total de casos de prueba, podemos concluir que los
resultados de las comparaciones por individuo estarán formados por una serie de
valores, ComparisonResult que indican lo siguiente:
Un mutante i está vivo, es decir, la comparación del mutante con la del
programa original produce la misma salida, cuando
T
X
mij = 0
j=1
Un mutante i está muerto, es decir, la comparación del mutante con la del
programa original produce una salida distinta, cuando
T
X
mij = 1
j=1
Un mutante i es erróneo, es decir, se ha producido un error en el despliegue
del mutante, cuando ∃mij = 2
94
Desarrollo del Proyecto
Representación de individuos
Cada individuo codifica la mutación a realizar al programa original mediante
un valor que representa al orden del individuo (0 < ordenIndividuo ≤
maxOrden), una aptitud o fitness y una serie de tripletas, tantas como el orden
máximo definido en la configuración, formadas por el identificador del operador,
una referencia a la instrucción donde se aplica el operador y un valor con
información para la aplicación del operador.
Figura 5.9: Diagrama de clases de los individuos y su población
Operador Operador de mutación que se aplica al programa original. Se codifica
con un valor entero entre 1 y el número de operadores de mutación
definidos, en adelante OM .
Localidad Número de instrucción del programa original donde se aplicará el
operador. Con objeto de realizar una distribución uniforme entre todos los
operadores independientemente del número de instrucciones asociadas a
cada uno, el campo se codifica con un valor entero comprendido en el
rango de 1 a I, donde I = mcm{mi , 1 ≤ i ≤ OM }, siendo mi el
número de instrucciones que existen en el programa original a las que se
puede aplicar un operador de mutación. Más adelante, es necesario hacer
una normalización, de manera que el valor Ii representará una operación de
mutación en la instrucción d(Ii × mi )/Ie.
Atributo Valor que representa la información necesaria para la aplicación del
operador de mutación. Dado que una mutación consiste en la alteración de
un elemento del programa, este campo especifica cuál será el nuevo valor
que tomará el elemento afectado por la mutación. Al igual que en el campo
Localidad, con objeto de realizar una distribución uniforme entre todos los
individuos, el campo Atributo contiene un valor entero dentro del rango 1
a V , donde V = mcm{vi ; 1 ≤ i ≤ OM }, siendo vi el número de valores
que puede tomar el operador de mutación i-ésimo.
5.5 Diseño del sistema
95
Aptitud Vendrá determinada por los resultados de la comparación de los
individuos con el programa original siguiendo la siguiente fórmula:
!
T
M
X
X
Fitness(I) = M · T −
mIj ·
mij
(5.1)
j=1
i=1
Siendo I el individuo implicado, M el número total de mutantes, T el
número total de casos de prueba y mij el resultado de la comparación de la
prueba j para el individuo i. Teniendo en cuenta, que si el resultado de la
prueba es inválido, el valor de la aptitud del mutante será cero. Por ejemplo,
dada la siguiente matriz de resultados:


1 0 1 1


mij (M × T ) = 2 2 2 2
1 0 0 0
Las aptitudes de los tres mutantes anteriores son las siguientes:
F (I1 ) = 3 × 4 − (1 × 4 + 0 × 2 + 1 × 3 + 1 × 3) = 2
F (I2 ) = 0
F (I3 ) = 3 × 4 − (1 × 4 + 0 × 2 + 0 × 3 + 0 × 3) = 8
GAmera sólo trabajaba con mutantes de primer orden, GAmeraHOM admite
operaciones con mutantes de orden superior (véase la figura 5.10).
Figura 5.10: Primer orden (A) y orden superior (B)
Ahora cada operador tendrá un orden específico (en el ejemplo 5.10 el orden
del individuo B es 3), marcada por la zona sombreada, que indicará el número
de cambios que sufrirá el programa original. Un individuo podrá tener tantos
cambios, como se indique en la configuración con el máximo orden de mutación
(en el ejemplo 5.10 el máximo orden de B es 5).
Hemos de tener en cuenta que esto implicará tener en la misma población,
individuos que representan a mutaciones de distintos órdenes. Esta codificación
96
Desarrollo del Proyecto
Figura 5.11: Individuos idénticos
plantea la posibilidad de tener individuos genéticamente diferentes, pero que
representan al mismo mutante, como se puede ver en la figura 5.11.
Así que, podemos decir que dos individuos son idénticos si tienen el mismo orden
de individuo, el mismo orden máximo de mutación y si tienen los valores de las
primeras mutaciones (operador, localidad y atributo) iguales hasta el orden de los
individuos.
Operadores genéticos
Los operadores genéticos serán los encargados de generar descendientes a partir
de individuos progenitores. Los operadores genéticos que se han diseñado son
la mutación y el cruce. La mutación sólo modifica un valor del individuo padre
produciendo un nuevo hijo, y el cruce, a raíz de dos progenitores mezcla sus
características obteniendo dos nuevos individuos descendientes.
Cada operador se define dentro del fichero de configuración con la siguiente
estructura:
!!genetic.NOMBRE {OPCIONES_INTERNAS} : {OPCIONES_COMUNES}
Las opciones internas son implementadas por el propio operador, mientras que
las opciones comunes, como su nombre indica, son características de todos los
operadores genéticos y se implementarán en GAGeneticOperatorOptions.
Una de las opciones internas de nuestros operadores genéticos será el modo de
selección de los individuos que participen en la operación genética. Por defecto,
el modo de selección sigue el método de la ruleta y no es necesario indicarlo
expresamente (véanse las líneas 11 y 12 del listado 5.2). Sin embargo, nuestra
mutación elige individuos de manera aleatoriamente uniforme a partir de una
semilla determinada. Podemos observar la creación de un ancla en la línea 4, para
no repetir el mismo contenido en la línea 8.
5.5 Diseño del sistema
97
Para las mutaciones, vamos a utilizar un par de opciones internas más: un
valor de escala llamado scaleFactor que representa el mismo valor que la
probabilidad de aplicación de ese operador (líneas 5 y 9 del listado 5.2) y un
rango de aleatoriedad llamado randomRange (líneas 6 y 10 del listado 5.2)
que influirán en el nuevo valor resultante de la operación de mutación.
Listado 5.2: Configuración YAML para los operadores genéticos
1
2
3
4
5
6
7
8
9
10
11
12
geneticOperators:
!!genetic.OrderMutationOperator
{selector:
&rndSel !!select.UniformRandomSelection {seed: 5},
scaleFactor: &pOMop 0.1,
randomRange: *mO} : {probability: *pOMop}
!!genetic.IndividualMutationOperator
{selector: *rndSel,
scaleFactor: &pIMOp 0.3,
randomRange: 100} : {probability: *pIMOp}
!!genetic.OrderCrossoverOperator
{} : {probability: 0.2}
!!genetic.IndividualCrossoverOperator {} : {probability: 0.4}
En cuanto a las opciones comunes a todos los operadores genéticos, tenemos la
probabilidad de aplicación de cada operador. La suma de las probabilidades de
todos los operadores genéticos han de sumar 100 %.
Figura 5.12: Diagrama de clases de los operadores genéticos
98
Desarrollo del Proyecto
5.5 Diseño del sistema
99
100
Desarrollo del Proyecto
A diferencia del resto de elementos que influyen en la creación de una nueva
generación (selección de individuos de la generación anterior y generación de
nuevos individuos) y que veremos más adelante, éstos no poseen un porcentaje que
indique el número de individuos que tienen que generarse siguiendo ese método,
ya que los operadores genéticos serán los últimos que participen en la creación de
la nueva generación produciendo individuos hasta que el tamaño de la población
se complete.
El modo en el que el algoritmo genético decide qué operador genético de los
disponibles aplicar en cada caso, se hace generando un número aleatorio entre
cero y uno, y como si del método de la ruleta se tratase, se va comparando con la
probabilidad de cada operador hasta que se cumpla que dicho aleatorio sea menor
o igual que la probabilidad del operador en cuestión.
Operador de mutación
Dado el carácter de los mutantes de orden superior, se definen dos tipos de
mutaciones: mutación de orden y mutación de individuo.
La mutación de orden se encarga de modificar el valor del orden del individuo
según la siguiente regla:
Orden(I) = oactual + rand(−rango, rango) · (1−probM O )
Donde el rango aleatorio y la probabilidad de aplicación fueron definidas en el
fichero de configuración (véase el listado 5.2).
La mutación de individuo cambia el valor del operador, la localidad o el atributo
de una de las mutaciones de un individuo. Aleatoriamente se elige la mutación
de las disponibles del individuo (desde la primera mutación, hasta el orden del
individuo) y del mismo modo, se selecciona el campo a mutar: operador, localidad
o atributo. El nuevo valor se calcula del siguiente modo:
Valor(I) = vactual + rand(−rango, rango) · (1−probM I )
Donde el rango aleatorio y la probabilidad de aplicación fueron definidas en el
fichero de configuración (véase el listado 5.2).
Operador de cruce
Tal y como ocurre con el operador de mutación, también podemos definir dos
tipos de operador de cruce: cruce de orden y cruce de individuo. Sin embargo,
en el cruce se ven afectados dos individuos que son seleccionados siguiendo las
5.5 Diseño del sistema
101
pautas indicadas en el fichero de configuración, siendo por defecto el método de
la ruleta.
En el cruce de orden se elige un punto de cruce aleatoriamente y a partir de
él se intercambian las mutaciones entre los individuos progenitores produciendo
dos nuevos individuos. Como puede darse el caso de que los progenitores sean
de distinto orden, dicho punto de cruce debe estar entre la primera mutación y la
mutación correspondiente al orden del progenitor mínimo.
Por su parte, el cruce de individuo también necesita un punto de cruce con
las mismas características que el elegido en el operador de cruce, pero además,
necesita elegir aleatoriamente el campo a cruzar de los individuos progenitores:
operador, localidad o atributo. Una vez hecho esto, basta intercambiar dichos
valores entre los individuos padres.
Dado que los operadores genéticos son los últimos en aplicarse y se utilizan hasta
completar el tamaño de la población, puede darse el caso de que sólo se necesite
un individuo y se produzcan dos derivados de una operación de cruce. Por ello,
la población destino de estos operadores genéticos será una población auxiliar y
se comprobará si hay suficiente espacio en la población actual para introducir los
generados por estos operadores (uno si se trata de una mutación y dos si es un
cruce).
Si se produce una operación de cruce y sólo falta un individuo por cumplir el
tamaño máximo de la población, vamos a introducir el primer individuo generado
en el cruce. Lo ideal sería elegir el que mejor aptitud tuviese, pero por cuestiones
de eficiencia se ha decidido simplificar este aspecto por el momento.
Generadores de individuos
Los generadores de individuos crean nuevos individuos siguiendo las directrices
marcadas por el fichero de configuración. El único generador de individuo en
nuestro sistema corresponde al generador uniforme de individuos.
Cada generador se define dentro del fichero de configuración con la siguiente
estructura:
!!generate.NOMBRE {OPCIONES_INTERNAS} : {OPCIONES_COMUNES}
No se necesitan opciones internas pero se deja la estructura preparada, por si en
un futuro se necesitasen.
Como opción común, un porcentaje que indica el porcentaje de individuos de
102
Desarrollo del Proyecto
la nueva generación que deben crearse siguiendo ese método, implementado en
GAIndividualGeneratorOptions.
Listado 5.3: Configuración YAML para los generadores de individuos
1
2
individualGenerators:
!!generate.UniformGenerator {} : {percent: 0.2}
Los generadores de individuos disponibles se irán llamando sucesivamente hasta
que completen el porcentaje de individuos indicado como opción de cada uno de
ellos, ya que en cada llamada sólo producen un único individuo.
Figura 5.13: Diagrama de clases de los generadores de individuos
El generador uniforme de individuos crea nuevos individuos siguiendo las
siguientes pautas:
El orden del nuevo individuo es un aleatorio entre uno y el máximo orden
de mutación.
El individuo tendrá tantas mutaciones como se definan en el máximo orden
de mutación.
El operador es un número aleatorio entre uno y el máximo operador
aplicable.
La localidad es un número aleatorio entre uno y la instrucción más alta
afectada.
El atributo es un número aleatorio entre uno y el atributo más alto aplicado.
Normalización de individuos
Antes de ejecutar los individuos contra los casos de prueba, es necesario
normalizar los individuos a los valores reales que tienen. Como podrá comprobar,
5.5 Diseño del sistema
103
si únicamente los operadores 3, 10 y 15 son los operadores aplicables, los
individuos tendrán como valores de operadores aleatorios entre uno y tres, el
máximo de operadores aplicables.
Por todo ello, surge la figura del GAHof (figura 5.7) que además de representar
al salón de la fama de un algoritmo genético, es decir, un registro de todos
los individuos creados a lo largo de la ejecución del algoritmo genético, sirve
para almacenar los individuos normalizados y así poder ejecutar los individuos y
obtener su aptitud de forma correcta.
Operadores de selección
Los operadores de selección de individuos eligen de una población, un determinado individuo para que sea introducido en la nueva generación. Tenemos implementados dos operadores de selección: el método de la ruleta y un método de
selección aleatorio. El primero de ellos será usado para completar un determinado
porcentaje de individuos de la nueva generación y el otro para elegir los individuos
que participen en las operaciones genéticas.
Figura 5.14: Diagrama de clases de los operadores de selección
Cada operador de selección se define dentro del fichero de configuración con la
siguiente estructura:
!!select.NOMBRE {OPCIONES_INTERNAS} : {OPCIONES_COMUNES}
No se necesitan opciones internas pero se deja la estructura preparada, por si en
un futuro se necesitasen.
Como opción común, un porcentaje que indica el porcentaje de individuos que
deben seleccionarse de la población anterior siguiendo ese método, implementado
en GASelectionOperatorOptions.
104
Desarrollo del Proyecto
Figura 5.15: Diagrama de secuencia de generación de individuos
5.5 Diseño del sistema
Figura 5.16: Diagrama de secuencia de selección de individuos
105
106
Desarrollo del Proyecto
Listado 5.4: Configuración YAML para los operadores de selección
1
2
selectionOperators:
!!select.RouletteSelection
{} : {percent: 0.4}
Podemos observar cómo el método de selección aleatorio no se incluye en 5.4 ya
que no se desea que individuos de la población anterior sean elegidos con este
método, sino que únicamente sean seleccionados por la ruleta.
Los operadores de selección disponibles se irán llamando sucesivamente hasta que
completen el porcentaje de individuos indicado como opción de cada uno de ellos,
ya que en cada llamada sólo seleccionan un único individuo.
Método de la ruleta
La ruleta se implementa calculando un número aleatorio y entre cero y la suma
de las aptitudes de todos los individuos de la población y un individuo aleatorio
z de la población proporcionada que marcará la posición de inicio. El proceso irá
sumando en un contador x la aptitud de cada individuoz, partiendo de z mientras
x sea menor que y. En el momento en el que no se cumpla, el individuo elegido
para participar en la nueva generación es z.
Criterios de parada
Los criterios de parada son condiciones que el algoritmo genético comprobará
antes de iniciar una nueva generación. En el momento en que se incumpla una de
ellas, el algoritmo parará, en caso contrario, continuará.
Figura 5.17: Diagrama de clases de las condiciones de parada
Cada criterio de parada se define dentro del fichero de configuración con la
siguiente estructura:
!!term.NOMBRE OPCIONES
5.5 Diseño del sistema
107
Por el momento, se dispone de una condición que verifica el número de
generaciones y otra que comprueba el porcentaje total de mutantes generados.
Listado 5.5: Configuración YAML para las condiciones de parada
1
2
3
terminationConditions:
- !!term.PercentAllMutantsCondition {percent: 0.8}
- !!term.GenerationCountCondition {count: 10}
Contador de generaciones
Comprueba si se ha llegado a un determinado número de generaciones para
autorizar la parada.
Porcentaje de mutantes generados
Comprueba si la división del número de individuos generados entre el número
total de mutantes ha superado el porcentaje indicado como opción en la
configuración.
Para un operador X con Y localidades y Z atributos, podemos obtener Y × Z
mutantes. Ahora bien, cuando tenemos un orden máximo de mutación N , resulta
que ahora se pueden combinar por cada orden. Por lo que el número total de
mutantes se calculará sumando todas las combinaciones posibles.
Loggers
Los loggers nos proporciona información sobre lo que está ocurriendo dentro del
algoritmo genético.
Cada logger se define dentro del fichero de configuración con la siguiente
estructura: !!log.NOMBRE OPCIONES
Las opciones disponibles serán un booleano console para indicar si la
impresión de mensajes será por pantalla y file que será la ruta donde se creará
un fichero con la salida de los mensajes. No se permite la salida por consola y por
fichero para un mismo logger.
Listado 5.6: Configuración YAML para los loggers
1
2
3
loggers:
- !!log.MessageLogger {console: true, file: }
- !!log.HofLogger {console: false, file: hof.txt}
Los loggers disponibles en GAmeraHOM son los siguientes:
108
Desarrollo del Proyecto
MessageLogger Logger de mensajes simples.
HofLogger Logger que muestra los resultados del HOF: una representación de
cada individuo con los resultados de la comparación.
NullLogger Logger vacío.
GAmeraHOM dispone de un AggregateLogger que aúna todos los loggers
definidos en la configuración, para que así sea transparente para el algoritmo el
uso de un logger u otro.
Además tenemos la clase PrintingByConsoleOrFile que se encarga de
direccionar el flujo de mensajes por consola o por fichero, según se haya
especificado en la configuración.
Figura 5.18: Diagrama de clases de los loggers
5.6 Implementación
5.6.
109
Implementación
Java
Han sido de gran utilidad textos como [38] y [48], los cuales han servido como
consulta principalmente en el aspecto de la introspección y en las buenas prácticas
de diseño.
Una ayuda esencial ha sido el uso del IDE Eclipse 3.6 gracias a su soporte en
refactorización, pudiendo renombrar métodos y clases de forma segura, pruebas
unitarias y asistentes para la creación de clases y tests.
YAML
En este caso, como documento básico se ha usado [40]. Ha sido todo un
descubrimiento por su facilidad de uso.
Para que el texto fuera formateado por Eclipse, se tuvo que instalar un plugin
adicional llamado yedit [49].
Maven
El uso de Maven [41] también ha facilitado el desarrollo de GAmeraHOM debido
a que se integra fácilmente con varias herramientas.
En el POM queda descrito el proyecto a construir con sus dependencias con
otros módulos o componentes externos, así como el orden de construcción de los
distintos elementos. Además, otra ventaja es que el motor incluido en su núcleo
puede dinámicamente descargar plugins de un repositorio si fuesen necesarios,
ahorrando tal paso al desarrollador.
5.7.
Evaluación de la calidad
Este proyecto, al formar parte de un conjunto de herramientas interrelacionadas
creadas por el grupo de investigación UCASE, tiene como objetivo primordial ser
software de calidad. Para ayudarnos en esta tarea hemos utilizado: Sonar, una
110
Desarrollo del Proyecto
plataforma de código abierto para la calidad del software, y Jenkins un software
de integración continua de código abierto.
5.7.1.
Sonar
Sonar [50] es una herramienta que permite gestionar la calidad del código
controlando los siete ejes principales de dicha calidad del código:
Arquitectura y diseño
Duplicaciones
Pruebas unitarias
Complejidad
Errores potenciales
Reglas de codificación
Comentarios
Sonar realiza varios análisis de nuestro código a través de otras herramientas y
presenta de manera unificada a través de su interfaz la información generada por
ellas en forma de métricas. Podemos ver de forma detallada los puntos débiles de
nuestro proyecto, como errores potenciales en el código, escasez de comentarios,
código repetido, clases demasiado complejas, escasez de cobertura de las pruebas
unitarias, etc.
El principal lenguaje soportado es Java, así que es idóneo para GAmeraHOM,
aunque hay disponibles extensiones para otros lenguajes.
Los proyectos realizados por el grupo UCASE se encuentran bajo esta herramienta en la dirección https://neptuno.uca.es/sonar/, aparecerá un
listado con todos los proyectos y en lo que respecta a GAmeraHOM encontraremos GAmera2::BPEL Executor, GAmera2::Component API
y GAmera2::Core.
Cuadro de mandos
Si clicamos sobre GAmera2::Core la página que se cargará por defecto es el
cuadro de mandos (dashboard) donde se presentan los resultados de las métricas
5.7 Evaluación de la calidad
111
del proyecto de forma general (figura 5.19). Está compuesto por una serie de
cajas o widgets que representan de forma agrupada un conjunto de métricas de
naturaleza similar.
Figura 5.19: Sonar - Cuadro de mandos
Podemos encontrar los siguientes elementos:
Líneas de código y clases.
Violaciones y cumplimiento de reglas de buenas prácticas.
Comentarios y duplicaciones.
Ciclos de dependencias.
Complejidad del código.
Cohesión (LCOM4).
Cobertura del código y resultado de las pruebas.
Cada uno de estos widgets pueden consultarse para obtener información más
detallada.
112
Desarrollo del Proyecto
Si por ejemplo, entramos en el widget dedicado a los tests, obtendremos un
listado con todos los paquetes de nuestro proyecto y, dentro de cada uno de
ellos, las clases con las distintas pruebas. En la figura 5.20 podemos ver las seis
pruebas diseñadas para la clase IndividualCrossoverOperator, pasadas
con éxito.
Figura 5.20: Sonar - Pruebas
Componentes
Aquí se muestra un listado de los componentes del presente proyecto, donde
consta información sobre el grado de cumplimiento de buenas prácticas, la
cobertura del código y el tiempo de compilación de cada uno de ellos.
Violaciones
En el widget dedicado a las violaciones (figura 5.21), encontraremos aquellos
incumplimientos de reglas de buenas prácticas, mostrando el lugar donde se ha
producido esa violación y una sugerencia para solucionarlo. En este caso, Sonar
clasifica como violación importante (major) el uso de System.err.println.
Sin embargo, queremos dejar así ese fragmento para que muestre por pantalla el
uso de una llamada incorrecta al programa.
Aunque Sonar ha ayudado a una mejora notable del código de GAmeraHOM, no
es la panacea como ha podido observarse en la única violación que se detecta al
componente gamera2-core.
5.7 Evaluación de la calidad
113
Figura 5.21: Sonar - Violación
Máquina del tiempo
Desde aquí podemos estudiar la evolución del proyecto por medio de un análisis
que podemos perfeccionar a nuestro gusto.
En la figura 5.22 podemos observar cómo la complejidad del proyecto ha crecido
conforme se ha ido avanzando en el desarrollo, apenas se han tenido líneas
duplicadas y las existentes han sido eliminadas, el cumplimiento de las buenas
prácticas siempre ha tenido un alto porcentaje y con respecto a la cobertura del
código, podemos ver cómo ha aumentando en la última parte de la gráfica.
Figura 5.22: Sonar - Evolución de gamera2-core
Algunas de las métricas disponibles se representan a través de distribuciones
114
Desarrollo del Proyecto
(figura 5.23), por ejemplo, la distribución de la complejidad por clases y por
funciones, la distribución de la cohesión entre las clases, etc.
Estas gráficas se muestran al final de la página de la máquina del tiempo:
Figura 5.23: Sonar - Distribuciones
Nube de etiquetas
Con la vista en forma de nubes de etiquetas podemos detectar puntos clave en
nuestro proyecto.
Figura 5.24: Sonar - Nube con el método Quickwins
Podemos elegir entre dos opciones para crear la nube:
Top risk Donde el tamaño representa la complejidad media por método en la
clase, y el color representa la cobertura de código o el nivel de cumplimiento
de reglas.
5.7 Evaluación de la calidad
115
Quick wins Donde el tamaño representa las líneas de código de la clase. El color
representa igualmente la cobertura o el nivel de cumplimiento.
Diseño
Uno de los aspectos más importantes es evitar ciclos entre clases y paquetes,
ya que esto impide tener componentes mucho más independientes, que podrían
ser cambiados. En este widget tenemos una relación de las dependencias entre
paquetes del proyecto en cuestión.
Si nos fijamos en el paquete gamera de gamera2-core, podemos ver que el
paquete gamera.cli tiene una dependencia de entrada con el paquete gamera y
que éste tiene una dependencia de salida con el paquete gamera.conf. Es decir,
gamera.cli es un paquete que depende del paquete gamera y gamera.conf es un
paquete del que depende el paquete gamera.
Figura 5.25: Sonar - Diseño de gamera2-core
Puntos críticos
En los hotspots o puntos críticos se puede ver el listado de las principales métricas
con un ranking de los cinco primeros recursos afectados.
Bibliotecas
Si hay que evaluar la calidad de un proyecto, las dependencias con librerías
externas son muy importantes. La opción para poder analizar estas situaciones
solo está disponible cuando se trata de proyectos Java construidos con Maven.
116
Desarrollo del Proyecto
Figura 5.26: Sonar - Librerías externas de gamera2-core
5.7.2.
Jenkins
Jenkins es un software de integración continua de código abierto escrito en Java,
basado en el proyecto Hudson.
La integración continua consiste en hacer integraciones automáticas de un
proyecto lo más a menudo posible para así poder detectar fallos cuanto antes.
Entendemos por integración, la compilación y ejecución de tests de todo un
proyecto. El proceso suele ser, cada cierto tiempo, descargarse las fuentes desde
el gestor de versiones, compilarlo, ejecutar los tests y generar informes.
En la ventana principal (figura 5.27) se muestra un listado con todos los proyectos
con información sobre el estado de la última ejecución (representado por una
bola azul si todo es correcto) y un informe sobre el estado de las cinco últimas
ejecuciones (el sol indica que no hay ejecuciones recientes con fallos).
5.8.
Plan de pruebas
Uno de los pilares de la XP es el proceso de pruebas. XP anima a probar
constantemente tanto como sea posible. Esto permite aumentar la calidad de
los sistemas reduciendo el número de errores no detectados y disminuyendo el
tiempo transcurrido entre la aparición de un error y su detección. También permite
aumentar la seguridad de evitar efectos colaterales no deseados a la hora de
realizar modificaciones y refactorizaciones.
XP divide las pruebas del sistema en cuatro grupos:
Pruebas unitarias Son diseñadas por los programadores y su función es la de
verificar el código. Comprueban de forma automática la funcionalidad de
un conjunto reducido y cohesivo de clases.
5.8 Plan de pruebas
117
Figura 5.27: Jenkins
Pruebas de aceptación También son conocidas como pruebas funcionales. Están
destinadas a evaluar si al final de una iteración se consiguió la funcionalidad
requerida, es decir, la descrita en la historia de usuario correspondiente. Son
diseñadas por el cliente final, con la ayuda de los miembros especializados
en pruebas del equipo de desarrollo, ya que el cliente debe saber lo que
espera del programa, pero no tiene por qué entender de diseñar pruebas.
Pruebas de integración En XP, se requiere que todo cambio hecho en una sesión
de programación sea integrado inmediatamente en el repositorio central.
Por lo tanto, las pruebas de integración se realizan de forma constante. Por
supuesto, las pruebas de integración deben ir precedidas por las pruebas
unitarias de los módulos modificados.
Pruebas de implantación Desde el inicio de un proyecto, el sistema debe de
implantarse en un entorno similar al real, posiblemente a menor escala,
y comprobarse su correcto funcionamiento. A pesar de que es solo una
práctica recomendada (que no obligatoria) de XP, ha sido fácil seguirla
gracias al sistema de integración continua montado para el grupo de
investigación.
Siguiendo estas pautas, se han diseñado pruebas para los tres componentes de
GAmeraHOM, pero prestando especial atención a gamera2-core. El conjunto
118
Desarrollo del Proyecto
de pruebas de gamera2-core está formado por 95 tests, de los que podemos citar
los siguientes:
El lanzador falla cuando se llama a CLIRunner sin argumentos, es decir,
sin el fichero de configuración YAML.
La configuración lanza un error si el fichero de configuración YAML está
vacío o si el motor de ejecución, los operadores genéticos, los generadores
de individuos, los operadores de selección, las condiciones de parada y/o
los loggers son inválidos o no están definidos.
La configuración lanza un error si el máximo orden de mutación es cero, o
si el tamaño de la población es negativa o cero.
El generador uniforme de individuos produce un error al intentar crear un
individuo cuyo orden es menor que uno.
El generador uniforme de individuos crea un individuo válido dentro de los
rangos establecidos.es menor que uno.
El generador uniforme de individuos puede tener una probabilidad entre [0,
1] y si no, lanza un error.
La selección aleatoria de individuos devuelve un individuo dada una
población.
El método de la ruleta funciona correctamente cuando su posición de salida
es el primer individuo, el último u otro cualquiera dentro de los permitidos.
El método de la ruleta lanza un error si la posición de salida no es correcta
o está fuera de los límites.
El operador de mutación de orden debe tener el valor de su randomRange
en positivo y el scaleFactor debe estar entre [0, 1].
El operador de cruce de orden lanza un error si el punto de cruce es cero,
mayor que el máximo orden permitido por individuo o mayor que el mínimo
orden de los progenitores.
El logger de mensajes simples funciona por consola o por fichero, lanzando
un error si están activas ambas opciones.
El operador de mutación de individuo lanza un error si el mutante o tripleta
a mutar es cero o mayor que el máximo orden por individuo.
5.8 Plan de pruebas
119
El operador de mutación de individuo lanza un error si el campo a mutar no
está entre uno y tres, correspondientes al operador, localidad y al atributo.
El operador de mutación de individuo debe tener el valor de su
randomRange en positivo y el scaleFactor debe estar entre [0, 1].
El operador de cruce de individuo lanza un error si el punto de cruce es
cero, mayor que el máximo orden permitido por individuo o mayor que el
mínimo orden de los progenitores.
La condición de parada del porcentaje total de mutantes es falsa cuando no
se han generado mutantes.
La condición de parada del porcentaje total de mutantes es falsa cuando es
menor que el porcentaje de mutantes generados.
La condición de parada del porcentaje total de mutantes es cierta cuando es
igual o mayor que el porcentaje de mutantes generados.
La condición de parada del porcentaje total de mutantes lanza un error si el
porcentaje es cero, negativo o mayor que cien.
El logger de impresión del HOF por fichero crea verdaderamente un fichero.
Capítulo 6
Resultados
Llegados a este punto, ya conocemos cómo funciona GAmeraHOM y es el
momento de desarrollar un ejemplo completo para que veamos sus resultados.
El programa BPEL original loanRPC consiste en la aprobación de un préstamo
según una serie de características, podemos verlo en el anexo C.1 y el conjunto de
casos de prueba podemos encontrarlo en C.2.
La configuración de YAML que vamos a usar es la siguiente:
1
2
populationSize: 26
maxOrder: &mO 4
3
4
5
6
7
8
executor: !!exec.BPELExecutor
testSuite: src/test/resources/loanRPC/loanRPC.bpts
originalProgram: src/test/resources/loanRPC/loanRPC.bpel
outputFile: target/loanApprovalProcess.bpel.out
15
16
17
18
19
20
geneticOperators:
!!genetic.OrderMutationOperator
{selector:
&rndSel !!select.UniformRandomSelection {seed: 5},
scaleFactor: &pOMop 0.1,
randomRange: *mO} : {probability: *pOMop}
!!genetic.IndividualMutationOperator
{selector: *rndSel,
scaleFactor: &pIMOp 0.3,
randomRange: 100} : {probability: *pIMOp}
!!genetic.OrderCrossoverOperator
{} : {probability: 0.2}
!!genetic.IndividualCrossoverOperator {} : {probability: 0.4}
21
22
23
individualGenerators:
!!generate.UniformGenerator {} : {percent: 0.2}
9
10
11
12
13
14
122
24
25
26
27
28
29
30
31
32
33
selectionOperators:
!!select.RouletteSelection
Resultados
{} : {percent: 0.4}
- !!term.PercentAllMutantsCondition {percent: 0.8}
- !!term.GenerationCountCondition
{count: 10}
loggers:
- !!log.MessageLogger {console: true, file: }
- !!log.HofLogger {console: false, file: hof.txt}
Para lanzar GAmeraHOM, tenemos que situarnos en el directorio del componente
gamera2-core, abrimos una terminal y llamamos al método principal de
CLIRunner pasándole como argumento la ruta donde se encuentra nuestro
fichero de configuración YAML:
$> mvn exec:java
-Dexec.mainClass=es.uca.webservices.gamera.cli.CLIRunner
-Dexec.args="miconfiguracion.yaml"
El resultado del análisis del programa original, con la lista de operadores
aplicables, con sus localidades y atributos está en C.3.
Con estos datos podemos saber cuáles son los operadores que pueden aplicarse a
nuestro programa (aquellos cuya localidad o instrucción afectada por el operador
sea distinta de cero), solamente ocho operadores cumplen esa condición, además
del atributo más alto que puede asumir.
A partir de aquí, el algoritmo realiza su trabajo produciendo tantas generaciones
como sean necesarias, y una vez que se cumpla alguna de las condiciones de
parada, se hace uso de un logger para la impresión del HOF (listado 6.1).
28
29
22
23
24
25
26
27
16
17
18
19
20
21
10
11
12
13
14
15
4
5
6
7
8
9
1
2
3
MUTANT_0 {4 (AIE, 1, 1), (ECN, 1, 1), (ECN, 1, 2), (CDE, 1, 2)}, [1 1 1 0 0 1]
MUTANT_1 {2 (ASI, 1, 0), (EAN, 1, 1)}, [1 1 1 1 1 1]
MUTANT_2 {4 (AIE, 2, 1), (ERR, 2, 2), (XMF, 1, 1), (ASI, 2, 1)}, [1 1 1 1 1 1]
MUTANT_3 {3 (CDC, 1, 0), (EIN, 0, 0), (CFA, 2, 0)}, [1 1 1 1 1 1]
MUTANT_4 {3 (ECN, 1, 4), (EIU, 1, 0), (ASI, 0, 1)}, [1 1 1 0 0 1]
MUTANT_5 {2 (XMF, 0, 0), (ASI, 1, 1)}, [1 1 1 1 1 1]
MUTANT_6 {2 (ASI, 1, 1), (AIE, 1, 1)}, [1 1 1 1 1 1]
MUTANT_7 {1 (EAP, 1, 1)}, [0 0 0 0 0 0]
MUTANT_8 {2 (ERR, 2, 3), (AIE, 0, 0)}, [1 0 0 1 1 0]
MUTANT_9 {3 (CCO, 0, 1), (EAN, 1, 0), (CFA, 4, 1)}, [1 1 1 0 0 1]
MUTANT_10 {2 (AEL, 9, 1), (AEL, 4, 0)}, [1 1 1 1 1 1]
MUTANT_11 {2 (ASF, 0, 0), (EAN, 0, 1)}, [1 1 1 0 0 1]
MUTANT_12 {1 (EIN, 1, 1)}, [1 1 1 1 1 1]
MUTANT_13 {2 (EIN, 2, 0), (EIN, 0, 0)}, [0 0 0 0 0 0]
MUTANT_14 {2 (EAP, 0, 0), (XMF, 1, 1)}, [0 0 0 0 0 1]
MUTANT_15 {3 (EIN, 0, 1), (ECN, 1, 4), (EAN, 0, 0)}, [1 1 1 0 0 1]
MUTANT_16 {4 (ASI, 2, 1), (ASF, 0, 0), (EIU, 1, 0), (EIN, 1, 0)}, [1 1 1 1 1 1]
MUTANT_17 {3 (ASF, 1, 0), (XMF, 1, 0), (EAN, 1, 0)}, [1 1 1 0 0 1]
MUTANT_18 {4 (ERR, 2, 1), (ASF, 1, 1), (AIE, 1, 1), (CFA, 3, 0)}, [1 1 1 0 0 1]
MUTANT_19 {4 (EIU, 0, 1), (CDC, 1, 2), (CDC, 1, 1), (ASI, 1, 1)}, [1 1 1 1 1 1]
MUTANT_20 {3 (AIE, 2, 0), (ASI, 0, 1), (ASI, 1, 0)}, [1 1 1 1 1 1]
MUTANT_21 {4 (CDC, 1, 1), (CFA, 2, 0), (CDC, 1, 1), (EIU, 1, 1)}, [1 1 1 1 1 1]
MUTANT_22 {4 (CDC, 1, 1), (EAP, 1, 1), (CFA, 8, 0), (EAP, 0, 0)}, [0 0 0 1 1 0]
MUTANT_23 {2 (ASF, 1, 1), (CDE, 2, 1)}, [0 1 1 0 0 0]
MUTANT_24 {4 (CDE, 2, 1), (ASI, 2, 0), (CDE, 2, 1), (ASI, 1, 1)}, [1 1 1 1 1 1]
MUTANT_25 {1 (AEL, 9, 1)}, [1 1 1 1 1 0]
MUTANT_N {ORDER (OPERATOR, LOCATION, ATTRIBUTE)+}, [COMPARISON RESULTS]
Listado 6.1: HOF de la ejecución de LoanRPC
123
Capítulo 7
Conclusiones
Valoración
La elaboración de este Proyecto ha sido una experiencia muy enriquecedora, tanto
por formar parte activa de un grupo de investigación, como por el esfuerzo que ha
requerido.
GAmeraHOM ha supuesto un antes y un después en mi perfil como profesional.
Cuando me aventuré en este proyecto apenas dominaba lo que eran los algoritmos
genéticos, sólo una pequeña base y lo que podía intuir por su similitud con la
biología.
Haciendo balance, he adquirido amplios conocimientos sobre este campo y los
Servicios Web, he ampliado mis conocimientos sobre Java, he aprendido la
importancia de usar un sistema de control de versiones (Subversion), la utilidad
de un sistema de integración continua (Maven), el uso de un gestor de referencias
bibliográficas (Zotero), etc.
Mención destacada tiene Sonar y Jenkins que supervisaban cada modificación de
código que realizaba, lanzando alarmas si cometía algún error. Todo un quebradero de cabeza en algunos momentos, pero finalmente, ha sido tremendamente
útil.
En lo que respecta al grupo, he podido comprobar cómo los seminarios que se
realizan semanalmente son muy fructíferos, por el hecho de poder exponer tus
avances y dificultades sobre la marcha del desarrollo de tu proyecto, y recibir
la ayuda de los demás. Además, nos hemos beneficiado de los conocimientos de
algunos miembros asistiendo a talleres grupales organizados por ellos, tales como:
Zotero, Git, LyX, etc.
126
Conclusiones
Sobre el esfuerzo se ha tenido que hacer una gran planificación, ya que el
desarrollo de este Proyecto ha estado compaginado en primer lugar con las clases
del segundo ciclo de Ingeniería Informática y, por último, con el trabajo. Por ello,
ha requerido priorizar las distintas necesidades para dar cabida a todo.
Dadas las características de un proyecto de investigación, se ha hecho especial
hincapié en la elaboración de una buena documentación, superando el 26 % de
comentarios sobre el código.
Por último, y no menos importante, la realización y aceptación de dos artículos
sobre este Proyecto, en el ICE-B 2011 [20] y en las XVI JISBD [22], me ha dado
la oportunidad de que mis avances fueran evaluados por un comité. Además, la
realización por vez primera de una ponencia en público en inglés ha hecho que
me sienta más segura hablando en una lengua extranjera.
Trabajo futuro
GAmeraHOM ni mucho menos termina aquí, seguirá avanzando en su desarrollo
y se integrará con otras herramientas.
Próximamente, GAmeraHOM se adaptará a la interfaz gráfica de MuBPEL y se
desarrollará un nuevo componente, gamera2-java, que sirva para realizar un
generador de mutantes de orden superior para Java.
Como objeto de tesis, se realizará un estudio para ver cuáles son los parámetros de
configuración óptimos que generen individuos de mayor calidad y que demuestren
la efectividad de esta técnica.
Apéndice A
Manual del usuario
Los pasos que debemos seguir para instalar la distribución binaria de GAmeraHOM
son los siguientes:
1. Abrimos en una navegador la dirección http://neptuno.uca.es/
nexus.
2. Escribimos gamera2-core en el campo de texto y clicamos sobre el icono de
la lupa. Aparecerá un directorio expandido en forma de árbol con nuestro
proyecto.
3. Dentro del SNAPSHOT más reciente descargamos la distribución comprimida que deseemos y la descomprimimos en bin.
$ cd /bin
$ sudo tar xvzf gamera2-core-2.0-20120110.184316-335-dist.
tar.gz
4. Añadimos el directorio base creado al descomprimir el fichero al PATH.
Para eso, para editamos el archivo /etc/bash.bashrc:
$ sudo gedit ~/.bashrc
5. Añadimos esta línea al final:
export PATH=$PATH:~/bin/gamera2-core-2.0-SNAPSHOT
6. Guardamos y cerramos la terminal.
128
Manual del usuario
7. Para comprobar que está instalado correctamente, vamos a abrir una nueva
terminal y nos situamos dentro del directorio samples de la distribución
$ cd ~/bin/gamera2-core-2.0-SNAPSHOT/samples/
8. Una vez aquí, basta con ejecutar GAmeraHOM de esta manera:
$ gamera2 bpel.yaml
9. Cuando termine de ejecutarse, en el mismo directorio habrá aparecido un
fichero llamado hof.txt con el HOF producido por el algoritmo genético.
Esta distribución incorpora unos ejemplos en la carpeta samples con un fichero
BPEL completo y su configuración YAML.
Apéndice B
Manual del desarrollador
B.1.
Instalación de herramientas
Maven
1. Descargar la versión 3 de Maven de http://maven.apache.org/
download.html en una carpeta accesible, por ejemplo opt.
2. Abrir una terminal, situarnos donde hemos descargado Maven y descomprimirlo:
$ cd /opt
$ sudo tar xvzf apache-maven-3.0.3-bin.tar.gz
3. Agregamos M2_HOME como una variable del sistema, para ello, editamos
el archivo /etc/bash.bashrc:
$ sudo gedit /etc/bash.bashrc
4. Incluimos las siguientes líneas al final:
export M2_HOME=/opt/apache-maven-3.0.2
export PATH=$PATH:$M2_HOME/bin:
5. Guardamos los cambios, cerramos el documento y ejecutamos el comando:
$ ./etc/bash.bashrc
130
Manual del desarrollador
Subversion
Como comentamos anteriormente, los miembros del grupo UCASE utilizan un
repositorio con un control de versiones.
Vamos a utilizar Subversion y para instalarlo bastará con introducir en una
terminal la siguiente instrucción:
$ sudo apt-get install subversion
IDE
Es muy recomendable la instalación de un IDE, ya sea Eclipse o NetBeans con
soporte para Java.
El resto del manual considera que el desarrollador cuenta con Eclipse.
B.2.
Puesta a punto del proyecto
Lo primero que debemos hacer es descargarnos los componentes de GAmeraHOM, para ello vamos a usar Subversion, instalado anteriormente.
GAmeraHOM ya dijimos que está formado por gamera2-api, gamera2-bpel
y gamera2-core, así que tenemos que descargarnos los tres proyectos:
$ svn checkout https://neptuno.uca.es/svn/sources-fm/trunk/src
/gamera2-api/
$ svn checkout https://neptuno.uca.es/svn/sources-fm/trunk/src
/gamera2-bpel/
$ svn checkout https://neptuno.uca.es/svn/sources-fm/trunk/src
/gamera2-core/
Para descargar todas las dependencias de los proyectos, vamos a usar Maven que
lo hará de forma automática. Para ello, entramos con la terminal en la carpeta en
la que se encuentra cada uno de los proyectos anteriores y escribimos:
$ mvn compile
Para crear el proyecto para Eclipse, simplemente ejecutamos:
$ mvn eclipse:eclipse
B.3 Ejecución del proyecto
131
Una vez hecho esto, sólo falta importar los proyectos dentro de Eclipse siguiendo
estos pasos:
1. Dentro de Eclipse, pulsaremos en File → Import.
2. Desplegaremos el menú General, seleccionaremos Existing Projects
into Workspace y pulsamos en Next.
3. En la nueva pantalla, dejamos marcada la opción Select root
directory, con el navegador seleccionamos la carpeta en la que se encuentra el proyecto y pulsamos en Finish.
4. De nuevo, en el menú principal pulsamos sobre Window → Preferences.
5. Desplegamos el panel Java → Build Path → Classpath Variables
y pulsamos en New.
6. En el nuevo diálogo, pondremos M2_REPO en el campo Name y en Path,
seleccionaremos el fichero /.m2/repository.
B.3.
Ejecución del proyecto
Para cargar GAmeraHOM, tenemos que abrir una consola y situarnos en el
directorio de gamera2-core y escribir la instrucción:
$ mvn exec:java -Dexec.mainClass=es.uca.webservices.gamera.cli
.CLIRunner -Dexec.args="rutaFicheroYAML"
Apéndice C
Ejemplos
C.1.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Fichero BPEL de LoanRPC
<?xml version="1.0" encoding="UTF-8"?>
<process
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/
executable"
xmlns:ns1="http://j2ee.netbeans.org/wsdl/loanServicePT"
xmlns:tns=
"http://enterprise.netbeans.org/bpel/LoanApproval_V2/
loanApprovalProcess"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="
loanApprovalProcess"
targetNamespace=
"http://enterprise.netbeans.org/bpel/LoanApproval_V2/
loanApprovalProcess">
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="loanServicePT.wsdl"
namespace="http://j2ee.netbeans.org/wsdl/loanServicePT"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="AssessorService.wsdl"
namespace="http://j2ee.netbeans.org/wsdl/
ConcreteAssessorService"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="LoanService.wsdl"
namespace="http://j2ee.netbeans.org/wsdl/
ConcreteLoanService"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="ApprovalService.wsdl"
namespace="http://j2ee.netbeans.org/wsdl/ApprovalService"
134
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Ejemplos
/>
<partnerLinks>
<partnerLink
xmlns:tns=
"http://j2ee.netbeans.org/wsdl/ApprovalService"
name="approver" partnerLinkType="tns:approvalServicePLT"
partnerRole="approvalServiceRole"/>
<partnerLink
xmlns:tns="http://j2ee.netbeans.org/wsdl/
ConcreteAssessorService"
name="assessor" partnerLinkType="tns:riskAssessmentPLT"
partnerRole="riskAssessmentRole"/>
<partnerLink
xmlns:tns="http://j2ee.netbeans.org/wsdl/
ConcreteLoanService"
myRole="loanServiceRoleType"
name="customer" partnerLinkType="tns:loanServicePLT"/>
</partnerLinks>
<variables>
<variable messageType="ns1:riskAssessmentMessage"
name="risk"/>
<variable messageType="ns1:approvalMessage"
name="approval"/>
<variable
xmlns:tns="http://j2ee.netbeans.org/wsdl/loanServicePT"
messageType="tns:creditInformationMessage"
name="request"/>
</variables>
<faultHandlers>
<catch faultMessageType="ns1:errorMessage"
faultName="ns1:loanProcessFault" faultVariable="error">
<reply faultName="ns1:unableToHandleRequest" name="
Reply1"
operation="request" partnerLink="customer"
portType="ns1:loanServicePT" variable="error"/>
</catch>
</faultHandlers>
<sequence>
<receive
xmlns:tns="http://j2ee.netbeans.org/wsdl/loanServicePT"
createInstance="yes" name="ReceiveRequest" operation="
request"
partnerLink="customer" portType="tns:loanServicePT"
variable="request"/>
<if name="IfSmallAmount">
<condition>
C.1 Fichero BPEL de LoanRPC
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
( $request.amount <= 10000 )
</condition>
<sequence name="SmallAmount">
<invoke inputVariable="request" name="
AssessRiskOfSmallAmount"
operation="check" outputVariable="risk"
partnerLink="assessor"
portType="ns1:riskAssessmentPT"/>
<if name="IfLowRisk">
<condition>
( $risk.level = ’low’ )
</condition>
<assign name="ApproveLowRiskSmallAmountLoans">
<copy>
<from>true()</from>
<to part="accept" variable="approval"/>
</copy>
</assign>
<else>
<invoke inputVariable="request"
name="CheckApproverForHighRiskLowAmount"
operation="approve"
outputVariable="approval"
partnerLink="approver" portType="
ns1:loanApprovalPT"/>
</else>
</if>
</sequence>
<else>
<invoke inputVariable="request"
name="ApproveLargeAmount"
operation="approve" outputVariable="approval"
partnerLink="approver" portType="
ns1:loanApprovalPT"/>
</else>
</if>
<reply name="ReportApproval" operation="request"
partnerLink="customer"
portType="ns1:loanServicePT" variable="approval"/>
</sequence>
</process>
135
136
C.2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Ejemplos
Fichero de pruebas BPTS de LoanRPC
<?xml version="1.0" encoding="UTF-8"?>
<tes:testSuite
xmlns:ap="http://j2ee.netbeans.org/wsdl/ApprovalService"
xmlns:as="http://j2ee.netbeans.org/wsdl/
ConcreteAssessorService"
xmlns:sp="http://j2ee.netbeans.org/wsdl/ConcreteLoanService"
xmlns:gen="http://j2ee.netbeans.org/wsdl/loanServicePT"
xmlns:pr=
"http://enterprise.netbeans.org/bpel/LoanApproval_V2/
loanApprovalProcess"
xmlns:tes="http://www.bpelunit.org/schema/testSuite"
xmlns:ns1="http://j2ee.netbeans.org/wsdl/loanServicePT"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<tes:name>loanApprovalProcess</tes:name>
<tes:baseURL>http://localhost:7777/ws</tes:baseURL>
<tes:deployment>
<tes:put name="loanApprovalProcess" type="activebpel">
<tes:wsdl>LoanService.wsdl</tes:wsdl>
<tes:property name="BPRFile">LoanRPC.bpr</tes:property>
</tes:put>
<tes:partner name="approver" wsdl="ApprovalService.wsdl"/>
<tes:partner name="assessor" wsdl="AssessorService.wsdl"/>
</tes:deployment>
<tes:testCases>
<tes:testCase name="SmallAmountLowRisk" basedOn=""
abstract="false" vary="false">
<tes:clientTrack>
<tes:sendReceive
service="sp:LoanService"
port="LoanServicePort"
operation="request">
<tes:send fault="false">
<tes:data>
<gen:name>A</gen:name>
<gen:firstName>B</gen:firstName>
<gen:cantidad>1500</gen:cantidad>
</tes:data>
</tes:send>
<tes:receive fault="false">
<tes:condition>
<tes:expression>accept</tes:expression>
C.2 Fichero de pruebas BPTS de LoanRPC
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<tes:value>’true’</tes:value>
</tes:condition>
</tes:receive>
</tes:sendReceive>
</tes:clientTrack>
<tes:partnerTrack name="assessor">
<tes:receiveSend
service="as:RiskAssessmentService"
port="RiskAssessmentPort"
operation="check">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:riskLevel>low</gen:riskLevel>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
<tes:partnerTrack name="approver"/>
</tes:testCase>
<tes:testCase name="SmallAmountHighRiskOK" basedOn=""
abstract="false" vary="false">
<tes:clientTrack>
<tes:sendReceive
service="sp:LoanService"
port="LoanServicePort"
operation="request">
<tes:send fault="false">
<tes:data>
<gen:name>A</gen:name>
<gen:firstName>B</gen:firstName>
<gen:cantidad>1500</gen:cantidad>
</tes:data>
</tes:send>
<tes:receive fault="false">
<tes:condition>
<tes:expression>accept</tes:expression>
<tes:value>’true’</tes:value>
</tes:condition>
</tes:receive>
</tes:sendReceive>
</tes:clientTrack>
137
138
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
Ejemplos
<tes:partnerTrack name="assessor">
<tes:receiveSend
service="as:RiskAssessmentService"
port="RiskAssessmentPort"
operation="check">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:riskLevel>high</gen:riskLevel>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
<tes:partnerTrack name="approver">
<tes:receiveSend
service="ap:ApprovalService"
port="ApprovalServicePort"
operation="approve">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:accept>true</gen:accept>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
</tes:testCase>
<tes:testCase name="SmallAmountHighRiskRejected" basedOn=""
abstract="false" vary="false">
<tes:clientTrack>
<tes:sendReceive
service="sp:LoanService"
port="LoanServicePort"
operation="request">
134
135
136
137
138
139
<tes:send fault="false">
<tes:data>
<gen:name>A</gen:name>
<gen:firstName>B</gen:firstName>
<gen:cantidad>1500</gen:cantidad>
</tes:data>
</tes:send>
140
141
142
<tes:receive fault="false">
<tes:condition>
C.2 Fichero de pruebas BPTS de LoanRPC
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<tes:expression>accept</tes:expression>
<tes:value>’false’</tes:value>
</tes:condition>
</tes:receive>
</tes:sendReceive>
</tes:clientTrack>
<tes:partnerTrack name="assessor">
<tes:receiveSend
service="as:RiskAssessmentService"
port="RiskAssessmentPort"
operation="check">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:riskLevel>high</gen:riskLevel>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
<tes:partnerTrack name="approver">
<tes:receiveSend
service="ap:ApprovalService"
port="ApprovalServicePort"
operation="approve">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:accept>false</gen:accept>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
</tes:testCase>
<tes:testCase name="LargeAmountOK" basedOn=""
abstract="false" vary="false">
<tes:clientTrack>
<tes:sendReceive
service="sp:LoanService"
port="LoanServicePort"
operation="request">
<tes:send fault="false">
<tes:data>
<gen:name>A</gen:name>
139
140
Ejemplos
192
193
194
195
196
<gen:firstName>B</gen:firstName>
<gen:cantidad>15000</gen:cantidad>
</tes:data>
</tes:send>
197
198
199
200
201
<tes:receive fault="false">
<tes:condition>
<tes:expression>accept</tes:expression>
<tes:value>’true’</tes:value>
</tes:condition>
</tes:receive>
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
</tes:sendReceive>
</tes:clientTrack>
<tes:partnerTrack name="assessor"/>
<tes:partnerTrack name="approver">
<tes:receiveSend
service="ap:ApprovalService"
port="ApprovalServicePort"
operation="approve">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:accept>true</gen:accept>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
</tes:testCase>
<tes:testCase name="LargeAmountRejected" basedOn=""
abstract="false" vary="false">
<tes:clientTrack>
<tes:sendReceive
service="sp:LoanService"
port="LoanServicePort"
operation="request">
<tes:send fault="false">
<tes:data>
<gen:name>A</gen:name>
<gen:firstName>B</gen:firstName>
<gen:cantidad>150000</gen:cantidad>
</tes:data>
</tes:send>
<tes:receive fault="false">
C.2 Fichero de pruebas BPTS de LoanRPC
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
141
<tes:condition>
<tes:expression>accept</tes:expression>
<tes:value>’false’</tes:value>
</tes:condition>
</tes:receive>
</tes:sendReceive>
</tes:clientTrack>
<tes:partnerTrack name="assessor"/>
<tes:partnerTrack name="approver">
<tes:receiveSend
service="ap:ApprovalService"
port="ApprovalServicePort"
operation="approve">
<tes:receive fault="false"/>
<tes:send fault="false">
<tes:data>
<gen:accept>false</gen:accept>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
</tes:testCase>
<!-- For the AEL-generated mutant -->
<tes:testCase name="SmallAmountError" basedOn=""
abstract="false" vary="false">
<tes:clientTrack>
<tes:sendReceive
service="sp:LoanService"
port="LoanServicePort"
operation="request">
<tes:send fault="false">
<tes:data>
<gen:name>A</gen:name>
<gen:firstName>B</gen:firstName>
<gen:cantidad>1500</gen:cantidad>
</tes:data>
</tes:send>
<tes:receive fault="true" faultcode="
ns1:unableToHandleRequest">
<tes:condition>
<tes:expression>SOAP-ENV:Fault/detail/errorCode</
tes:expression>
142
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
Ejemplos
<tes:value>5</tes:value>
</tes:condition>
</tes:receive>
</tes:sendReceive>
</tes:clientTrack>
<tes:partnerTrack name="assessor">
<tes:receiveSend
service="as:RiskAssessmentService"
port="RiskAssessmentPort"
operation="check">
<tes:receive fault="false"/>
<tes:send fault="true"
faultcode="ns1:loanProcessFault"
faultstring="Assesor failed to handle the request">
<tes:data>
<errorCode>5</errorCode>
</tes:data>
</tes:send>
</tes:receiveSend>
</tes:partnerTrack>
<tes:partnerTrack name="approver"/>
</tes:testCase>
</tes:testCases>
</tes:testSuite>
C.3 Análisis de LoanRPC.bpel
C.3.
143
Análisis de LoanRPC.bpel
Operador
Localidad
Atributo
Operador
Localidad
Atributo
ISV
EAA
EEU
ERR
ELL
ECC
ECN
EMD
EMF
ACI
AFP
ASF
AIS
AIE
AWR
AJC
ASI
0
0
0
2
0
0
1
0
0
0
0
1
0
2
0
0
2
1
4
1
5
1
1
4
2
1
1
1
1
1
1
1
1
1
APM
APA
XMF
XMC
XMT
XTF
XER
XEE
AEL
EIU
EIN
EAP
EAN
CFA
CDE
CCO
CDC
0
0
1
0
0
0
0
0
9
1
2
1
1
9
2
2
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
2
2
2
Bibliografía
[1] David Booth, Hugo Haas, Francis McCabe, Eric Newcomer, Michael
Champion, Chris Ferris, and David Orchard. Web Services Architecture,
2004. http://www.w3.org/TR/ws-arch/.
[2] OASIS. Web Services Business Process Execution Language 2.0, 2007.
http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.
0-OS.html.
[3] IDC. Research Reports, 2008. http://www.idc.com.
[4] Richard A. DeMillo, Richard J. Lipton, and Frederick G. Sayward. Hints on
Test Data Selection: Help for the Practicing Programmer. Computer, 11(4):
34–41, 1978. ISSN 0018-9162.
[5] Richard G. Hamlet. Testing Programs with the Aid of a Compiler. IEEE
Transactions Software Engineering, 3(4):279–290, 1977.
[6] Martin R. Woodward.
Mutation testing —its origin and evolution.
Information and Software Technology, 35(3):163–169, 1993.
[7] Yue Jia and Mark Harman. An Analysis and Survey of the Development
of Mutation Testing. IEEE Transactions on Software Engineering, 99
(PrePrints), 2010. ISSN 0098-5589.
[8] Yu-Seung Ma, Jeff Offutt, and Yong Rae Kwon. MuJava: an automated class
mutation system. Software Testing, Verification & Reliability, 15(2):97–133,
2005. ISSN 0960-0833.
[9] Javier Tuya, M.a José Suárez Cabal, and Claudio de la Riva. Mutating
database queries. Information and Software Technology, 49(4):398–417,
2007.
146
BIBLIOGRAFÍA
[10] K. N. King and A. Jefferson Offutt. A FORTRAN language system for
mutation-based software testing. Software - Practice and Experience, 21(7):
685–718, 1991.
[11] Márcio Eduardo Delamaro and José Carlos Maldonado. Proteum–a tool for
the assessment of test adequacy for C programs. In Conf. on Performability
in Computing System, pages 79–95, 1996.
[12] Yue Jia and Mark Harman. MILU: A customizable, runtime-optimized
higher order mutation testing tool for the full C language. In TAIC-PART
’08: Testing: Academic & Industrial Conference - Practice and Research
Techniques, pages 94–98. IEEE, 2008.
[13] Antonia Estero-Botaro, Francisco Palomo-Lozano, and Inmaculada MedinaBulo. Mutation Operators for WS-BPEL 2.0. In ICSSEA 2008: 21th
International Conference on Software & Systems Engineering and their
Applications, 2008.
[14] Juan Boubeta Puig. Implementación de operadores de mutación para WSBPEL. Master’s thesis, Universidad de Cádiz, 2010.
[15] Juan José Domínguez Jiménez, Antonia Estero Botaro, Antonio García
Domínguez, and Inmaculada Medina Bulo. Evolutionary Mutation Testing.
Information and Software Technology, 2011. http://dx.doi.org/10.
1016/j.infsof.2011.03.008.
[16] Juan José Domínguez-Jiménez, Antonia Estero-Botaro, Antonio GarcíaDomínguez, and Inmaculada Medina-Bulo. GAmera: an Automatic Mutant
Generation System for WS-BPEL Compositions. In ECOWS’09: Seventh
IEEE European Conference on Web Services, 2009.
[17] David E. Goldberg. Genetic algorithms in search, optimization and machine
learning. Addison-Wesley, Reading, 1989.
[18] Yue Jia and Mark Harman. Higher Order Mutation Testing. Information and
Software Technology, 51(10):1379–1393, 2009. ISSN 0950-5849.
[19] Ian Sommerville, Galipienso, M.a Isabel A. Galipienso, and Antonio Botia
Martinez. Ingeniería del software. Pearson educación. Pearson Educación,
2005. ISBN 9788478290741.
[20] Emma Blanco-Muñoz, Antonio García-Domínguez, Juan José DomínguezJiménez, and Inmaculada Medina-Bulo. Towards Higher-order Mutant
Generation for WS-BPEL. In ICE-B, pages 143–148, 2011.
BIBLIOGRAFÍA
147
[21] International Conference on e-Business. http://ice-b.icete.org/.
[22] Emma Blanco Muñoz, Antonio García Domínguez, Juan José Domínguez
Jiménez, and Inmaculada Medina Bulo. Propuesta de una arquitectura para
la generación de mutantes de orden superior en WS-BPEL. In Actas de las
XVI Jornadas de Ingeniería del Software y Bases de Datos, 2011.
[23] Thomas Erl. Service-Oriented Architecture: A Field Guide to Integrating
XML and Web Services. Prentice Hall PTR, Upper Saddle River, NJ, USA,
2004. ISBN 0131428985.
[24] Shien-Chiang Yu and Ruey-Shun Chen. Web Services: XML-based system
integrated techniques. The Electronic Library, 21(4):358–366, 2003.
[25] Charles Darwin. On the Origin of Species by Means of Natural Selection.
Murray, London, 1859. or the Preservation of Favored Races in the Struggle
for Life.
[26] John H. Holland. Adaptation in natural and artificial systems. MIT Press,
Cambridge, 1992.
[27] D.F Jones, S.K Mirrazavi, and M Tamiz. Multi-objective meta-heuristics: An
overview of the current state-of-the-art. European Journal of Operational
Research, 137(1):1 – 9, 2002. ISSN 0377-2217.
[28] J.J. Grefenstette and Vanderbilt University. Dept. of Computer Science. A
user’s guide to GENESIS. Technical report (Vanderbilt University. Dept. of
Computer Science). Computer Science Dept., Vanderbilt University, 1986.
[29] Robert E. Smith, David E. Goldberg, and Jeff A. Earickson. Sga-c: A clanguage implementation of a simple genetic algorithm, 1991.
[30] D. Whitley and K. Kauth. GENITOR: A different genetic algorithm.
In Proceedings of the 1988 Rocky Mountain Conference on Artificial
Intelligence, pages 118–130, 1988.
[31] Kenneth A. De Jong. An analysis of the behavior of a class of genetic
adaptive systems. PhD thesis, Ann Arbor, MI, USA, 1975.
[32] Juan José Domínguez-Jiménez, Antonia Estero-Botaro, and Inmaculada
Medina-Bulo. A framework for mutant genetic generation for WS-BPEL.
pages 229–240, 2009.
[33] ActiveVOS. ActiveBPEL WS-BPEL and BPEL4WS engine, October 2009.
http://sourceforge.net/projects/activebpel502/.
148
BIBLIOGRAFÍA
[34] Daniel Lübke and Antonio García Domínguez. BPELUnit - The Open
Source Unit Testing Framework for BPEL, November 2010. http://www.
se.uni-hannover.de/forschung/soa/bpelunit/.
[35] Forja del Departamento de Lenguajes y Sistemas Informáticos. https:
//neptuno.uca.es/redmine/.
[36] Kenneth A. De Jong.
Version Control with Subversion, 2006.
BenCollins-Sussman,BrianW.Fitzpatrick,yC.MichaelPilato.
[37] Mike Mason. Pragmatic Version Control Using Subversion. The Pragmatic
Programmers, 2008.
[38] Justin Couch and Daniel H. Steinberg. Java 2 Bible. John Wiley & Sons,
Inc., New York, NY, USA, 2002. ISBN 0764523465.
[39] Trail: The Reflection API (The JavaTM Tutorials). http://docs.oracle.
com/javase/tutorial/reflect/.
[40] Oren Ben-Kiki, Clark Evans, and Brian Ingerson. YAML ain’t markup
language (YAML) (tm) version 1.2. Technical report, YAML.org, 9 2009.
http://www.yaml.org/spec/1.2/spec.html.
[41] Tim OBrien, Jason Van Zyl, Brian Fox, John Casey, Juven Xu, Thomas
Locher, Dan Fabulich, Eric Redmond, Larry Shatzer, and Bruce Snyder.
Maven: By Example An Introduction to Apache Maven. Sonatype, Inc.,
2010. 1–138 pp.
[42] José H. Canós, Patricio Letelier, and M.a Carmen Penadés. Metodologías
Ágiles en el Desarrollo de Software. In Actas de las VIII Jornadas de
Ingeniería del Software y Bases de Datos, 2003.
[43] Kent Beck and Cynthia Andres. Extreme Programming Explained: Embrace
Change (2nd Edition).
Addison-Wesley Professional, 2004.
ISBN
0321278658.
[44] Ron Jeffries.
Misconceptions about XP, 2002.
http://www.
xprogramming.com/xpmag/Misconceptions.htm.
[45] Antonia Estero Botaro, Francisco Palomo Lozano, and Inmaculada Medina
Bulo. Mutation Operators for WS-BPEL 2.0. In ICSSEA 2008: Proceedings
of the 21th International Conference on Software & Systems Engineering
and their Applications, 2008.
BIBLIOGRAFÍA
149
[46] Francisco Palomo-Lozano Antonia Estero-Botaro and Inmaculada MedinaBulo. Quantitative Evaluation of Mutation Operators for WS-BPEL Compositions. IEEE International Conference on Software Testing Verification
and Validation Workshop, 0:142–150, 2010.
[47] The Apache Software Foundation, 2011. http://www.apache.org.
[48] Achut Reddy. Java Coding Style Guide. http://developers.sun.com/
sunstudio/products/archive/whitepapers/java-style.pdf.
[49] yedit - Eclipse plugin for editing YAML files. http://code.google.
com/p/yedit/.
[50] Sonar. http://www.sonarsource.org/downloads/.
Descargar