1 ' i 3 ' L I 4 h DGlT SElT SEP / P-2 -.& Centro Nacional de Investigación y Desarrollo Tecnológico cenidet Reconocimiento de patrones de diseño de Gamma a partir de la forma canónica definida en el IPADIC++ - . TESIS Que para obtener el grado de Maestro en Ciencias en Ciencias Computacionales presenta Patricia Zavaleta Carrillo 'L Directores de Tesis: M.C. Máximo López Sánchez M.C. René Santaolaya Salgado .'. ,... \. 3 7 .. Cuernavaca, Morelos Enero de 2002 - I, . . ..' . .' ' . . ' . . .... . . . . .. . . ~ . ~ ...,. . . , .. . " "' ;,..4 ."I .. . . . 'i Centro Nacional de Investigación y 'Desarrollo Tecnológkb' FORMA C 3 REVISION DE TESIS . Cuernavaca, Morelos a 03 de diciembre de 2901 ... . ' . Dr. Raúl Pinto Elías Presidente'de la Academia de Ciencias Computacionales Presente Nos es grato comunicarle, que conforme a los lineamientos para la obtención del dado de Maestro en Ciencias de este Centro, y después de haber sometido a revisión académica la tesis denominada: RECONOCIMIENTO DE PATRONES DE DISENO DE GAMMA A PARTIR DE LA FORMA CANONICA DEFINIDA EN EL lPADlC+ +, realizada por la C. PATRlClA ZAVALETA CARRILLO, y habiendo cumplido con todas las correcciones que le fueron indicadas, acoidamos nÓ tener objeci6n para que se le conceda la au'torización de impresión de la tesis. Sin otro particular, quedamos de usted. Atentamente La comisión de revisión de tesis # M.C. MAXIM & C.C.P. Dr. Rodolfo A. Pazoc RangellJefe del Departamento de Ciencias Computacionales INTERIOR INTERNADO PALMIRA S/N. CUERNAVACA. MOR MCXICO APARTADO POSTAL SI64 CP 62050. CUERNAVACA, TELS [73)12 2314.12 7613.18 7741.FAX173) 12 2434 - . ,> I SIP Centro Nacional de Investigación y Desarrollo Tecnológico". FORMA C 4 AUTORIZACION DE IMPRESIÓN DE TESIS ~. 7' Cuernavaca, Morelos a 1O de enero de 2 0 2 C. PATRICIA ZAVALETA CARRILLO Candidato al grado de Maestro e n Ciencias en Ciencias Computacionales Presente . .I ., . - .. .. ~ ....~ - . . .. ~ Después de haber atendido las indicaciones sugeridas por la Comisión Revisora d e la Academia de Ciencias Computacionales e n relación a su trabajo de tesis: RECONOCIMIENTO DE PATRONES DE DISEÑO DE GAMMA A PARTIR DE LA FORMA CANONICA DEFINIDA EN EL lPADlC+ +, m e es grato comunicarle, que conforme a los lineamientos establecidos para la obtención del grado d e Maestro e n Ciencias en este Centro, se le concede la autorización para que proceda con la impresión de su tesis. , Atentamente Dr. R o d o l f o d Sazos Rangel Jefe del Depto. de Ciencias Computacionales INTERIOR INTERNADO PALMIRA S/N. CUERNAVACA. MOR. MCXICO APARTADO POSTAL 5-1 64 CP 62050. CUERNAVACA. TELS. (73112 2314,12 7613.18 7741.FAX173) 12 2434 ~ A L A U na7ncrñcrl-rnnirlnt rnm my cenidef A mis padres Francisco ‘ y Medarda A mis hermanos y a mi familia A los amigos de toda la vida y a todas aquellas personas que creyeron en mi Agradezco a: Dios por las bendiciones que me ha dado y porque siempre ha estado conmigo incondicionalmente. Mis asesores de tesis M.C. Máximo López Sánchez y M.C. René Santaolaya Salgado por darme mucho de su tiempo y compartir conmigo sus experiencias y conocimientos. Gracias por su sincera amistad. Mis revisores de tesis M.C. Ohvia Fragoso Díaz , M.C. Andrea Salazar Magadán y M.C. Reynaldo Alanis Cantú, por sus sugerencias para enriquecer este trabajo de tesis. Mis maestros y amigos por compartir conmigo sus conocimientos y experiencias. Mis compañeros de generación Anely, Iris, Areli, Anel, Socorro, Mario, Leone], Hugo, David, Giovanni, Agustín, Fernando, Moisés, Antonio, Eduardo y a mis compañeros de las áreas de electrónica, mecánica y mecatrónica por brindarme su amistad y apoyo. Mis amigos Zulma y su familia que han sido como mi segunda familia; a Ely, Anita, Fabian, Chely, Anely, Gaby y en general a todas aquellas personas que me han dado cariño, amistad y apoyo en algunos momentos de.mi vida. Cecilia y Miriam del centro de cómputo, Anita y Mario de la biblioteca, gracias por la ayuda y amistad que me brindaron siempre. La Secretaría de Educación Pública (SEP) por el apoyo económico que me brindó durante mi estancia en esta institución. Resumen En el desarrollo de software un objetivo fundamental es la instrumentación de métodos y técnicas que permitan producir software de calidad con un mínimo de tiempo de desarrollo. El desarrollo de software basado en componentes es un método que permite producir software a tiempo y mínimo costo de producción, y aumentando su confiabilidad. Los patrones de diseño consideran arquitecturas revisadas para garantizar un mayor grado de reuso, por lo tanto, es deseable que el diseño de un componente este basado en estos patrones de diseño, lo cual asegura su calidad y reusabilidad. En el Centro Nacional de Investigación y Desarrollo Tecnológico (Cenidet), se trabaja en un proyecto relacionado con el desarrollo y administración de componentes de software, un subproyecto dentro de este proyecto es el IPADIC++, el cual es una herramienta que busca un mayor factor de reuso de código orientado a objetos, utilizando patrones de diseño como plantillas que guían el proceso de mejora continua de la arquitectura de los programas. El objetivo principal en este trabajo de tesis es ampliar los alcances del reconocimiento de patrones de diseño en código escrito en lenguaje C++, mediante la implementación. del reconocimiento de la gramática completa del lenguaje ‘C++ bajo el estándar ANSI-IS0 y la implementación del reconocimiento de otros patrones de diseño descritos en el catálogo de Gamma et.al. [GAM951 adicionales a los considerados en el IPADIC++. La herramienta esta constituida por dos módulos. El primero recibe como entrada código escrito en lenguaje C++. Este código es analizado sintácticamente, obteniéndose una cadena de texto (forma canónica) que representa información de la estructura de clases del código que se analiza. Esta forma canónica es recibida por el segundo módulo el cual realiza un reconocimiento de los patrones de diseño a través del análisis de esta forma canónica. Hay dos posibles resultados obtenidos al analizar códigos escritos en lenguaje C++ con esta herramienta: “PATRON ENCONTRADO Ó “PATRON NO ENCONTRADO’. De los casos de prueba realizados para evaluar la herramienta se concluye que los resultados obtenidos fueron los esperados, de acuerdo al análisis manual que se hizo al código fuente de los casos de prueba. i TABLA DE CONTENIDO Resumen......................................................................................................................... Tabla de contenido......................................................................................................... Lista de figuras..................... ..:........................................................... ..;.......................... Lista de tablas .....;........................................................................................................... , . Glosario de terminos .................................................................................................... i .< ii :. v ... vi11 ix ........................... 1 ......................................... 2 3 3 3 4 4 4 4 4 5 5 6 Capítulo 2. ESTADO DEL ARTE ...................1 ........;.............................. ., 2.1 Introduccion ............................................................................................................. 7 Capítulo 1. INTRODUCCI~N .................................... ., 1.1 Introduccion .................................................................. . . : 1.2 Antecedentes............................................................................................................ 1.2.1 Sistema para identificación de patrones de diseño en código C t t................ . ., 1.3 Descripcion del problema..: ..................................................................................... ., 1.4 Propuesta de solucion.............................................................................................. 1.5 Objetivos............................................ ;........................................ ;............................. 1.5.1 Objetivo general ................ ............................................................................ . . 1.5.2 Objetivos específicos............................................................... ;..................... 1.6 Metodología .................................................. ;.......................................................... 1.7 Beneficios................................................................................................................. 1.8 Alcance y limitaciones...........~ ................................................................................. . r 1.9 Organizacion del documento................................................................................... ~ 2.2 Investigación de patrones de diseño implementados en el desarrollo de software . 2.3 Investigación de patrones de diseño en la reingeniería ............................................ 2.3.1 Un método inductivo para descubrir patrones de diseño desde sistemas de software orientados a objetos.................................................................................. 2.3.2 Recuperación de diseño mediante búsqueda automática de patrones de diseño estructurales en software orientado a objetos .............................................. 2.3.3 Ingeniería inversa de diseño y detección automática de patrones de diseño en Smalltalk............................................................................................................. 2.3.4 Identificación automática de patrones de diseño........................................... 2.3.5 Comprensión de frameworks y patrones de diseño: un enfoque de . , . ingenieria inversa .................................................................................................... 2.3.6 Ingeniería inversa de componentes de diseño basada en patrones ................. 2.4 Conclusiones............................................................................................................ 8 8 9 9 10 10 11 11 12 13 .. I1 Capítulo 3 .MARCO TEÓRICO .............................................................. .. 3.1 Introduccion ............................................................................................................. 3.2 Desarrollo de software basado en componentes...................................................... 3.3 Modelo orientado a objetos............................................................ :........................ 3.4 Lenguajes de patrones .................... 1......................................................................... . 3.4.1 Patrones de diseno .......................................................................................... . . 3.5 Gramaticas................................................................................................................ 3.5.1 Gramáticas libres de contexto ........................................................................ 3.5.2 Gramáticas regulares ...................................................................................... 3.6 Generador de parsers ................................................................................................ 3.7 JavaCC..................................................................................................................... . I Capítulo 4 MODELO CONCEPTUAL DEL S STEMA..................... .. 4.1 Introduccion........................................................................................................ ;.... ... 4.2 Analisis del sistema .................................................................................................. 4.2.1 Análisis del IPADIC++.................................................................................. 4.2.2 Estudio del parser que compila el código fuente según la gramática del lenguaje C++ .................................................................................................. 4.2.3 Análisis de información requerida................................................................. 4.3 Arquitectura de la herramienta ................................................................................. 4.3.1 Módulo para la transformación del código C++ a la forma canónica ............ 4.3.2 Módulo de reconocimiento de patrones de diseño ......................................... 4.4 Interfaz ai usuario ..................................................................................................... . 14 15 15 18 20 21 23 23 25 25 26 29 30 30 30 33 34 37 40 46 48 Capítulo 5 EVALUACIÓN EXPERIMENTAL.............................. ..... 50 5.1 Hipótesis de investigación........................................................................................ 5.2,Definición de casos de estudio................................................................................. 5.3 Instrumentos de medición aplicados........................................................................ 5.4 Plan de pruebas .............................................................................................. ........... .. 5.4.1 Requisitos ambientales................................................................................... 5.4.2 Características a ser probadas ........................................................................ 5.4.3 Características a no ser probadas ................................................................... 5.4.4 Especificación de entrada ............................................................................... .. 5.4.5 Especificacion de salida......................................................................... ;....... .. de pruebas ............................................................................... 5.4.6 Identificacion 5.5 Resultados de las pruebas ......................................................................................... 5.5.1 Caso de prueba 1 ............................................................................................ 5.5.2 Caso de prueba 2 ............................................................................................ 5.5.3 Caso de prueba 3............................................................................................ 5.5.4 Caso de prueba 4 .................................................................. ......................... 51 51 51 51 52 53 53 54 54 54 55 56 58 58 59 ~ ... 111 5.5.5 Caso de prueba 5............................................................................................ 5.5.6 Caso de prueba 6............................................................. ;.............................. 5.5.7 Caso de prueba 7............................................................................................ 5.5.8 Caso de prueba 8............................................................................................ 5.5.9 Caso de prueba 9............................................................................................ 5.5.10 Caso de prueba 10........................................................................................ 5.5.11 Caso de prueba 11...............!........................................................................ 5.5.12 Caso de prueba 12........................................................................................ 5.5.13 Caso de prueba 13........................................................................................ 5.5.14 Caso de prueba 14........................................................................................ 5.5.15 Caso de prueba 15........................................................................................ 5.5.16 Caso de prueba 16........................................................................................ 5.5.17 Caso de prueba 17........................................................................................ 5.5.18 Caso de prueba 18........................................................................................ 5.5.19 Caso de prueba 19........................................................................................ 5.5.20 Caso de prueba 20........................................................................................ 5.6 Resumen de resultados........ .................................................................................... 59 60 61 61 62 62 63 64 64 65 66 66 67 67 68 68 69 Capítulo 6.CONCLUSIONES................................................................ 70 6.1 Conclusiones generales............................................................................................ 6.2 Trabajos futuros........................................................................................................ 71 71 Bibliografia..................................................................................................................... Anexo A . Patrones de diseño reconocidos en la tesis.................................................... Anexo B . Códigos correspondientes utilizados en la evaluación experimental............. Anexo C. Funcionamiento del sistema.......................................................................... 73 76 83 100 iv Lista de Figuras . Descripción No de figura 'Esquema del parser y scanner.......................................................... 3.1 Página 26 3.2 Pantalla de generación del analizador: ............................................. 21 3.3 Pantalla de selección de opciones para el analizador....................... 21 3.4 Pantalla de confirmacion .................................................................. 28 4.1 Pantalla principal del IPADICtt ..................................................... 31 4.2 Ventana de diálogo de detección de patrones de diseño................. 32 4.3 Estructura general de la herramienta ................................................ 31 4.4 Diagrama de clases de la herramienta .............................................. 38 4.5 Diagrama de clases del analizador sintáctico para ¡a gramática del ................................................ lenguaje C++................................... 39 Diagrama de clases del analizador sintáctico para la gramática de . - ..................................................................... los patrones de diseno 39 Entradas y salidas del módulo para transformar el código escrito en lenguaje C++ a la forma canónica ............................................... 40 4.8 Ejemplo en el que se visualizan entradas y salidas del módulo ....... 45 4.9 Entradas y salidas del módulo de reconocimiento de patrones de diseño............................................................................................... 46 Ejemplo en el que se visualizan entradas y salidas del módulo de reconocimiento de patrones de diseño............................................. 48 4.11 Interfaz principal del sistema ........................................................... 49 5.1 Pantalla principal de la interfaz, mostrando opciones del menú archivo............................................................................................. 56 5.2 Ventana de diálogo para abrir archivo fuente.................................. 56 5.3 Pantalla después de elegir el código fuente...................................... 51 5.4 Resultado de buscar el patrón de diseño abstract factory .............. 51 .. ~ 4.6 4.1 4.10 V . No de figura Descripción Página 5.5 Resultado de buscar el patrón de diseño composite ......................... 58 5.6 Resultado de buscar el patrón de diseño iterator ............................. 58 5.7 Resultado de buscar el patrón de diseño abstract factory en el código del patrón composite ............................................................. 59 Resultado de buscar el patrón de diseño Abstract Factory en el . . del patrón iterator................................................................ codigo 60 Resultado de buscar el patrón de diseño composite en el código del patrón abstract f a c t o v .............................................................. 60 Resultado de buscar el patrón de diseño composite en el código del patrón iterator ............................................................................ 61 Resultado de buscar el patrón de diseño iterator en el código del patrón abstract factory ................................................................... 61 Resultado de buscar el patrón de diseño iterator en el código del patrón composite ............................................................................ 62 Resultado de buscar el patrón de diseño abstract factory en la tesis de maestría ....................................................... :....................... 63 Resultado de buscar el.patrón de diseño composite en la tesis de maestría ............................................................................................ 63 Resultado de buscar el patrón de diseño iterator en la tesis de maestría ............................................................................................ 64 5.16 Resultado de buscar el patrón de diseño strategy ............................ 65 5.17 Resultado de buscar el patrón de diseño template method ............. 65 5.18 Resultado de buscar el patrón de diseño strategy en el código del abstract factory ............................................................................... 66 Resultado de buscar el patrón de diseño strategy en el código del iterator ............................................................................................ 66 Resultado de buscar el patrón de diseño strategy en el código del composite ......................................................................................... 67 5.8 5.9 5.10 5.11 5.12 5.13 5.14 5.15 5.19 5.20 vi . No de figura Descripción 5.21 Resultado de buscar el patrón de diseño temulate method en el . . codigo del abstractfactory ............................................................... 5.22 Página 67 Resultado de buscar el patrón de diseño template method en el código del iterator............................................................................ 68 Resultado de buscar el patrón de diseño template method en el .. codigo del compsite....................................................................... 68 A.1 Estructura del patrón de diseño abstract factory ............................ 77 A.2 Estructura del patrón de diseño composite ...................................... 78 A.3 Estructura del patrón de diseño iterator........................................... 79 A.4 Estructura del patrón de diseñofactory method.............................. 80 A.5 Estructura del patrón de diseño strategy .........1................................ 81 A.6 Estructura del patrón de diseño template method........................... 82 c.1 Opciones del menú archivo............................................................. 101 c.2 Ventana de diálogo para seleccionar archivo con extensión cpp..... 101 c.3 Contenido de paneles después de elegir el archivo a analizar.......... 102 c.4 Contenido de panel de forma canónica del código fuente si hay error sintáctico en el archivo analizado............................................ 102 c.5 Pantalla resultante al elegir un patrón de diseño a detectar.............. 103 C.6 Submenú para patrones creacionales del menú detección............. 103 c.7 Submenú para patrones de comportamiento del menu detección .. 104 C.8 Submenú para patrones estructurales del menú detección ............. 104 c.9 Opciones del menú ayuda ............................................................... 104 c.10 Ventana de diálogo de contenido del sistema................................. 105 c.11 Ventana de diálogo de patrones de diseño .................................. c.12 Ventana de diálogo de acerca de..................................................... 5.23 . . .... 105 105 vii Lista de Tablas 3.1 Descripción Clasificación de los patrones de diseño de Gamma ......................... Página 22 4.1 Ejemplo del contenido de las tablas de información ........................ 36 No. de tabla ... VI11 Glosario de términos BACKDOOR. Acrónimo de las siglas en inglés de Backwards Architecture Concerned with Knowledge Discovery of Object Oriented Relationships. Herramienta que implementa un método inductivo para descubrir patrones de diseño desde sistemas de sofhvare orientados a objetos. CDZF. Acrónimo de Case Interchange Format. Es un cuerpo estándar patrocinado por EIA (Electronic Industries Association) y el ISO, cuya misión es permitir el intercambio entre herramientas de modelado tal como herramientas CASE. Para esto, CDIF define una arquitectura metamodelo de 4 capas formal, formatos de transferencia y un metamodelo que actúa como la comprensión común implícita de lo que los datos de las herramientas nos dicen. Cenidet. Acrónimo de Centro Nacional de Investigación y Desarrollo Tecnológico Clase abstracta. Una clase abstracta actúa como una plantilla de otras clases. Normalmente se utiliza como la raíz de una jerarquía de clases. COTS (Components OffThe Shelf).- Definición de marcos de aplicaciones de caja negra o de componentes estandarizados de vitrina. Dinamic binding (ligadura dinámica). Sinónimo de late binding (ligadura tardía). D P H . Herramienta que automatiza la detección, identificación y clasificación de patrones de diseño en programas C++. Framework. Es una aplicación “semi-completa” reusable que puede ser especializada para producir aplicaciones a la medida. Framework Luthier. Es una aplicación que provee soporte para la construcción de libros electrónicos completamente integrados con las visualizaciones desarrolladas a partir de la información coleccionada de algún programa analizado. Forma canbnicu. La forma canónica es una forma de representación, basada en cadenas de texto de los nombres de clases y las relaciones estructurales entre las clases de un sistema, separadas por una coma. Herramientas CASE. (Siglas en Inglés de Ingeniería de Sistemas apoyada por computadora) Proporciona formas orientadas gráficamente para expresar planos, modelos y diseños. Hiperdocumentos. Documentos que tienen estructura de hipertexto, pero además referencias a objetos multimediales (como sonidos, imágenes, videos). ix Ingeniería inversa. Es el proceso de analizar un sistema para: a) Identificar los componentes del sistema y sus interrelaciones, y b) Crear representaciones de un sistema en otra forma en un más alto nivel de abstracción. IPADZC++. Acrónimo de Sistema para Identificación de Patrones de Diseño en Código C++. Herramienta que detecta patrones de diseño en código escrito en lenguaje C++. KT. Herramienta que aplica ingeniería inversa a diagramas de diseño de código smalltalk para detectar patrones de diseño. OMT. Acrónimo de las siglas en inglés de Object Modeling Tecnique. Técnica de modelado de objetos. Metodología orientada a objetos para el desarrollo de software. Overloading (sobrecarga). Proceso de escribir más de una función u operador con el mismo nombre. Las funciones deben .diferir en su lista de argumentos de modo que el lenguaje puede identificarlas con una llamada. Override (anular, ignorar, redefinir, Reimplantar). Se utiliza para describir la reimplementación de los métodos en tipos objeto. PAT. Acrónimo de las siglas en inglés Program Anaiys& Tool. Herramienta que realiza la búsqueda de patrones de diseño en sistemas orientados a objetos. Reingeniería. Examina los sistemas y aplicaciones de información con la intención de reesbycturarlos o reconstruirlos de tal modo que muestre una mayor calidad. Refacforización. "Refactorizar un software es modificar su estructura interna con el objeto de que sea más fácil de entender y de modificar a futuro, tal que el comportamiento observable del software al ejecutarse no se vea afectado." [FOW99]. UML. Acrónimo de las siglas en inglés Unified Modelig Language. E s una notación (principalmente diagramática) para el modelado de sistemas usando conceptos orientados a objetos. X Capítulo 1 ’ INTRODUCCI~N Capítulo 1 En este capítulo se presentan algunos puntos importantes resaltando la importancia de la tesis en el área de la Ingeniería de Software. Se provee una ubicación acerca del contexto en el cual se llevó a cabo la presente tesis, se describe el problema a solucionar, la solución propuesta, los objetivos principales, la metodología seguida para resolver el problema, así como los beneficios y alcances de la misma. 1 Capítulo 1 1.1 Introducción INTRODUCCI~N .. 1 Uno de los objetivos más importantes be la Ingeniería de Software es el diseño e instrumentación de métodos y técnicas que permitirán producir software de calidad con un mínimo de tiempo de desarrollo. Uno de estos métodos es el desarrollo de software basado en componentes, los cuales han sido previamente construidos y tienen probada su calidad, I Entre los .beneficios del desarrollo de software basado en componentes está su potencial para reducir costos, reducir tiempos. de producción de software y aumentar la confiabilidad, ya que los componentes de software deben ser verificados para prevenir errores en ellos; por lo tanto, facilitar el desarrollo’de software basado. en componentes sería de gran utilidad.al área de desarrollo de aplicaciones de software [NOV97] ~ i Para que los componentes sean reusables deben cumplir con las siguientes características: que obedezcan a una arquiteckra bien diseñada, es decir, que tengan la forma de plantillas genéricas, en las que se vea; disminuidos algunos problemas como son las dependencias funcionales, que .dichas plantillas sean cerradas a las modificaciones y abiertas a las extensiones [MAR96], y que además sean recurrentes, es decir, que se utilicen frecuentemente. Cuando existen componentes que cumplen con estas características se puede hablar de patrones de diseño, los cuales define [GAM951 como “un conjunto de clases que trabajan en colaboración en la solución de un problema que se presenta recurrentemente bajo un mismo contexto, o de problemas similares; y que además han sido analizadas y diseñadas de conformidad a las características antes mencionadas”. Si los componentes están organizados como patrones de diseño, se puede asegurar en mayor medida su calidad y también su reusabilidad. i Christopher Alexander [GAM951 define un patrón de diseño ‘como sigue: “Cada patrón describe un problema, el cual ocurre una y otra vez en nuestro ambiente, describe entonces el núcleo de la solución de tal forma que se puede’utilizar esta solución un millón de veces sin hacerlo de la misma forma dos veces”. i En general un patrón tiene cuatro elementos esenciales: un nombre, el problema, la solución y las consecuencias. El nombre representa una manija que se puede utilizar para describir en una o dos palabras un problema de diseño, su solución y sus consecuencias. El problema describe cuando aplicar el patrón, explica el problema y su contexto. La solución describe los elementos que conforman el diseño, sus relaciones, responsabilidades y colaboración. Las consecuencias son el resultado de aplicar un patrón. Estas incluyen su impacto en la flexibilidad, extensibilidad, o portabilidad de un sistema. I En la actualidad, el uso de patrones de diseño se está fomentando en gran medida y prueba de ello son los múltiples artículos encontrados en la literatura, en donde se plantea la solución de problemas usando patrones de diseño, algunos de estos artíciilos se encuentran en las siguientes referencias: [FOS98] [COO98]. 2 Capítulo 1 INTRODUCCI~N 1.2 Antecedentes El grupo de Ingeniería de Software del Centro Nacional de Investigación y Desarrollo Tecnológico (Cenidet) trabaja con un proyecto llamado “Sistema de administración de componentes de software bisado en frameworks”, en este proyecto se propone un modelo de referencia del ciclo de ?ida de componentes reusables, así como la construcción de sistemas automatizados, visuales e interactivos que den soporte al modelo de referencia. La relevancia de este proyecto radica en la novedad del tema de investigación y por el impacto económico que puede traer en las compañías desarrolladoras de software, al contar con herramientas de administración I$e componentes de reuso que le permitan madurar sus propios dominios de aplicaciones [SAN99]. El Sistema para identificación de patrones de diseño en código C++ [CAS991 es un subproyecto que forma parte de este proyecto. 1.2.1 Sistema para identificación de patrones Ide diseño en código C+t (IPADICH) [CAS991 Se trata de un tema de tesis desarrollado en el Cenidet, dentro del cual se elaboró una herramienta (IPADIC++) que tiene la finalidad de detectar patrones de diseño en código fuente escrito en lenguaje C++; detecta los patrones: composite, iterator y abstract factory. Esto lo realiza mediante la representacion del código fuente en forma canónica para generar un modelo canónico, posteriormente realiza un mapeo entre éste y los patrones de diseño de Gamma representados con el mismo modelo canónico, de manera que se puede deducir si el código cuenta en su diseño con alguno de estos tres patrones, o si es parecido a algún patrón de diseño conocido. La herramienta consta de dos módulos que son: módulo para transformación de código C++ y’módulo de reconocimiento de patrones. El primero transforma el código escrito en lenguaje C++ a una forma canónica. El módulo de reconocimiento toma como entrada la salida del módulo anterior, realiza un análisis de la forma canónica para detectar si encontró algún patrónde diseño. IPADICW es una herramienta que busca un mayor factor de reuso de código orientado a objetos, extendiendo el tiempo de vida .útil’ de programas y controlando SU evolución; utilizando patrones de diseño como plantillas que guían el proceso de mejora continua de la arquitectura de estos programas. 1’ La desventaja principal es que no considera toda la sintaxis del lenguaje C++; por lo que el código de entrada debe tener la estructura sintáctica que reconoce la herramienta y no otra estructura bien formada, de acuerdo a las!reglas gramaticales del lenguaje C++. 1.3 Descripción del problema El problema encontrado en el iPN)IC+i es que no considera toda la sintaxis del leguaje C++ y solo mapea 3 patrones de diseño aei catálogo de Gamma et.al.[GAM95], ya que en el desarrollo de IPADIC++ se consideró solo la gramática parcial necesaria para poder implementar estos patrones. Esta restricción afecta al alcance del objetivo propuesto. 3 Capítulo 1 INTRODUCCI~N 1.4 Propuesta de solución La meta principal de este trabajo de tesis es contribuir en la solución del problema mencionado anteriormente, a través de lo siguiente: Se propone la implementación completa de la gramática del lenguaje C++ bajo el estándar ANSI-IS0 en el sistema, así como incluir dentro de la descripción de los patrones de diseño su intención que conlleva la implementación del mismo, para distinguir la parte racional detrás de los patrones que así lo requieran, tal como el strategy y state que tienen la misma estructura, pero los diferencia su intención. 1.5 Objetivos 1.5.1 Objetivo general Validar la hipótesis: “Esposible la identzjkación automática de patrones de diseño en código fuente de la sintaxis completa del lenguaje C++, a través de la implementacion de un modelo de representación canónica tanto de patrones de diseño como de código fuente a analizar”. 1.5.2 Objetivos específicos I. Construcción de un sistema que permita identificar en un código fuente escrito en C++, 6 patrones de diseño. 2. Implementar la totalidad de la gramática del lenguaje C++ en el IPADIC++ 3. Reconocer al menos 3 patrones de diseño adicionales a los propuestos en el IPADIC++, que son:factory method, strategy y template method. 4. Incluir dentro del reconocimiento de patrones de diseño de Gamma la identificación de la parte racional detrás del patrón. 5. Que esta tesis sea el punto de partida para investigaciones futuras en el área de patrones de diseño y reuso de software, dentro del Grupo de Ingeniería de Software del cenidet. 1.6 Metodología La metodología adoptada para abordar el problema planteado es la siguiente: I . Análisis de la estructura e intención de los patrones de diseño a implementar para poder determinar la forma canónica que permita la representación del patrón de diseño. Está forma canónica será realizada mediante el uso de la teoría de las gramáticas libres de contexto. 4 Capítulo 1 INTRODUCCI~N 2. Análisis de la estructura y diseño del IPADICtt-. 3. Análisis e implementación de la gramática completa del lenguaje C+t dentro del sistema, para poder transformar cualquier tipo de código escrito en lenguaje C++ bajo el estándar ANSI-IS0 a la forma canónica, basándose en el paradigma de la programación orientada a objetos, relaciones entre clases, teoría de autómatas y compiladores, así como del lenguaje de programación Java y C++; además, de las características y funcionalidad de los patrones de diseño que intervienen en la tesis. 4. Diseño e implementación de un módulo de reconocimiento para los patrones de diseño. En este módulo se hace uso de un generador de analizadores sintácticos (parsers) JavaCC (se da una descripción de esta herramienta en el capítulo 3), así como del lenguaje de programación Java y las formas canónicas de los patrones de diseño involucrados en este proyecto de tesis. 5. Se utiliza para la codificación de la herramienta el lenguaje de programación Java, ya que proporciona la ventaja de ser independiente de la plataforma de hardware y sistema operativo utilizado para ejecutar el sistema. 1.7 Beneficios Proporcionar un avance al conocimiento formal de los patrones de diseño. Obtener un sistema IPADIC++ más completo, que tenga la posibilidad de reconocer un patrón de diseño en cualquier forma que pueda presentarse el código en C++, debido a que tendrá implementada toda la gramática del lenguaje correspondiente. 1.8 Alcances y limitaciones El proyecto de tesis abarca lo siguiente: Pruebas de la estructura canónica de los tres patrones de diseño que fueron implementados en el IPADIC++ (abstract Factory, Composite, e Zterator). Se forma la estructura canónica de otros tres patrones de diseño (factory method, Strategy y Template method). Implementación del reconocimiento de los patrones de diseño strategy y template method, el patrón de diseñofactory method por razones de tiempo no se implementó en la herramienta. Implementación de la gramática completa del lenguaje C++ en el módulo de transformación del código fuente, a su correspondiente forma canónica. Desarrollo e implementación del módulo de reconocimiento de los patrones de diseño involucrados. Análisis de código en lenguaje C++. Las clases pertenecientes al código analizado pueden estar en uno o en varios archivos, con la restricción de que al presentarse en el mismo archivo deben estar tanto la declaración como la impiementación de la clase. 5 Capítulo 1 INTRODUCCI~N 1.9 Organización del documento La documentación del desarrollo de este trabajo de^ tesis esta organizado de la siguiente manera: En el capítulo 2 se'describe el estado del arte en tomo al trabajo de tesis, se mencionan y analizan los trabajos relacionados, además se hace una comparación entre tales trabajos y la investigación a desarrollar para observar ventajas y desventajas. En el capítulo 3 se mencionan y explican aquellos fundamentos teóricos que sustentan este trabajo de tesis. En el capítulo 4 se describe la arquitectura del sistema, así como el funcionamiento del mismo. En el'capítulo 5 se da. una descripción de la forma en la que se llevó a cabo la evaluación experimental de la herramienta. En el capítulo 6 se describen las conclusiones observadas al evaluar la herramienta, así como las posibles mejoras y trabajos que se le pueden realizar en el futuro. 6 Capítulo 2 ESTADO DEL ARTE Capítulo 2 . / ESTADO DEL ARTE En este capítulo se presenta el estado del arte actual en tomo a la investigación de los patrones de diseño y se describen diferentes investigaciones en las que se incluyen herramientas que implementan métodos para poder realizar el reconocimiento de patrones de diseño en programas escritos en algún lenguaje de programación y se mencionan las ventajas y desventajas de cada una de estas herramientas. 7 Capitulo 2 ESTADO DEL ARTE 2.1 Introducción Uno de los tópicos más recientes dentro de la ingeniería de software es el término patrones de diseño. De los trabajos relacionados a este tema se tienen varios enfoques, entre los que hay dos direcciones principales; una de ellas se enfoca a la implementación de patrones de diseño en el desarrollo de aplicaciones de software, ya sea incluyendo los patrones de diseño como parte de los lenguajes de programación o implementados como parte del diseño de la aplicación. Por otra parte, la investigación de la reingeniería acerca de patrones de diseño, se enfoca a dos áreas: una de ellas se refiere a la identificación de patrones en códigos existentes y la otra es aplicar métodos de refactorización para incluir patrones en los sistemas, con el fin de poder obtener componentes reusables de estos sistemas y poder incluirlos en frameworks o marcos de aplicaciones, orientados a objetos donde se puedan controlar, evolucionar y administrar estos componentes. 2.2 Investigación de patrones de diseño implementados en el desarrollo de software Dentro de este enfoque existen varias investigaciones, como los trabajos desarrollados por F.J. Budinsky et. al. [BUD961 quienes desarrollaron una herramienta que automatiza la implementación de patrones de diseño; esto es realizado al proporcionarle al sistema algunas piezas de información, nombres de aplicación específicos para los participantes en un patrón, se crea la declaración y definiciones de clases que implementan el patrón; posteriormente, el usuario tiene que adicionar este código al resto de la aplicación. Otra investigación esta enfocada a la inclusión de patrones de diseño como lenguaje de construcción, donde Jan Bosh de la Universidad de Kariskrona I Ronneby [BOS98] presenta un modelo de objeto'en capas, que provee un lenguaje de soporte para la representación explícita de los patrones de diseño en el lenguaje~deprogramación. En otro enfoque, se utilizan los patrones de diseño ya existentes para .solucionar nuevos problemas, como describen Ted Foster y Hiping Zhao [FOS98] en el modelado de un sistema de transportes, donde utilizan patrones de diseño que proveen un formalismo para capturar componentes concurrentes, frecuentemente dentro de los modelos de transportes público. En un estudio muy particular, Baumgartner, Laufer y Russo [CHAOO] analizaron patrones de diseño desde muchas fuentes, e identificaron pocas Características clave que podnan adici0narse.a C++ para hacer los patrones de diseño más fáciles de expresar (interesantemente) todas estas características del lenguaje están presentes en algunos lenguajes. Otras investigaciones han analizado patrones de diseño y han propuesto más clases especializadas de características de lenguaje, con el fin de soportar más limitados subconjuntos de patrones. 8 Capítulo 2 ESTADO DEL ARTE 2.3 Investigación de patrones de diseño en la reingeniería Dentro de este enfoque se trata la recuperación de los patrones de diseño en sistemas de software existentes, esto es con el fin de obtener un mejor entendimiento de los sistemas y poder hacer de ellos una base de componentes que tengan las características necesarias para que puedan ser reusados. Así tenemos diferentes investigaciones que se describen a continuación: 2.3.1 Un método inductivo para descubrir patrones de diseño desde sistemas de software orientados a objetos [SHU96] En este artículo se presenta un método inductivo’ (no automático) que ayuda a descubrir patrones de diseño en sistemas de software orientados a objetos. Proporciona un conjunto de procedimientos definidos rigurosamente para que puedan ser repetibles y utilizables por personas que no están familiarizadas con procesos de ingeniería inversa. El método propuesto aquí se denomina BACKDOOR (Backwards Architecture Concerned with Knowledge Discovery of O 0 Relationships). La principal salida del proceso al aplicar el método, es una base de conocimientos que describe que patrones han sido usados a la fecha por una organización. Una vez que se han identificado los patrones potenciales, son revisados por los desarrolladores para ver si cxiste algún significado en el conjunto de clases identificadas. Este método consta de 6 pasos secuenciales e iterativos: 1. Revisión de la documentación de la especificación del problema v el diseño. Se estudia la especificación del problema para identificar restricciones y tópicos del problema, así como para obtener ideas de la funcionalidad proporcionada. 2. Desarrollo de un modelo preliminar del sistema desde la declaración de clases. Aquí se descubre como interacttían las clases (se revisa la declaración de las mismas); se detectan relaciones como herencia, comunicación entre clases, etc. 3. Refinar la notación de objetos desde la implementación de las clases. Se da una mirada detallada al código de implementación de las clases, es decir, se revisa minuciosamente la implementación de las clases para tratar de identificar relaciones entre las mismas. 4. Utilizando el modelo refinado de la arquitectura del sistema, identificar candidatos potenciales a patrones basados en herencia y lipas de comunicación entre clases. Este paso se enfoca a relaciones interesantes en las arquitecturas, buscando similaridades estructurales recurrentes. Relaciones como: clases “mediador”, “interfaz a otras clases”, “herencia paralela”, “liga entre dos subsistemas”. 5 . Analizar los candidatos a patrones detectados en el paso 4. Aquí se hace una comparación de los patrones potenciales identificados en el paso 4 contra los patrones del conjunto de referencia. El conjunto de referencia al principio está compuesto Únicamente por los patrones de diseño descritos por Erich Gamma en su libro, pero si después se detectan patrones de diseño nuevos, estos se agregan al conjunto de patrones de referencia. 6 . Intervención de diseñadores e implementadores para aclarar problemas de diseño. En este paso se tienen entrevistas con los diseñadores y codificadores responsables para un ’ Se le denomina inductivo, ya que primero localiza patrones de diseño potenciales, posteriormente realiza una comparación de ellos con los patrones de diseño existentes con la finalidad de hacer una mejor detección, además si encuentra patrones nuevos, los anexa al conjunto de patrones de referencia. 9 Capítulo 2 ESTADO DEL ARTE mejor entendimiento del sistema. La información recabada en este paso se espera que sirva para retomar a los pasos 4 o 5 para,una'iteración más detallada. Su principal desventaja es que se trata de un método manual, por lo tanto requiere de mucha intervención por parte del usuario. 2.3.2 Recuperación de diseño mediante búsqueda automática de patrones de diseño estructurales en software orientado a objetos [KRA96] En este artículo se muestra'una herramienta denominada PAT (Program Análisis Tool), en esta se extrae información de diseño directamente de los archivos de cabecera de C++ y se almacenan en un repositorio. Los patrones son expresados como reglas Prolog y la información de diseño es también trasladada; una simple consulta de Prolog es usada para la búsqueda de todos los patrones. En esta herramienta únicamente se reconocen instancias de algunos patrones de diseño estructurales mencionados por Erich Gamma [GAM95], los cuales son: adapter, Bridge, Comporite, Decorator y Proxy. Los pasos que sigue PAT para la búsqueda de patrones de diseño son: 1. Cada patrón es representado como un diagrama OMT estático, estos diagramas constituyen el repositorio P (de patrones). 2. Un programa es usado para convertir P en una regla de Prolog para cada patrón de diseño. 3. Se utiliza la herramienta ooCASE para realizar el mecanismo de análisis estructural ooCASE extrae información de diseño de los archivos de cabecera de C++ y la representa en el repositorio en la notación OMT. La parte resultante del repositorio es llamada D (de diseño). La información relevante que es extraída de los archivos de cabecera de C++ es: nombre de clases, nombre de atributos, nombre de métodos, relaciones de herencia y relaciones de agregación y asociación. 4. Otro programa de este sistema es usado para convertir D en la representación Prolog. 5. Una consulta Q de Prolog detecta todas las instancias de patrones de diseño de P en el diseño D examinado. La desventaja de PAT es que detecta únicamente patrones de diseño estructurales y no detecta patrones de creación y de comportamiento. 2.3.3 Ingeniería inversa de diseño y detección automatica de patrones de diseño en Smalltalk [BR097] En este artículo Kyle Brown describe el desarrollo de su tesis de maestría, en la que demuestra la viabilidad de desarrollo de programas para detectar el uso de patrones de diseño de software en programas realizados en lenguaje Smalltalk. Para este fin examina la estructura de los patrones de diseño, determina la naturaleza de lo que hace que un patrón de diseño se detecte por medios automatizados y bosqueja algoritmos por medio de los cuales un pequeño conjunto de patrones de diseño pueden ser detectados. 10 Capítulo 2 ESTADO DEL ARTE Esta tesis documenta el desarrollo de una herramienta de software (KT) la cual recupera información de diseño desde código Smalltalk, y la usa para detectar algunos patrones de diseño como son: composite, Decorator, y Template Method. Además muestra el diagrama de clases del código analizado, utilizando la herramienta CASE Rational ROSE. Para hacer esto, toma la información de diseño recuperada del código, después genera un archivo en el mismo formato que los archivos de diseño generados por Rational ROSE. La desventaja de esta herramienta es que no identifica patrones de creación. 2.3.4 Identificación automática de patrones de diseño [BAN981 En este artículo se presenta una herramienta (DP++) que automatiza la detección, identificación y clasificación de patrones de diseño en programas C++. DP++ actualmente identifica algunos de los patrones estructurales y algunos de los patrones de comportamiento (Behavioral) descritos por Erich Gamma et.al. [GAM95]. Esta herramienta se basa en las relaciones estructurales entre las clases y objetos, para identificar usos de patrones de diseño en programas orientados a objetos; relaciones estructurales como: clases abstractas, clases base y subclases, plantillas de clases (template classes), relaciones de herencia, agregación por contención física de variables de instancia y agregación por referenciaíapuntador a variables de instancia. Esta herramienta utiliza un algoritmo de reconocimiento para cada patrón de diseño reconocido en ella. Además despliega una ventana con el modelo de clases de la estructura del programa y una ventana con una vista de árbol que despliega la jerarquía de clases del proyecto. La principal desventaja de esta herramienta, es que no detecta patrones de diseño de creación (creational patterns). 2.3.5 Comprensión de frameworks y patrones de diseño: un enfoque de ingeniería inversa [CAM971 Se trata de una investigación basada sobre el framework Luthier, para desarrollar herramientas para aplicación de análisis y visualización por el significado de técnicas de reflexión basadas sobre meta-objetos. Luthier provee soporte flexible para proporcionar herramientas de visualización adaptables para diferentes funcionalidades de análisis, usando un manejador de hiperdocumento para organizar la información. Una vez que una o muchas aplicaciones son desarrolladas en un framework dado, son analizadas, se reúne una representación prolog de dato y es usada para reconocer potenciales patrones de diseño que pueden existir en el diseño del framework. Prolog es usado para representar las reglas de reconocimiento de patrones de diseño, para desarrollar las visualizaciones de patrones potenciales y para generar explicaciones acerca de estos patrones y las razones que sugieren su presencia en el diseño. Reconoce patrones como el composite, decorator, proxy, state y strategy. Para probar la efectividad de la investigación y la herramienta, un experimento sobre utilización delframework se llevó a cabo. El experimento no precisamente demostró ESTADO DEL ARTE Capítulo 2 el nivel de eficiencia del enfoque dc comprensión delfrurnework ni de las herramientas de desarrollo para soportarlo, pero dan una buena idea de sus ventajas y limitaciones. Su principal desventaja es que no reconoce patrones de creación y no demuestra una buena eficiencia de la herramienta. 2.3.6 Ingeniería inversa de componentes de diseño basada en patrones [KEL99] Es una investigación con enfoque principal a la recuperación de información referente a lo racional detrás de las decisiones del diseño de grandes sistemas de software. Aquí se presenta un medio ambiente para la ingeniería inversa de componentes de diseño basado en las descripciones estructurales de patrones de diseño. El medio ambiente consiste del siguiente conjunto de técnicas y herramientas: 1. Capturar código fuente. El propósito es extraer un modelo inicial del código fuente existente que esta escrito en C++. Se genera una representación basada en ASCII de los elementos relevantes de código. Se adopta el formato transferido CDIF como la sintaxis y el metamodelo UML así c o h o el modelo semántico. 2. Repositorio de diseño. Su propósito es proveer un almacenamiento centralizado, manipulación y consulta de los modelos de código fuente. El esquema del repositorio de diseño es basado sobre el metamodelo UML extendido. El sistema administrador de base de datos orientado a objetos Poet 5.1 sirve como repositorio. 3. Recuperación de diseño basada en pufrones. El propósito es ayudar a estructurar partes de diagramas de clases para reensamblar diagramas de patrones. Hay 3 técnicas para soportar esta tarea: Recuperación automática. . Recuperación manual. Recuneración semi-automática. La recuperación automática, relaciona a la estructura automatizada completa de diseños de software acorde a la descripción de patrones, los cuales son almacenados en el repositorio como componentes abstractos de diseño. 4. Representación de diseño. Su propósi.to es proveer la visualización interactiva y refinamiento de modelos de código fuente, componentes de diseño abstracto y componentes implementados. Se aplicaron pruebas sobre 3 sistemas industriales, de los que 'se seleccionaron los componentes de diseño abstracto que están basados en la descripción de los patrones de diseño templute method, fuctov method y bridge. De las pruebas aplicadas al medio ambiente se concluye que como las estructuras del template method y factory method reflejan en su estructura la intención del patrón respectivo se puede contar con que la recuperación en los componentes de diseño de: ambos patrones es correcta, mientras que para el patrón bridge requiere de juicio humano, ya que se trata de un patrón que puede ser implementado en muchas diferentes maneras. ' ' Su principal desventaja es que depende de varias herramientas para ejecutarse. 12 Capítulo 2 ESTADO DEL ARTE 2.4 Conclusiones La mayor parte de las herramientas descritas anteriormente solo consideran algunos de los patrones de diseño de Gamma, principalmente de comportamiento o estructurales y solo algunos de creación, lo que podria deberse,a que aún no se ha podido encontrar un método adecuado para identificar patrones de diseño que tienen estructura idéntica, además difieren en la intención que conlleva el uso de tal patrón. Por otra parte, también se encuentra que existe dentro de la identificación de patrones de diseño en código fuente, otra dificultad que se relaciona con la manera de programar, de los desarrolladores de software, ya que existen dentro de los códigos implementaciones iguales con diferente estructura sintáctica [FUC90]. Además, la mayoría de las herramientas descritas anteriormente son dependientes de la plataforma de hardware y sistemas operativos,'ya que no se desarrollaron en un lenguaje de programación independiente de la plataforma como Java. El.IPADIC++ se desarrolló en lenguaje Java, lo que le permite poder ejecutarse en prácticamente cualquier plataforma y sistema operativo que soporte Java, la desventaja de IPADIC++ es que no implementa la gramática completa del lenguaje C++, por lo que no reconoce patrones de diseño que no estén implementados con la estructura sintáctica parcial que reconoce en sus módulos. 13 Capítulo 3 MARCO TEÓRICO Capítulo 3 MARC~OTEÓRICO En este capítulo se describen las bases teóricas que dan fundamento al desarrollo de está investigación, tratando aspectos como: desairollo de software basado en componentes, el modelo orientado a objetos, lenguajes de patrones, patrones de diseño, gramáticas libres de contexto, gramáticas regulares y la herramienta para generación de analizadores léxicos y sintácticos (parsers) JavaCC. 14 Capítulo 3 MARCO TEÓNCO 3.1 Introducción En el contexto del desarrollo de esta tesis se encuentran algunos fundamentos teóricos, de los cuales es importante indicar su relación con este trabajo ‘de investigación, asi como describirlos brevemente. Este tema de investigación se encuentra inmerso en el área de Ingenieria de Software, en la línea de investigación de desarrollo de sofhvare basado en.componentes, dentro de la cual la investigación relacionada con los patrones de diseño ayuda en cierta forma, a determinar si un software cumple con. las características para ser reusable y ser incorporado a una base ‘decomponentes. El contexto de relación del modelo de desarrollo orientado a objetos con esta tesis, es que los patrones de diseño emergen del modelo de desarrollo orientado a objetos, por lo tanto es necesario dar una descripción de este modelo. Además de que el IPADIC++ analiza código escrito en lenguaje C++ el cual obedece al paradigma orientado a objetos. Asimismo, el lenguaje Java utilizado para la codificación de la herramienta esta basado en el modelo de desarrollo orientado a objetos. Este trabajo realiza la detección de patrones de diseño, a partir del análisis de código fuente, por lo que es necesario comprender y analizar los patrones de diseño y su relación con los lenguajes depatrones. La relación de las gramúticas con el tema de tesis se presenta porque, el modelo canónico de representación de patrones de diseño formulado en este proyecto, consta de una gramútica libre de contexto dado el tipo de reglas, que :posee. Por otra parte, para especificar la sintaxis en la gramática del lenguaje C++ se~implementauna gramática regular. Para la generación de los analizadores utilizados por los módulos implementados, se utilizó la herramienta Javacc para la generación de analizadores léxicos y sintácticos, por lo que se da una breve descripción del funcionamiento de esta he&amienta. 3.2 Desarrollo de software basado en componentes (CBD) Hace treinta años que empezamos a oír acerca de la crisis del software, la cual se inicio a medida que los sistemas de software evolucionaron pasando de la etapa en que el software se diseñaba a la medida de cada aplicación y tenía una distribución relativamente pequeña. La segunda etapa se caracterizó por la multiprogramación, los sistemas multiusuario y la introducción de nuevas formas de interacción hombre-máquina, en esta etapa el software se desarrollaba para distribuirlo ampliamente; conforme crecía el número de sistemas de software se extendieron las bibliotecas de computadora, los productos de software incorporaban cientos de miles de sentencias en las que se presento la necesidad de realizar actividades de “mantenimiento de software”, estas actividades comenzaron a absorber recursos de manera alarmante y la naturaleza personalizada de la mayona de los programas los hacía imposibles de mantener, lo que dio origen a la crisis del software. La cual se ha traducido en la insatisfacción a la demanda de aplicaciones informáticas. Si bien Capítulo 3 MARCO TEÓRICO es cierto que la capacidad computacional tanto en hardware como en software ha tenido un fuerte desarrollo en los últimos años, no se puede negar que también la demanda de sistemas de información se caracteriza por sistemas cada vez mas intolerantes a fallas y de mayor complejidad. Para agregar madurez al proceso de desarrollo de sistemas, una meta actual de investigación en ingeniería de software es la de otorgar,,facilidadesen los procesos por 'medio de la adopción de herramientas automatizada: para construir, entender, mantener y documentar el software, conduciendo a una mejor calidad y confiabilidad, así como una mayor satisfacción del cliente [AHR95]. El desarrollo de software se está moviendo rápidamente de una forma artesanal hacia el proceso de ingeniería y manufactura .a gran escala. Un movimiento hacia componentes de software está siendo manejado, por la urgente necesidad de contar con artefactos de software reusable que cuenten con una mejor calidad y que puedan ser configurados en diferentes aplicaciones; para satisfacer las necesidades de cambio con un mínimo de inversión en costo y esfuerzo [TH095]. Los primeros componentes fueron llamados circuitos integrados de software, los cuales aparecieron como paquetes sellados con un conjunto especifico de entradas y salidas, a estos componentes se les conoce como mensajes, interfaces de aplicaciones (API's) y protocolos [TH095]. Durante muchos años se ha visto al desarrollo de software basado en componentes como una de las técnicas más promisorias para enfrentar la crisis del software. Sin embargo, hasta hoy no se ha logrado establecer en su totalidad que la producción de sistemas se haga bajo una política de empleo de componentes, como un modelo de ingeniería. La comunidad científica de ingeniería de software ha propuesto varios paradigmas de programación para aliviar en parte este problema, con los cuales se gana un cierto nivel de reuso. Con el paradigma de programación procedural se permite a los programadores, ejecutar segmentos de código organizados en librerías de funciones más de una vez, sin tener que duplicar el código en cada localidad física donde es necesario. También se pueden insertar subrutinas extraídas de otros programas desarrollados previamente. El paradigma de programación modular habilita el desarrollo de programas por piezas de código independientes. Los elementos de reuso ahora son los módulos y/o módulos compuestos que logran una mayor funcionalidad, "para dar satisfacción a los requerimientos de nuevas aplicaciones. El modelo de programación orientado a objetos tienda tecnología con el potencial de incrementar el reuso de componentes de software, al nivel de objetos, porque con orientado a objetos existe un plan, denominado clase o plantilla, para la creación de objetos, el cuál empaqueta las estructuras de datos (estado) con las funciones (comportamiento) relacionadas a éstas e indica el espacio en memoria necesario para almacenar el estado y sus valores iniciales, y se facilita un mecanismo para la construcción de las instancias. El elemento clave en este modelo es la habilidad que proporcionan los lenguajes que soportan este paradigma para facilitar la reutilización de bibliotecas de clases. . 16 Capítulo 3 MARCO TEÓFUCO En la actualidad, el desarrollo de sistemas basado en componentes (CBD), representa el paradigma de construcción de software.mas ampliamente aceptado y el de más duración que sus predecesores. Este paradigma, va a ''desplazar a los arquetipos anteriores de programación, ya que se considera el enfoque más prometedor para obtener beneficios significativos en lo que se refiere a productividad y reusabilidad. CBD ofrece una oportunidad para construir arquitecturas que perdurarán hasta el siguiente siglo y promete formas o maneras para evolucionar soluciones en la fase de cambios de requerimientos de aplicaciones[SPI97]. El estado del arte de CBD indica dos direcciones, una apunta hacia el desarrollo y uso de frameworks, los cuales definen a los objetos de reuso de dominios configurados mediante un modelo orientado a objetos, la otra dirección va hacia la definición de componentes de anaquel (COTS) que utilizan un modelo de infraestructura común. Un framework es 'un conjunto semi-completo de clases en colaboración que incorpora un diseño genérico el cual puede ser adaptado a una variedad de problemas específicos para producir nuevas aplicaciones hechas a la medida [JOH98] y [FAY97]. Los frameworks son colecciones de estados y comportamiento, modelados como una comunidad. de clases interactuando y organizadas dentro de un número pequeño de jerarquías de herencias [TH095]. Los frameworks modelan dominios de aplicación particulares y requieren de un entendimiento profundo de programación y diseño orientado a objetos. Los arquitectos definen la esencia del framework'usualmente en la forma de clases abstractas y los diseñadores lo implementan proporcichando clases concretas que realizan el comportamiento. Un buen framework requiere de un gran conocimiento del dominio y experiencia en el desarrollo de frameworks. Las personas encargadas del mantenimiento (extendedores), mejoran un framework que está siendo utilizado por una familia específica de aplicaciones, lo cual permite especializarlo y extenderlo sin la tradicional re-programación asociada. Los frameworks pueden ser empacados como cajas negras, blancas o grises. Las cajas negras son completamente cerradas a las modificaciones y/o extensiones, mientras que las cajas blancas son totalmente vulnerables ya que permiten libre acceso a los detalles de implantación y a las estructuras. Las cajas grises son las más deseables porque ocultan los detalles de implantación y/o los algoritmos propietarios y, la estructura que pudieran impactar en la evolución delframework o su portabilidad. Los artefactos de reuso de este paradigma lo representan las diferentes configuraciones o comunidades de clases interactuando .y organizadas en jerarquías de herencia denominados frameworks. Por otro .I ladg; trabajos recientes presentan a los patrones como un método promisorio para describir a la estructura interna y el comportamiento de frameworks, desafortunadamente la mayoría de métodos de análisis y diseño orientados a objetos ignoran a los frameworks y asumen que todas las aplicaciones se construyen de manera rudimentaria. En esta dirección, la tendencia hacia el reuso de componentes de software se propone a través de arquitecturas basadas en patrones de diseño, librerías de clases y frameworks. AI futuro se vislumbra que este enfoque influenciará grandemente el desarrollo de software [WAT97]. .&. Los componentes de tipo COTS son cajas negras, ensambladas y conectadas de acuerdo al principio de ocultación de datos. Por razones de mantenimiento y comerciales, I 17 Capítulo 3 MARCO TEÓRICO estos componentes se empacan en formato de solo ejecución y, tal vez, con algo de código fuente como documentación [TH095]. Aunque muchos componentes son implementados como objetos, un componente no tiene que ser un objeto. Un componente solo necesita empacar la hncionalidad de programas de tal forma que las capacidades del componente sean visibles por el contenedor durante el ensamble y en tiempo de ejecución. Por otro lado, está siendo muy común empacar aplicaciones legadas completas en arreglos de componentes para ampliar el acceso a los datos que ellos manejan [SPI97]. La producción de software basado en componentes, implica problemas que aún son temas de investigación [MIL95], tales como: la carencia de herramientas adecuadas y/o suficientes para apoyar todo el ciclo de vida del software, la carencia de personal calificado para desarrollar componentes y la carencia de políticas en las organizaciones para construir aplicaciones bajo este enfoque. Por lo que, moverse desde la actual práctica de desarrollo de software dominada por grandes y complejas aplicaciones”legadas, con un cúmulo de peticiones de desarrollo y mantenimiento por atender, hacia una generación de desarrollo de software basada en componentes y programación automática, ha probado mucha dificultad [AHR95]. Sin embargo, ya existen algunas tecnologías que pueden ayudar, tales como: el Análisis e ingeniería de dominios, herramientas CASE, métodos de análisis, diseño y programación orientada a objetos, patrones de diseño y frameworks, nuevos modelos de arquitecturas, ambientes de administración de componentes, etc. La evolución de los modelos del ciclo de vida del software ha sido constante, transitando desde los tradicionales modelos de cascada a los modelos más modernos como el de prototipos rápidos, implementados con interfaces interactivas que permiten producir software al nivel de prototipo de manera inmediata hasta lograr la satisfacción’de los requerimientos del cliente o del usuario final. Una tendencia tecnológica actual es la definición de nuevos modelos del ciclo de vida del software, sobre los cuales se construyan ambientes de desarrollo que incluyan herramientas automáticas o semiautomáticas, visuales e interactivas, que cubran tanto el desarrollo de componentes como la construcción de sistemas basándose en el uso de éstos. Margaret Burnett [BUR951 ha propuesto que los nuevos modelos de desarrollo de software contemplen al menos cuatro etapas: mecanismos para la clasificación y recuperación de componentes, mecanismos para el encapsulado de nuevos componentes, mecanismos para la integración de componentes y mecanismos para la ejercitación de componentes. 3.3 Modelo orientado a objetos El modelo orientado a objetos es una filosofía para diseñar e implementar sistemas de software, que permite una representación más directa del modelo del mundo real en el código. Este modelo se soporta en cuatro propiedades básicas: “abstracción de datos ”, “ocultación de datos ”, “herencia y ‘)olimorfismo” y en cinco componentes: “clases“, “objetos’’, “métodos”, “mensajes” e “instancias ”: ” Abstracción de datos. Es un modelo de software que empaqueta una estructura de datos junto con un conjunto de operaciones asociadas a ésta, y es la propiedad que habilita el ocultamiento y encapsulado de datos. La abstracción de datos es representada por la 18 Capítulo 3 MARCO TEÓRICO “descripción del protocolo .de la clase”, este protócolo define las propiedades de cualquier objeto que sea instancia de la clase. Ocultación de datos. La implantación interna. de los objetos que dan los detalles de su funcionamiento, debe estar protegida. Es decir, los datos ocultos del objeto Únicamente I deben ser accesibles por los métodos propios del objeto. 81 Herencia. Es una propiedad clave en la programación orientada a objetos. Una subclase Y hereda todos los atributos y operaciones asociadas con su superclase X. Esto significa que todas las estructuras de datos y algoritmos originalmente diseñados e implementados para X están inmediatamente disponibles para Y . Cualquier cambio en los datos u operaciones contenidas dentro de una superclase se heredarán inmediatamente por todas las subclases que se derivan de la superclase [PRE98]. Polimorfismo. Propiedad del comportamiento que tienen los objetos de responder de diferente manera a mensajes recibidos. El polimorfismo se implementa a través de la sobrecarga de funciones y/o operadores y la forma se asocia en tiempo de ejecución. Clases. Es un concepto orientado a objetos que encapsula las abstracciones de datos y procedimientos que se requieren para describir el contenido y comportamiento de alguna entidad del mundo real [PRE98]. La clase, define lalplantilla o el protocolo para la creación de objetos semejantes, y al .mismo tiempo conceptúa una entidad. Objetos. El objeto encapsula datos (los valores de los atributos que definen el objeto), operaciones (acciones que se aplican para cambiar los atributos del objeto), otros objetos (pueden definirse objetos compuestos), constantes (fijar valores) y otra información relacionada [PRE98]. Métodos. Cada una de las operaciones encapsuladas por un objeto proporciona una representación de uno de los comportamientos del objeto [PRE98]. Mensajes. Los mensajes son el.medio a través del cual los objetos interactúan. Un mensaje estimula la ocurrencia de cierto comportamiento en el objeto receptor [PRE98]. Instancias. Un objeto es una instancia de una clase. Una vez.definida la clase, los atributos pueden reusarse al crear nuevas instancias de la clase. Todas las operaciones válidas de la clase están conectadas a la definición del objeto y son heredadas por todas las instancias de esta clase. Este modelo apoya directamente el reuso de software, ya que proporciona mecanismos que permiten adaptar un componente de código a nuevos usos o aplicaciones sin modificar su definición actual. Las estructuras de programas orientados a objetos se organizan en clases taxonómicas. A mayor nivel en la jerarquía corresponde una mayor generalidad, a menor 19 Capítulo 3 MARCO TEÓRICO nivel en la jerarquía se incrementa la particularidad de las clases. Este es el mecanismo que proporciona el medio para hacer programación por incrementos, puesto que a mayor jerarquía las clases pueden ser reusadas en más aplicaciones diferentes, extendiendo su funcionalidad mediante clases más específicas. El elemento clave del modelo de programación orientada a objetos es la habilidad que proporcionan los lenguajes que soportan este paradigma para facilitar el uso de librerías de componentes reusables. Varios avances en la Ingeniería de Software hicieron más viable la reusabilidad de software, la programación orientada a objetos (POO) permitió la construcción de sistemas más generales, donde muchas partes del código puedan ser aplicadas a múltiples sistemas. 3.4 Lenguajes de patrones Patrones para el desarrollo de software es uno de los tópicos más nuevos que emergen de la comunidad de desarrollo de tecnologías orientadas a objetos. La meta de patrones dentro de la comunidad de software es la creación de un cuerpo de literatura que ayude a los desarrolladores de software a . resolver problemas difíciles comunes, encontrados a través de todo el ciclo de desarrollo de software.’Los patrones ayudan a crear un lenguaje compartido para comunicar conocimientos y eiperiencias acerca de estos problemas, así como de sus soluciones. Codificando formalmente estas soluciones y sus relaciones, deja capturar exitosamente el cuerpo de conocimiento que comprende nuestro entendimiento de buenas arquitecturas que conforman las necesidades de los usuarios. Cada patrón es una regla de tres partes, el cual expresa una relación entre un cierto contexto, un cierto sistema de fuerzas (el problema) que ocurre repetidamente en ese contexto y una cierta configuración de software (la solución) que permite que estas fuerzas se resuelvan por sí mismas. Los autores de “Patterns of Software Architecture” definen tres tipos de patrones: 1. Patrones de arquitecturu’. Un patrón arquitectónico expresa una estructura de organización o esquema fundamental para sistemas de software. Provee un conjunto de subsistemas predefinidos, especifica sus responsabilidades, e incluyen reglas y guías para organizar las relaciones entre ellos. 2. Patrones de diseio. Un patrón de diseño provee un esquema para refinar los subsistemas o componentes de un sistema de software, o las relaciones entre ellos. Comúnmente describe estructuras recurrentes de componentes en colaboración que resuelven un problema de diseño en general dentro de un contexto en particular. 3 . Patrones de código. Un patrón de código es un patrón d l bajo nivel, específico a un lenguaje de programación. Un patrón de código descri6e como implantar aspectos particulares de componentes o las.relaciones entre ellos, utilizando las características de un lenguaje dado. Las diferencias. entre estas tres clases de patrones esta en su correspondiente nivel de abstracción y detalle. Los patrones arquitectónicos son estrategias de alto nivel que involucran componentes a gran escala y las propiedades y mecanismos globales de un sistema. Los patrones de diseño son tácticas de nivel medio que desmenuza las estructuras y el comportamiento de entidades y sus relaciones. Estas no influencian la estructura del 20 ’ Capítulo 3 MARCO TEÓRICO sistema total, pero definen micro arquitecturas de subsistemas y componentes. Los patrones de código son técnicas de programación en lenguajes específicos que se ajustan en un nivel bajo interno o detalles externos de la estructura o comportamiento de un componente. Una colección de patrones forma un vocabulario para entender y comunicar ideas. Tal colección puede estar integrada junto a un todo cohesivo, que revela las estructuras y relaciones inherentes de sus partes constituyentes hacia el logro total de un objetivo compartido. Esto es lo que Christopher Alexander llama un lenguaje de patrones. Si un patrón es una solución recurrente a un problema en un contexto dado por algún sistema de fuerzas, entonces un lenguaje de patrones es una colección de tales soluciones, los cuales, en cada nivel de escala, trabajan juntos para resolver un problema complejo en una solución ordenada de conformidad con las metas predefinidas. La utilidad del estudio de patrones radica en que los lenguajes de patrones describen marcos ,de trabajo (fiiarnework) o familias de sistemas relacionados. 3.4.1 Patrones de diseño Un patrón de diseño nombra, abstrae, e identifica los aspectos clave de una estructura común de diseño que la hace útil para crear un diseño orientado a objetos reusable. El patrón de diseño identifica las clases participantes y sus instancias, sus funciones y colaboraciones y la distribución de sus responsabilidades. Cada patrón de diseño se enfoca a un tópico o problema de diseño orientado a objetos en particular. Describe cuando se aplica, si puede o no ser aplicado en vista de otras restricciones de diseño y las consecuencias y negociaciones de su uso. Puesto que eventualmente debemos implantar nuestro diseño, un patrón de diseño también provee el código de ejemplo para ilustrar una implantación. Aunque los patrones de diseño describen diseños orientados a objetos, ellos están basados en soluciones prácticas que han sido implantadas en un torrente de lenguajes de programación orientados a objetos. La forma ‘Alexandriana’,‘GoF’ o forma ‘canbnica’ describe un patrón de diseño: 1. Nombre, es una palabra o frase corta para referirse al patrón, el conocimiento y la estructura que describe; 2. Problema, describe su intención (INTENT), las metas y objetivos que quiere alcanzar dentro del contexto y sistema de fuerzas dado, donde con frecuencia, las fuerzas se oponen a los objetivos; 3. Contexto, describe las PRECONDICIONES bajo las cuales el problema y su solución parecen recurrir y para lo que es deseable la solución, puede pensarse como la configuración inicial del sistema antes de que sea aplicable el patrón. También nos indica la APLICABILIDAD del patrón; 4. Fuerzas, describen las restricciones relevantes y como interactúan aún en conflicto con cada una de las otras y con las metas que se desean, aquí un escenario concreto sirve como la MOTIVACIÓN para que el patrón sea utilizado; 5. Solución, representa a las reglas de relación tanto estáticas como dinámicas, que describen como obtener el resultado deseado. La descripción puede utilizar figuras y diagramas para identificar la ESTRUCTURA del patrón, sus PARTICIPANTES y sus COLABORACIONES para mostrar como se resuelve el problema. La ESTRUCTURA ESTÁTICA indica la forma y la organización del patrón, pero con frecuencia es el COMPORTAMIENTO DINÁMICO Ib’que hace que el patrón viva; ~ sep-~ ,GE. ~ ~ t i DGIT w P “--.-a-- -. 1 w, . Capítulo 3 MARCO TEÓFUCO 6 . Ejemplos, describen las POSTCONDICIONES y los efectos laterales, buenos y malos, del patrón. Esto a veces es llamado RESOLUCIÓN DE FUERZAS porque describe cuales fuerzas han sido resueltas; 7. Razonamiento, explica cómo las fuerzas y las restricciones son orquestadas para lograr una armonía resonante. Nos dice como trabaja el patrón actualmente y porque es bueno. A diferencia de la solución, el razonamiento proporciona el conocimiento de la naturaleza interna de la estructura y los mecanismos clave que están bajo la superficie del sistema; 8. Patrones relacionados, muestran las relaciones estáticas y dinámicas entre un patrón y otros dentro del mismo sistema o lenguaje de patrón. Los patrones relacionados de alguna manera comparten las fuerzas. Los patrones predecesores tienen un contexto inicial y uno resultante, que es compatible con el contexto resultante o inicial de otro patrón. El patrón sucesor sigue del patrón con un contexto inicial. El patrón alternativo, describe una solución diferente al mismo problema pero bajo diferentes fuerzas y restricciones. Los patrones co-dependientes, pueden o deben ser aplicados al mismo tiempo que otro patrón. El catálogo de Gamma et.al.[GAM95]clasifica 23 patrones de diseño de acuerdo a dos criterios, ilustrados en la tabla 3.1: Propósito se refiere a lo que hace el patrón, a) Creacionales: relacionados con el proceso de creación de objetos. b) Estructurales: trata de la composición de clases u objetos. c) De comportamiento: caracterizan la manera en la cual clases y objetos interactúan y distribuyen responsabilidades. Alcance específica si los patrones se aplican principalmente para clases o para objetos, a) Clases: relaciones entre clases y sus subclases establecidas a través de la herencia, fijadas estáticamente en tiempo de compilación. b) Objetos: relaciones entre objetos que pueden ser cambiadas en tiempo de ejecución. Comportamiento Interpreter Template method Chain of responsability Command Iterator Mediator Memento Observer State Strategy Visitor 22 MARCO TEÓRICO Capítulo 3 3.5 Gramáticas Para definir un lenguaje formal L, necesitamos dos cosas: 1) un alfabeto C de símbolos individuales y, .: . 2) un conjunto de reglas. para determinar cuales cadenas de'I símbolos del alfabeto son palabras legales del lenguaje. Usando esta definición un lenguaje no es otra cosa másique un conjunto de cadenas legales de un .alfabeto. Tomados juntos el alfabeto y las regias para formar cadenas son llamados una gramática. 4 Una gramática es un sistema formal para definir un lenguaje, así como también una herramienta para imponer a las cadenas del lenguaje una estdctura Útil. Es el conjunto de reglas por las cuales son construidas expresiones válidas d& algún lenguaje. Todos los lenguajes de programación tienen reglas que describen la estruCtura sintáctica de programas bien formados [HOP93]. Formalmente una gramática se define por (V, T, P, S), donde: ;! V: Es un conjunto finito de símbolos no terminales. T: Es un conjunto de símbolos terminales. P: Es un conjunto finito de producciones, las cuales tienen la forma A j a , donde A es un símbolo y oc es una cadena de símbolos de (VuT)*. S: Es una variable la cual contiene el símbolo de inicio. 3.5.1 Gramáticas libres de contexto Una gramática libre de contexto es un conjunto de vakiables (también llamado no terminales o categorías sintácticas), cada una de las cuales representa un lenguaje. Los lenguajes representados por las variables son descritos recursivkmente en términos de otras variables y símbolos primitivos llamados terminales. Las teglas que relacionan a las variables se conocen como producciones[HOP93].Se llaman iramáticas libres de contexto porque una derivación de un no terminal se puede aplicar indebendientemente del contexto donde este ubicado ese no terminal. Las palabras de un lenguaje libre de contexto pueden ser reconocidas por un autómata push-down (PDA), un PDA esta compuesto d& dos cintas (posiblemente infinitamente largas). La primera es una cinta de entrada cónteniendo la palabra a ser reconocida. La segunda es una pila, inicialmente conteniendo '!elsímbolo de comienzo S y un símbolo de terminación'#. Las gramáticas libres de contexto tienen muchos usos prácticos, muchos de las sintaxis de los lenguajes de programación pueden ser especific'ados usándolas, cada uno de estos lenguajes tienen, sin embargo, construcciones que no son de libre contexto, tal como el encabezado para un procedimiento con parámetros, parámekos solo tienen sentido en el contexto de un procedimiento [APP91]. 23 Capítulo 3 MARCO TEÓRICO Una gramática libre de contexto tiene cuatro componentes[AH090]: 1. Un conjunto de símbolos terminales. Símbolos básicos con los cuales se forman las cadenas del lenguaje. 2. Un conjunto de símbolos no terminales. Son variables 'que denotan conjuntos de símbolos gramaticales. 3. Un conjunto de producciones. Definen reglas gramaticales,.están formadas por un lado izquierdo, unaflecha, y un lado derecho. El lado izquierdo consta de un símbolo no terminal, el lado derecho puede estar formado por símbolos terminales, símbolos no terminales o una combinación de ambos. 4. Un simbolo inicial. Es un símbolo único y es no terminal. Una gramática libre del contexto se denota por G=(V,T,P,S), en donde : V: es el conjunto de símbolos no terminales. T: es el conjunto de símbolos terminales. P: es el conjunto de producciones. S: es el símbolo inicial. Naturalmente, las expresiones aritméticas pueden ser definidas recursivamente. Los siguientes ejemplos ilustran como trabaja la definición. Consideremos expresiones que envuelven: a) Los cuatro operadores binarios, b) Paréntesis para agrupar, c) Operandos que son números y, .d) Números que pueden ser cadenas de uno Ó más dígitos. I' Las producciones son: <expr> + <numero> <expr> + (<expr>) <expr> + -<expr> <expr> + <expr> <op> <expr> cop> + + I - I * I / <numero>+ <numero><digito> <numero>+ <digitoz <digito>+O I 1 12 13 14 15 16 17 18 19 Los símbolos terminales son: 0,1,2,3,4,5,6,7,8,9, + - * / ( ) Los símbolos no terminales son: expr,'op, numero y digito. El símbolo inicial es: expr. 3.5.2 Gramáticas regulares[APP91] Definiremos una gramática regular en dos pasos. El primero para .definir una expresión regular e sobre un alfabeto C. .24 I/ MARCO TEÓRICO Capítulo 3 1. A (cadena nula) es una expresión regular. 2. Si XEZ,entonces x es una expresión regular. 3. Si e, es una expresión regular, entonces también lo es (e,). 4. Si el y e2 son expresiones regulares, entonces también lo son el + el, el ' e2, y el*. La regla 2 nos dice que cada símbolo del alfabeto es una expresión regular. Nota que expresiones regulares son encerradas bajo tres operaciones, +(unión), (concatenación) y * (Cerradura de Kleene). El paréntesis de la regla 3 no es un símbolo del alfabeto, pero puede ser usado libremente para hacer expresiones claras. Símbolos tal como "(" y 'y'' que pueden ser usados en expresiones pero que no forman parte del lenguaje mismo,, son llamados metasímbolos. Para entender la regla 4 consideremos.un ejemplo. Suponer que C = {x, y), la regla establece que x+y es regular. Aquí x+y significa x ó y , ó el conjunto unión x y y, si x y y son conjuntos. x y es también expresión regular, como son x , xx, m,...yx,yy, yyy, my, etc. Podemos escribir q y como (x)(yy) para indicar la concatenación den y yy. Con expresiones regulares definidas, podremos listar las reglas de una gramática regular usada para desarrollar un lenguaje regular L, desde una expresión regular e. Escribiremos L(e) para indicar el lenguaje L definido por e. 1. Si e = x, entonces L(x) = {x}, esto es, la palabra sola en el lenguaje L es x. L(A) = { A } . 2. Si L(e1) = Li y L(e2) = L2 entonces, a. L(eie2) = LiLi b. L(ei+ez) = LI + LZ c. L(el*) = LI* Por ejemplo suponer LI = {x} y L2 = {y}, donde'& = x y ez = y. Esto es, cada lenguaje tiene exactamente una palabra en él, entonces: a) L(xy) = {xy}, una palabra sencilla, xy b) L(x+Y) ? {XI+ {Y) = {x, YI C) L(X*) L* = {A, XX, XXX, ...} d) L(x* y) = L(x*) L(y) = {y, xy, XXY, X n Y , -1 Los lenguajes regulares son generados por expresiones regulares, cuyas palabras pueden ser reconocidas por autómatas finitos (deterministas o no deterministas). Un lenguaje que puede ser reconocido por un autómata finito es equivalente a un lenguaje regular. 3.6 Generador de parsers [MET-] Un parser es una herramienta que lee caracteres desde una entrada fuente e intenta darle sentido a su organización y desempeñar funciones Útiles basadas en esta organización. En general el parser no lee directamente de los caracteres de entrada, los caracteres de entrada son leídos por un scanner el cual ensambla los caracteres en tokens. Estos tokens son entonces leídos como entrada por el parser. El esquema de la combinación parserscanner es mostrado en la figura 3.1. 25 . . . . . .. . MARCO TEÓRICO Capítulo 3 Caracteres fuente Scanner Caracteres Tokens Parser Un generador de parsers es una herramienta que toma como entrada la especificación de un parser y un scanner (llamado gramática) y genera como salida el código que implementa el analizador sintáctico. Scanners son especificados . en gramáticas usando expresiones regulares (representan tokens). En el javacc, la sintaxis usada es ilustrada en el siguiente ejemplo: Token { <INT: “int”> <ID: r‘a3,-‘‘zn, “A”-“Z” 3 1 “ - ”] [“ >, >> “A”-“Z”, “0”-“9”, a - z , ‘6 ‘I ”I)* - La especificación anterior contiene dos expresiones regulares, la primera es simple especifica “int”, mientras que la segunda es comparada por alguna cadena que empieza con una letra o guión bajo y es seguida por algún número de letras, dígitos o guión bajo. Los parsers son especificados usando producciones. Una producción define un no terminal al especificar como puede ser expandido en otros no terminales y tokens. El siguiente ejemplo muestra como es una producción en javacc: void varDecl(): {I { Type() <ID> [“=” expression()] “;” I Esta producción define un no terminal “varDecl” como expansión para el no terminal “type” seguido por el token “<ID>” seguido opcionalmente por una inicialización (la cual es el token “=” seguido por el no terminal “expression”) finalizando con el token “_>> 3.7 JavaCC [MET-] Esta herramienta se utiliza para la generación de analizadores léxicos y sintácticos (parsers), el significado de sus siglas es: Java Compiler Compiler. El funcionamiento de la misma es el siguiente: 26 Capítulo 3 ' MARCO TEÓFUCO JavaCC toma como entrada un archivo con extensión jj, el cual debe contener la especificación de la gramática en formato BNF del lenguaje a analizar y posteriormente genera un programa en Java (conjunto de clases) que reconoce empates a dicha gramática. Los pasos para la generación del parser son: 1. Escribir el archivo que contiene la especificación de la gramática a analizar. 2. Invocar a la herramienta JavaCC, figura 3.2, seleccionar el archivo de especificación de la gramática, dar clic en next. ! Figura 3.2 Pantalla de generación del analizador 3. Seleccionar las opciones de javacc (figura 3.3), dar clic nuevamente en next. Figura 3.3 Pantalla de selección de opciones para el analizador 27 -. .. .. .. MARCO TEÓRICO Capítulo 3 4. en la última pantalla figura 3.4, dar clic sobre build para generar' el coniunto de - programas en Java que formarán parte del.analizador , . _ _ _ _ sintáctico. - , ,2 cmnim: ~ I I li F I ') I Cbck on 'Build' to @crate p m m ~ I .u ! I i !I . Id- . rmI " Q.1 . . 5. Invocar el compilador de Java (Javac) para crear el código Bytecode (.class) del analizador. javac nombre-archivo.java Después de esto ya se puede invocar al analizador sintáctico a través del nombre de la clase principal del mismo (nombre del archivo con extensión jj), para utilizarlo con un fin específico. Además de esto, JavaCC también proporciona otras herramientas como: JJTree: Es una herramienta que pre-procesa una gramática JavaCC con acciones para construir árboles sintácticos. JJDoc: Convierte archivos de gramáticas JavaCC en documentos, ejemplo: archivos HTML. JavaScope: JavaScope ofrece muchas métricas de cobertura basadas en código fuente, éstas nos dan una idea de como probar nuestros analizadores sintácticos. 28 Capitulo 4 MODELO CONCEPTUAL DEL SISTEMA Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA En este capítulo se describe la solución adoptada para resolver el problema planteado en el primer capítulo, esta solución se basa en el uso de un analizador sintáctico construido a partir de la definición de la gramática completa del lenguaje C++; del modelo canónico de representación de patrones de diseño planteado en el IPADIC++ y de la herramienta que verifica la estructura de los programas en lenguaje C++ atendiendo a la sintaxis de este lenguaje. 29 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA 4.1 Introducción En el capítulo uno se describe un problema que tiene relación con la detección de patrones de diseño en código fuente escrito en el lenguaje C++ que fue implementado en el IPADIC++ [CAS99], En la detección de patrones que realiza el IPADIC++ no se considera la gramática completa del lenguaje C+t. Esta limitante conduke a que el analizador del código que se explora no reconozca todas las secuencias o cadenas de código aunque éstas sean bien formadas de conformidad con las reglas de la gramática estándar ANSI-IS0 del lenguaje C++; por lo que en este trabajo de tesis se planteó como una necesidad, solucionar esta restricción, incluyendo en el analizador'del IPADICtt la gramática estándar de C++. Por lo tanto se utilizó la arquitectura de entradas y salidas del sistema descrita por el IPADIC++, con la diferencia de que en el primer módulo .se incluye un analizador sintáctico que define la gramática completa del lenguaje C++ [VIS96], con este módulo se extrae información que se guarda en tablas de información, y posteriormente, esta información se procesa para obtener la forma canónica del código fuente. Esta forma canónica se pasa al modulo de reconocimiento de patrones de diseño, concluyendo con el resultado sobre la detección o no detección del patrón de diseño. A continuación se describe el análisis' realizado p h a el desarrollo de la investigación, la arquitectura de la herramienta y la interfaz ai usuario. 4.2 Análisis del sistema Para el desarrollo de la presente tesis fue necesario realizar un análisis del funcionamiento del IPADICtt, del analizador sintáctico que compila el código fuente según la gramática del lenguaje C++ y de la información requerida para llegar al objetivo planteado, a continuación se describe cada uno de estos puntos y las conclusiones a las que se llegó. 4.2.1 Análisis del IPADIC++ El Sistema para identificación de patrones de diseño en código C++ (IPADIC++) [CAS991 define un modelo y un lenguaje canónico que sirve para representar la estructura de los patrones de diseño y transforma por medio de las reglas gramaticales del lenguaje canónico las relaciones estructurales del código. fuente a su forma canónica. El modelo consiste en una gramática libre al contexto en notación BNF. Para la forma canónica del código fuente se utilizan las reglas de producción del lenguaje C++. La herramienta desarrollada en el IPADICtt esta constituida por dos módulos: 1. Módulopara la transformación de código C++ a la forma canónica: Tiene como entrada un conjunto de clases en C t t , que pueden estar en uno o varios archivos. En el segundo caso deben existir llamadas a los demás'archivos, y proporciona como salida la forma canónica del código analizado. Este módulo reconoce en el código analizado los tipos de relaciones: herencia, agregación, asociación e instanciación y se genera una cadena (forma canónica del código) que'contiene las relaciones entre las clases del código. También detecta la cardinalidad de relaciones, esto es, cuando objetos de una clase se relacionan más de una vez con objetos de 30 . Capítulo 4 . . .~ ~ MODELO CONCEPTUAL. DEL SISTEMA otra clase. Además de generar como salida la forma canónica del código analizado, también proporciona una tabla con las relaciones detectadas en el código en las que no están involucradas las clases pertenecientes a él, se asume que estas relaciones se establecen con la librería de funciones o clases del lenguaje C++. 2. Módulo de reconocimiento de patrones de diseño: Este módulo recibe como entrada el código del programa que se explora, representado en su forma canónica, y realiza el análisis sobre este código para detectar alguno de los tres patrones de diseño implementados en el sistema (abstract facto&, composite e iterator). Asimismo, proporciona como salida un mensaje que especifica el resultado de la detección del patrón de diseño buscado dentro del código fuente. La interfaz de la herramienta muestra una ventana (figura 4.1). Esta ventana consta de un menú que tiene dos opciones: Patrones de diseño y Ayuda.; La opción de Patrones de diseño permite iniciar el proceso de detección del patrón de diseño seleccionado y la opción de Ayuda muestra ventanas de dialogo de información acerca del sistema. Figura 4.1 Pantalla principal del IPADICH Al seleccionar la opción de Patrones de diseño aparece una ventana de diálogo (figura 4.2) en la que hay que seleccionar el archivo con extensión CPP a analizar. Una vez que se selecciona este archivo y se pulsa el botón aceptar, el sistema procede a la detección del patrón de diseño seleccionado en el código fuente, y concluye con los mensajes de resultado de la búsqueda del patrón de diseño sobre la forma canónica del código fuente. Los mensajes de salida son: en el cuadro de texto de relaciones existentes en el código muestra la forma canónica de las relaciones estructurales entre clases del código fuente; en el cuadro de texto de relaciones del código que se explora con la librería muestra las relaciones del código con la librería de C++, y en el cuadro de texto de resultado de buscar el patrón muestra el resultado de la búsqueda del patrón de diseño en el código fuente. El Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA texto mostrado en resultado de la búsqueda puede ser: “PATRON E N C O N T W O ’ , mencionándose las clases que intervienen en el patrón, “PATRON NO ENCONTRADO’, mencionándose las relaciones que hacen falta para que se tenga el patrón buscado. Forma canónica del patrón: - 1 Nombre del archivo a analizar: D:icrnmiPATRONESiIteratoripruebal .cop I Relaciones existentes en el código: lierator Relaclanes del código con la librería Resultado de buscar el patrón: Figura 4.2 Ventana de diálogo de detección de patrones de diseño Comentarios: Es necesario utilizar algunos de los conceptos definidos por el IPAüIC++ como es la definición del modelo canónico y la definición del autómata de reconocimiento para los patrones de diseño, así como de la estructura general de entradas y salidas del sistema. En el módulo de transformación del código fuente a forma canónica, se retoma parte del procedimiento que une los diferentes archivos de código fuente que están asociados al archivo principal que se explora, por medio de la directiva de pre-procesamiento #include. En 1PADICi-i- el orden de obtención de código fuente de cada uno de los archivos asociados se lleva a cabo conforme se encuentran las llamadas a los archivos por medio de la directiva #include. Para efectos de implementación en esta tesis, se pondrán los nombres de los archivos en una pila. En la obtención de la forma canónica del código fuente, se, requiere de la implementación de un analizador sintáctico que realice la compilación del código fuente con respecto a la gramática completa del lenguaje C++ . Esta forma canónica servirá como entrada del modulo de reconocimiento de patrones de diseño. AI modulo de reconocimiento de patrones de diseño &‘le añadirán las acciones correspondientes para la detección de los’ patrones de diseño Strategy y Template method. Se debe modificar el funcionamiento de la interfaz con el usuario para optimizar el tiempo de ejecución del sistema. 32 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA 4.2.2 Estudio del analizador sintáctico que compila el código fuente según la gramática del lenguaje C t t Analizador sintáctico de la gramática del lenguaje C++ desarrollado en JavaCC por Sreenivasa Viswanadha [VIS96]. Esta herramienta tiene asociados los siguientes archivos java que ayudan en la determinación de los alcances de las variables que forman el programa analizado: Scope.java es una clase que maneja datos de una clase o función. Como es el nombre, el tipo (si es clase o tipo), contiene una tabla parcial de símbolos que están dentro de está clase o función, y el nombre de la clase o función a la que pertenece. CIassScope.java es una clase que hereda de Scope, esta clase guarda todas las superclases de las que una clase es derivada. DecIaration.java es una clase que guarda los atributos de una declaración; el nombre, el alcance, usa una variable que define si es clase o no y otra variable booleana que define si es tpedef o no. Esto se llena conforme la declaración es analizada SymtabManager.java clase que maneja la tabla de símbolos y alcances dentro de una unidad de traducción dada. Consta de las siguientes variables: scopeTuble es un objeto de tipo Hashtable, es una tabla de símbolos global indexada por nombre del alcance (clase o función). scopeStuck pila de alcances que tiene un máximo anidamiento permitido de 100, es un arreglo que contiene clases Scope. depth variable de tipo entero inicializado en cero y nos indica la profundidad de anidamiento de scope. Además, contiene los siguientes métodos: J Openscope: este método abre un nuevo alcance (con nombre y bandera de tipo opcionales). J PutTypeName: este método pone el nombre pasado como argumento en la tabla de símbolos tipo introducidos en la clase o función que esta en la posición depth de la pila de clases o funciones. J IsFullyScopedTypeName: este método regresa un valor booleano, si el nombre que recibe como argumento es un nombre de tipo dentro de los alcances manejados. J IsTypeName: retorna un valor booleano que nos indica si el nombre se encuentra dentro de las tablas de símbolos definidos dentro de los, alcances (clase/función) que se encuentran en la pila de alcances. J CloseScope: método que cierra el alcance al disminuir en uno la profundidad de anidamiento en los alcances. J IsCtor: retorna un valor booleano que indica si el nombre que recibe es el nombre de un método igual al de una clase. J GetCurScope: este método retorna el objeto de tipo Scope actual. J GetScope: retorna el objeto Scope correspondiente al nombre pasado como parámetro ai método. J GetScopeOfFullyScopedName: retorna un objeto de tipo Scope correspondiente a B en A::B::C (pasándole B como parámetro al método) . J IsGlobalScope: retorna un valor booleano si la profundidad de anidamiento de Scope . (clase/función) es uno o dos. ' 33 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA AI compilar el archivo CPLUSPLUS.jj se generan los archivos CPPParser.java, CPPParserConstants.java, CPPParserTokenManager.java,ParseException.java, Token.java, TokenMgrError.java. La ejecución del programa CPPParser comienza abriendo 'el archivo con extensión CPP a analizar, pone su contenido en una variable de flujo de entrada de archivo, si no hay error crea una instancia llamada parser, de la clase CPPParser y ejecuta el método traslation unit() este método inicia abriendo un alcance para el programa a analizar. Define un programa de C++ como una unidad de traducción y a la unidad de traducción como un grupo de cero o más declaraciones externas seguidas de un token de fin de archivo (<EOF>). Las declaraciones externas a su vez se definen como uno de los siguientes tipos: Declaración Enumeración Definición de destructor Definición de constructor Definición de función Declaración o definición de función de conversión Encabezado de plantilla Estos tipos se derivan en otras producciones que definen cada una de estas partes en la gramática del lenguaje C++. Comentarios: En este analizador sintáctico solo se realiza un análisis de sintaxis de código fuente escrito en lenguaje C++. Hace uso de otras clases que ayudan en el reconocimiento de los alcances de cada una de las clases, variables y funciones que forman el programa analizado. El analizador sintáctico no reconoce el salto de línea y las directivas del pre-procesador. Se incluyó en,el analizador sintáctico el reconocimiento de los saltos.de línea. Se detectan los puntos en los que serán incluidas las accionesisemánticas para obtener la información necesaria para poder escribir la cadena de símbolos que contenga la forma canónica del código fuente. . Para obtener la información requerida se incluyeron acciones semánticas en Declaración y definición de función, dentro de las derivaciones de declaración es donde se extrae la infórmación referente a las clases y las relaciones de herencia, agregación, asociación e instanciación. Y dentro de las derivaciones de la declaración de función se extrae la información referente a las funciones como es su nombre, el alcance que tiene cada función y la localización de estructuras $0 switch anidadas. 4.2.3 Nuevos patrones Para poder realizar el reconocimiento de los patrones de diseño se requiere de la siguiente información: 34 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA Factory method 03 Clases Participantes: Cliente Creador-abstracto Creador-concreto [n] Producto abstracto Producto~concreto[n] *:* Relaciones: Herencia Instanciación Asociación Para el reconocimiento de este patrón, se requiere de encontrar al menos una clase derivada (Creador-concreto[n]) de otra clase abstracta (Creador-abstracto) y que esta clase derivada efectué la instanciación de un objeto de clase (Producto concreto[n]) la cual debe ser derivada de la clase abstracta (Producto-abstracto); o encontrar solo una clase que instancie objetos de otra clase y hacer la observación de que se pueden incluir las clases base de cada una de ellas para que se cuente con el patrón. . .. 9 Strategy -3 Clases Participantes: Context = Strategy (clase abstracta) Concrete-Strategy [n] *3 Relaciones: Herencia = Agregación Para el reconocimiento de este patrón hay dos opciones: 1. Si se encuentra la instrucción switch o $(anidados en más dé tres niveles), se puede sugerir la implementación de este patrón poniendo el código correspondiente a cada opción del switch en un método Interfaz dentro de una clase Concrete Strategy. Además de implementar una clase Strategy, de la que se derivaran ias clases Concrete-Strategy, en esta clase definir un método virtualmente puro Interfaz. Y finalmente, implemeritar una clase Contexto en la que se manejarán las opciones del $o switch, agregar a esta clase la clase Strategy. . . 2 . Por estructura se tendrían que encontrar clases Concrete-Strategy que hereden una interfaz común para la implementación de un algoritmo y una clase contexto que mantiene una referencia a un objeto Strategy, se puede d e f i n i k a interfaz que deja que la clase Strategy acceda a los datos o pasarse la clase contexto como un argumento para operaciones Strategy. . . 9 Template method *3 Clases Participantes: Abstractclass = Concreteclass 4 4 Relaciones: Herencia 9 9 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA Se debe reconocer en una clase base (abstractclass), un método plantilla dentro del cual se hagan llamadas a otros métodos (primitivos) virtualmente puros que las subclases (Concreteclass) reemplazan para proveer comportamientos concretos. Para poder obtener y manejar la información anterior se requiere del uso de las siguientes tablas de información, de las que se ejemplifica su contenido en las tablas 4.1: J Archivos: El nombre del archivo que contiene la función main corresponderá a la clase cliente, posteriormente siguiendo la directiva #include, se analizarán los códigos asociados al código de la clase cliente, para detectar todos los nombres de archivos asociados. J Clases: Nombre de clase y relaciones (herencia, agregación, asociación e instanciación) que existen entre ellas. J Funciones: Nombre de la función, clase a la que pertenece la función. Nombre de la función en la que existen i f s con más de 3 anidamientos o switch con más de 3 case. Relaciones entre las funciones (formales y actuales). Tablas 4.1: Ejemplo del contenido de las tablas de información 36 MODELO CONCEPTUAL DEL SISTEMA Capítulo 4 F actual Clase ConcreteAggregate ConcreteIterator Aggregate F formal Open Add Operation Iteratoradd main First INST.ELSE False False SALIO NIVEL True 4.3 Arquitectura de la herramienta Ésta herramienta esta constituida por dos módulos: Módulo para la transformación del código C++ a la forma canónica y Módulo de reconocimiento de patrones de diseño; implementados en el lenguaje de programación Java y en el generador de parsers javacc. La arquitectura de la herramienta se ilustra en la figura 4.3. El diagrama de clases de la herramienta en notación OMT se muestra en las figuras 4.4, 4 . 5 4.6. ~ \I"".6Y I Pi.l...*Dli" I 1, I . Parse;dela gramatia del lenguale C U I Modelo de ~ I Representación canónica de codigo I I Desplegado de a que patrón corrcsponde o a cual se parece 1 Tablas de información I I t "I del e6digo a la forma canónica de patrones de diseña Figura 4.3 Estructura general de la herramienta 37 MODELO CONCEPTUAL DEL SISTEMA Capítulo 4 ____. *FCPD() ..-~ Pantalla w h : DialogHandler = new DialogHandler () +detecta() Abrir bandarch : boolean =false rror: boolean =false ,/ *Abrir() *nom breSinEkt0 modulo2/ I d +ieico(.) %tros-arch() %et-codigo() $getTablas() $get-rlib() $mosb-ar-inf-tab() *inicialira() *buscaFun() *getTernplatesO %eRegRep() $bus caClas eRel() *buscaClas eRelLibi BfonnaCanonica() *buscaRegFun() Figura 4.4 Diagrama de clases de la herramienta 38 1 MODELO CONCEPTUAL DEL SISTEMA Capítulo 4 4.3.1 Módulo para la transformación del código C++ a la forma canónica En este modulo se convierte el código escrito en lenguaje C++ a su forma canónica en la figura 4.7 se ilustran las entradas y salidas para este modulo. . Paner de la gramática 1 I 4 +I I Closol ASOCIACION dmd, close3 AGREGACION clare2, V ASOCIACION clareS ACRECACION closed INSTANCIACION cloreZ, I closoZ HEREDA &re3 código a 18 foma can6nica Figura 4.7 Entradas y salidas del módulo para transformar el código escrito en lenguaje C++ a la forma canónica Este módulo tiene como entrada el archivo de definición de las clases que forman un programa escrito en lenguaje C++, estas definiciones pueden estar en uno o varios archivos; en el caso de que estén en varios archivos debe de incluirse en cada uno de los archivos la directiva #include con el nombre del archivo o archivos en los que se encuentra la definición de las clases de las que hace uso, es importante el orden en que se encuentren las definiciones de estos archivos y se obtiene como salida la forma canónica del código fuente analizado. Las clases principales en este modulo son CPPParser y ManTabData (ver diagrama de clases, figura 4.5). CPPParser es la clase que realiza el análisis sintáctico de la gramática del lenguaje C++, esta clase a su vez tiene asociadas otras clases que genera automáticamente javacc, tiene además clases que ayudan a verificar los ámbitos de alcance de cada una de las clases y variables que forman los programas analizados. ManTabData es la clase manejadora de las tablas de información necesaria para obtener la forma canónica del código analizado. Los pasos seguidos para la construcción de este módulo son los siguientes: 1. Se inicia obteniendo los nombres de los archivos asociados al programa cliente por medio de la directiva #include, con esta lista de nombres se une el contenido de estos archivos en un solo código fuente. Este archivo es pasado como entrada al analizador sintáctico que verifica la estructura sintáctica del código fuente de acuerdo a la gramática completa del lenguaje C++. 2. Una parte de este módulo se generó utilizando la herramienta JavaCC haciendo us<>del archivo CPLUSPLUS.jj en el que se especifica la gramática del lenguaje C++, este 40 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA archivo tiene asociados archivos de java que le ayudan en la implementación del proceso de análisis semántico para la resolución de ambigüedades. 3. Se estudió el analizador sintáctico que verifica la gramática y se detectaron los puntos en los que se definen cada uno de los datos que se requieren para llenar las tablas de información, con las que se podrá obtener la cadena que contenga la forma canónica del código fuente. Se implementó una clase de java llamada ManTabData, esta clase contiene los métodos que manejan las estructuras de cada una de las tablas de información así como las tablas mismas, esta clase es asociada al analizador sintáctico y utilizada durante el proceso de reconocimiento del código fuente guardando la información requerida en las tablas de esta clase. 4. Después de lo anterior, se invocó a la herramienta JavaCC, para generar las clases pertenecientes al analizador. 5 . Posteriormente se invocó al compilador de Java para generar el código de bytes (Bytecode) del analizador. Después de ésto, el analizador está listo para llamarse desde cualquier otra clase. 6 . Una vez que concluye el proceso de reconocimiento del código fuente, se procesa la información contenida en las tablas para obtener la forma canónica del código fuente. 7. Esta forma canónica es devuelta como salida de este módulo. Para la realización del punto tres fue necesario identificar en el código fuente los puntos clave en el código donde se escriben las acciones semánticas para la obtención de la información necesaria para llenar las tablas, estos puntos son descritos a continuación: Para las clases, en el código fuente en la definición de una clase el nombre de la clase corresponde al identificador que se encuentra después de la palabra reservada “class ”. El archivo que contiene la función main, se toma como clase (cliente), por lo tanto se toma el nombre del archivo como el nombre de la clase. Para la herencia, en el código fuente en la definición de una clase se especifican dos puntos(:) seguidos del nombre de otra clase, el nombre de la clase hija corresponde a la clase definida y el nombre de la clase padre corresponde al identificador que se encuentra después de los dos puntos(:). Para la agregacibn, en el código fuente se identifica en la declaración de variables miembro de la clase, donde el tipo de la variable declarada corresponde al nombre de la clase agregada a la clase que se esta definiendo. En caso de que se encuentre más de una declaración de este tipo se especifica la agregación con cardinalidad, colocando el postfijo [n] al final del nombre de la clase agregada. Así el nombre de la clase compuesta es la clase que se esta definiendo y el nombre de la clase agregada es el nombre de la clase que corresponde al tipo de la variable que se esta definiendo. 41 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA Para la asociación, en el código fuente se identifica en la declaración de variables miembro de la clase, donde el tipo de la variable declarada corresponde al nombre de la clase asociada a la clase que se esta definiendo este tipo se encuentra declarado como un apuntador, es decir va seguido de un asterisco. En este tipo de relación se especifica la cardinalidad [n] en la clase conocida para todos casos de asociación que se den en el código fuente ya que un apuntador a un objeto de clase especifica el inicio de una lista de objetos de la clase que se esta asociando. Así el nombre de la clase conocedora es el nombre de la clase que se esta definiendo y el nombre de la clase conocida es el nombre de la clase a la que se apunta. Para la insfunciación, en el código fuente se identifica en las instrucciones que forman el código de una función, la devolución de un nuevo objeto del tipo de la clase instanciada. Así el nombre de la clase creadora es la clase en la que se encuentra la función y el nombre de la clase creada es el nombre de la clase instanciada. Para las funciones, se encuentra en el código un especificador de tipo que es devuelto por la función, seguido del nombre de la función ligado opcionalmente a un alcance con alguna clase(::) donde se especifica antes de los cuatro puntos el nombre de la clase a la que pertenece la función y después de los cuatro puntos el nombre de la función seguido por paréntesis que abre y una lista opcional de parámetros seguido de un paréntesis que cierra. Dentro de cada función puede haber un llamado a otras funciones. A continuación se ejemplifica en código cada uno de los puntos descritos en los párrafos anteriores: //Archivo pruebal.cpp #include "c:\\patrone #include "c:\\patrones\\PD-composite\\composite.cpp" int main (void){ Leaf 11 = new Leaf(-l); Leaf 12 = new Leaf (-2); composite ci = new Composite(1); Composite c2 = new Cornpocite(2); ci.add(&li) ; c2.rernoveComposite(&cl) ; return ( 0 ) ; I //Archivo: Component.hpp #include <iostream.h> class Component{ e clase: Component \ 42 Capítulo 4 private : MODELO CONCEPTUAL DEL SISTEMA Clase que conoce: Component Clase conocida: Component[n] //Archivo:Composite.cpp #include "c:\\patrones\\PD composite\\component.hpp" e a s s Composit c Component, { . IClase hija: Composite Clase padre: Component public: Composite(int id){ first = NULL; -identification virtual void add (Component*); virtual void removeLeaf(Component*) ; virtual void removeComposite(Component*); virtual void operation (void); void operation(Component*); = id;} Clase que conoce: Composite Clase conocida: Component[n] //Archivo: Leaf.hpp #include "c:\\patrones\\PD composite\\component.hpp" class Leaf : public Compon&t{ Leaf L I Clase padre: Component I public: Leaf(int id) { - identification . = id;) virtual void operation(void) {coutcc"Leaf: " < c-identification<<endl;} private : int -'identification; 1; class ConcreteFactoryl: public AbstractFactory { private : int Identificacion;. 43 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA public: ConcreteFactoryl(int ID) { Identificacion = ID; } ; virtual AProductoA *CreateProductA(int); virtual void Prtívoid) ( cout c c 'IConcreteFactoryl: I' c c Identificacion < e endl; 1 } ; / / Fin clase AbstractFactory. AProductoA *ConcreteFactoryl::CreateProductA(int I) { return(new CProductoAOíI) ) ; T 1' 1 Clase Creadora: ComcreteFactoryl Clase Creada : CproductoAO Clase propietaria: Composite Loid Composite::operatiofj(Component* c) { Y static int level = O; Component *t; c->operationO ; if(c->compositeDetect){ for(t=( (Composite *)c)- > -first; t; t=t->getchild()){ operation(t1 ; 1 level--; Función actual: operation Función formal: operation 1 -Las restricciones de este módulo son las siguientes: Se analiza únicamente código escrito en lenguaje C++. Las clases pertenecientes al código analizado pueden estar en uno o en varios archivos, con la restricción de que en el mismo archivo deben estar tanto la declaración como la implementación de la clase. Debido a que en C++ es difícil diferenciar entre una relación de Agregación y una de Asociación, ya que la primera se puede implementar de dos formas: ya sea declarando al objeto o como un apuntador (referencia) al objeto, en cambio Asociación se implementa declarando un apuntador al objeto (para más información ver el apéndice A); cuando se encuentra una relación implementándose a través de un apuntador se considera como Asociación, si se encuentra sin apuntador es considerada como Agregación. Durante el reconocimiento de la estructura sintáctica del código fuente se reconoce y guarda información acerca de las clases y los diferentes tipos de relaciones que se pueden encontrar en los patrones de diseño: Herencia, Agregación, Asociación e Instanciación, 44 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA posteriormente esta información se procesa para obtener la forma canónica. En la figura 4.8 se muestra un ejemplo en el que se visualiza el resultado de ejecutar el módulo en cuestión. 'ARCHIVO c:\patronesWD~camposile\component.hpp" 'include <iastream.h> lass Component( iublic: Component()(-nexf = NULL;) virtual void operation(void) = O; Component* getchild(vaid) const {ream next;) virtual void setchild(Companent* next) {_next = next;) v i m a l int campasiteDetecl() (rehirn(O);} invate: Component' n e x t ; IARCHIVO c:\patronesiPD-~omposit~\~ompasite.hpp" [include c:\\patrones\WD_camposite\\camp~~~~t.hpp" lass Composite: public Component{ iublie: hmposile(in1 id){-first = NULL; -identification = id;) vimal void add(Component*); viI1uoI void removeLeaf(Componen1'); virtual void removeComposite(Component'); virtud void operatian(vaid); void opfration(Camponen1'); v i m a l in1 eompositeDetect() (return(i);) .¡yate: int -identification; Component' -first; IARCHIVO c:\patronesWD-~omposite\lcaf.hpp" tinelude "c:\\patranes\WD~composite\\cornponenl.hpp" ,lass Leaf: public Component( Bublic: Leaf(in1 id){-identificatian = id;) vinual "aid aperatian(vaid) (caut«"Leaf: "«identi fication«endl;) invale: in1 _identification; /ARCHIVO C\ppatranesWD-Composit~\p~~b~l .cpp linclude "c:\\patranes\\PD~compos~t~\\composite.cpp" linclude "c:\\ppalrones\iPD_comp~~it~\\l~~f.hpp" nt main(vaid)( Leaf II =new Leaf(-l); Leaf I2 =new Leaf(-2); LeafLl =newLeaf(l); Leaf L2 =new Leaf(2); Composite C I =new Composite(1); Composite c2 =new Compasite(2); Camposite c3 =new Compasite(3); c l .add(&ll); cl .add(&12); c3.add(&L1); e3.add(&L2); cZ.add(&cl); c3.add(&c2); c3.operation(&c3); c3.opcration(&c3); conversión del código L canónica Component, prueba1 A GREGACION LeafPI AGREGACION Composite[n], Leaf HEREDA Component, Composite HEREDA Component ACQUAINTANCE Component[n], Component ACQUAINTANCE Component[n] Figura 4.8 Ejemplo en el que se visualizan entradas y salidas del módulo. c2.removeComposite(&cl); c3.operation(&c3); ..........I "%. 45 MODELO CONCEPTUAL DEL SISTEMA Capítulo 4 Este módulo también detecta la cardinalidad de relaciones, es decir, cuando una clase se relaciona más de una vez con otra; por ejemplo, si en la clase A se encuentra más de una relación de agregación con la clase B, este módulo encuentra una relación de agregación con cardinalidad n de la clase B en la clase A. 4.3.2 Módulo de reconocimiento de patrones de diseño En este módulo se implementa el reconocimiento de los patrones de diseño, toma como entrada la forma canónica del código fuente y el patrón de diseño a ser localizado, y a partir de un análisis de éste código detecta si se encontró el patrón de diseño buscado. Las entradas y salidas de este módulo se visualizan en la figura 4.9. Desplegado de a que patrón corresponde o I AbstractFactary recOnOclmientO Figura 4.9 Entradas y salidas del módulo de reconocimiento de patrones de diseño En esta tesis se agrego al modelo, la implementación para el reconocimiento de los patrones de diseño Strategy y Template method, el patrón de diseño factory method por razones de tiempo no fue implementado en el sistema. Los pasos seguidos para la construcción de este módulo son los siguientes: 1. Se comprobó que la forma canónica generada por el primer módulo funcionara correctamente como entrada para este módulo. 2. El reconocimiento de los patrones de diseño strategy y tempiate method, se hizo basándose en el comportamiento del programa analizado. Para el strategy se tomó en cuenta las estructuras if0 switch anidadas presentes en el código. Para el patrón template method se tomó en cuenta los métodos o funciones que hacen llamado a otras funciones 46 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA de la misma clase. La forma canónica de.los patrones fue realizada apoyándose en el modelo canónico para la representación de patrones de diseño[CAS99], y en la estructura de cada patrón (ver anexo B). 3. En este módulo la clase Detección hace uso del programa empate2.jj en el que se especifica la gramática d e , los patrones de diseño abstract factory, composite e iterator[CAS99]. 4. Para los patrones de diseño template method y strategy se hace uso de la información obtenida del código durante el análisis del mismo, guardada en las estructuras que maneja la clase MantabData de donde se obtiene la información relacionada con estos patrones. 5 . Para el template method, en el análisis del código fuente con la clase CPPParser, se identifica en las sentencias que son declaraciones si se trata de la llamada a una función de ¡a misma clase (función formal), en este punto ya se tiene el nombre de la función que llama (función actual), el nombre de la clase a la que pertenece la función actual, el nombre de la función actual y el nombre de la función formal se guardan en una tabla de información manejada por la clase ManTabData. 6 . Para el strategy, en el análisis del código fuente con la clase CPPParser, se identifican las sentencias $ o switch anidadas, se manejan para este fin tablas de información auxiliares en las que se guardan contadores y variables booleanas con las que se controla el conteo de niveles de anidamiento de sentencias $ o switch existentes en el código, por último se guardan en una tabla de información manejada por la clase ManTabData cada $o switch que tenga tres o más niveles de anidamiento. 7. Después de lo anterior, se invocó a la herramienta JavaCC, para generar las clases pertenecientes al analizador. 8. Posteriormente se invocó. al compilador de Java para generar el código de bytes (Bytecode) del analizador. Después de esto, el analizador está listo para llamarse desde cualquier clase cliente. En la figura 4.10 se muestra un ejemplo en el que se visualizan la entrada al módulo tratado aquí, y la salida arrojada por el mismo. 47 Capítulo 4 AProductoB, AProductoA, AbstractFactory, prueba1 AGREGACION ConcreteFactoryl AGREGACION ConcreteFactoryZ AGREGACION AProductoA AGREGACION AProductoB, ConcreteFactoryl HEREDA AbstractFactory CREATES CProductoAO CREATES CProductoBO, ConcreteFactoryZ HEREDA AbslractFactory CREATES CProductoAl CREATES CProductoBl, CProductoAO HEREDA AProductoA, CProductoBO HEREDA AProductoB, CProductoAl HEREDA AProductoA, CProductoB 1 HEREDA AProductoB MODELO CONCEPTUAL DEL SISTEMA client ACQUAINTANCE apa ACQUAINTANCE af, af, cfl HEREDA af CREATES pa, apa, pal HEREDA reconocimiento de patrones de PATRON ENCONTRADO: CLASES ABSTRACTAS: AProductoB AProductoA AbstractFactory PRODUCTOS: CProductoA0 CProductoBO CProductoAl CProductoBl FABRICAS: ConcreteFactoq ConcreteFactory2 CLIENTES: prueba1 Figura 4.10 Ejemplo en el que se visualizan entradas y salidas del módulo de reconocimiento de uatrones de diseño. 4.4 INTERFAZ AL USUARIO En el sistema se implement6 una nueva interfaz como se muestra en la figura 4.11, la cual consta de un menú desplegable y tres paneles de datos. En el área de texto del primer panel se muestra el código fuente correspondiente al programa escrito en lenguaje ‘i C++ a analizar. En la segunda área de texto del siguiente panel se muestra la forma :. canónica del código fuente y la forma canónica del patrón de diseño elegido para detectar en el código fuente. En el tercer panel se tienen cuatro áreas de texto en la primer área de texto se muestran las relaciones del código fuente con librerías de C++, en la segunda se muestra el resultado de la detección de contadores i f s anidados con más de tres niveles o switch con más de tres casos, esto es con el fin de indicar la clase y la función en la que se encuentran para que el usuario pueda optar por usar en estos puntos el patrón strategy, en la tercer área de texto se muestra el resultado de la búsqueda de métodos plantilla en las clases y en la Última área de texto se muestra el resultado de la detección del patrón de diseño. En el anexo C se describe el funcionamiento del sistema. 48 Capítulo 4 MODELO CONCEPTUAL DEL SISTEMA ódigofuente Forma canónica de código fuente Relaciones del cód. con lib. 1 1UI ' 8 'I . , I ¡ : ;;I I ./I . / - ' , Estructuras Strategy ! . Métodos Piantilia en clases I .j Resultado de la detección I ! I ! : Forma canónica del patrán de diseño I .o -" p-L_ . . .. .. '~ ~ ~ ." -.- . . Fi-fl. _-_ -. - . .- ~ '' .,. -. -- .-.. ~ .. -t==-- . , . - wJXZIFuMir--iin Figura 4. I1 Interfaz principal del sistema 49 .-. Capítulo 5 . . - . ~ .. EVALUACI~NEXPERIMENTAL Capítulo 5 EVALUACI~N EXPERIMENTAL -. En este capítulo se detallan las pruebas experimentales realizadas sobre la herramienta generada en este proyecto de tesis. Se enuncia la hipótesis de investigación, se definen los casos de estudio a utilizar en estas pruebas, los instrumentos de medición aplicados, el plan de pruebas, los resultados de las pruebas, y el resumen de resultados. 50 EVALUACI~NEXPERIMENTAL Capítulo 5 5.1 Hipótesis de investigación La hipótesis de investigación planteada en la propuesta de este proyecto de tesis fue: Es posible la identificación automática de patrones de diseño en código fuente, de la sintaxis completa del lenguaje C++, a través de la implementación de un modelo de representación canónica tanto de los patrones de diseño como del código fuente a analizar. Durante el desarrollo de esta investigación se obtiene un resultado positivo que es confirmado con la evaluación experimental. 5.2 Definición de casos de estudio IPADIC++, solo considera puntos específicos de la gramática del lenguaje C t t para obtener la información que necesita en el reconocimiento de los patrones de diseño abstract factmy, composite e iterator, por lo que tiene algunas limitaciones, como es, el reconocimiento de relaciones en las que al mismo tiempo que se declara el objeto se hacen otras operaciones con él. En el desarrollo de la presente tesis uno de los objetivos es la implementación del reconocimiento de la gramática completa del lenguaje C++ en la generación de la forma canónica de códigos fuente analizados para detectar en estos patrones de diseño. Debido a lo mencionado en el párrafo anterior el criterio principal de prueba, es que se deben de obtener formas canónicas semejantes a las obtenidas en los casos de estudio utilizados por el IPADICtt; en segundo lugar, al pasar esta forma canónica al módulo de reconocimiento de patrones de diseño debe obtenerse el mismo resultado que el obtenido por el IPADICtt; por otra parte, se prueba el reconocimiento de los patrones de diseño strategy y template method. 5.3 Instrumentos de medición aplicados Con objeto de comprobar lo enunciado por la hipótesis planteada en el presente trabajo de investigación, se deben detectar los patrones de diseño incluidos en esta investigación haciendo uso del modelo canónico de representación de patrones de diseño. En la detección del patrón puede concluirse con dos resultados, uno es el reconocimiento del patrón de diseño correspondiente y el otro es que no se detecten patrones. El instrumento de medición aplicado es propiamente la herramienta desarrollada en esta tesis, lo que sirve para demostrar que es posible realizar la identificación automática de patrones de diseño en código fuente, de la sintaxis completa del lenguaje C++, a través de la implementación de un modelo de representación canónica tanto de los patrones de diseño como del código fuente a analizar. . 5.4 Plan de pruebas El plan de pruebas incluye dos puntos principales: Plan 01. Se realizan doce casos de prueba que consisten en evaluar el sistema mediante la comprobación de la forma canónica obtenida por el IPADIC++, haciendo el reconocimiento de los código evaluados considerando la gramática completa del 51 Capítulo 5 EVALUACI~NEXPERIMENTAL lenguaje C++, debiendo obtener en este punto una forma canónica basada en el modelo canónico definido en el I P A ü I C t t [CAS991 y, al realizar el reconocimiento de los patrones de diseño obtener el mismo resultado. Plan 02. Se realizan ocho casos de prueba en los que se verifica la forma canónica basada en el modelo canónico [CAS99], y al realizar el reconocimiento de los patrones de diseño strategy y template method, se pueden obtener dos resultados que son PATRON ENCONTRADO o PATRON NO ENCONTRADO. 5.4.1 Requisitos ambientales Las características y propiedades físicas y lógicas requeridas para el ambiente de pruebas son las siguientes: *3 Equipo: 9 Computadora personal con la siguiente configuración: J Procesador Intel PI11 o superior. J 128 MB de memoria RAM o más. J Espacio de 2 GB en disco duro o más. J Monitor de alta resolución o superior. J Tarjeta gráfica de 1024x768 píxeles y color de alta densidad de 16 bits o superior. J Mouse. Teclado. 40 Sistema Operativo: 9 Windows 98 o superior. *: Herramientas: 9 Java Compiler Compiler, JAVACC 2.0. 9 Lenguaje de programación Java, JDK 1.2.1 o superior. 9 Medio ambiente de trabajo para programas java, Kawa. *:* Programas de prueba: > Archivo con el código fuente de los programas completos especificados en los casos de prueba que se van a analizar. *:* Programación: 9 Clases que muestran la ventana principal, ejecutan acciones del menú principal. J Programa principal PrincipaLjava. J Archivo Pantalla.java. J MyMenu.java J MyMenuBar.java J Archivo Abrir.java. J Archivo Deteccion.java. J Archivo F-C-P-D.java. 52 Capítulo 5 > EVALUACIÓN EXPERIMENTAL Especificación de la gramática del lenguaje C++, expresada en lenguaje JavaCC, CPLUPLUS.ii. J Programa-principal CPPParser.java. J Archivo CPPParserConstants.java. J Archivo CPPParserTokenManager.java. 4 Archivo ParseException.java. J Archivo Token.java. J Archivo TokenMgrError.java. J Archivo ClassScope.java. J Archivo Declaration.java. J Archivo Scope.java. J Archivo SymtabManager.java. J Archivo ManTabDat.java. k Especificación de la gramática para el reconocimiento de los patrones de diseño, expresada en lenguaje JavaCC, empate2.Jj. J Programa principal empate2,java. J Archivo EmpateZToken Manager.java. J Archivo TokenMgrError.java. 4 Archivo ParseException.java. J Archivo Token.java. 4 Archivo ASCII Charstream.java. J Archivo Empat&Constants.java. 5.4.2 Características a ser probadas Plan O1 Reconocimiento del patrón de diseño “abstractfacfovy”. Reconocimiento del patrón de diseño “composite”. Reconocimiento del patrón de diseño “iterator”. Reconocimiento de un patrón de diseño incorporado dentro de la estructura de otro patrón de diseño. Plan 02 Reconocimiento del patrón de diseño “sfrufegv”. Reconocimiento del patrón de diseño “template mefhod’. Reconocimiento de un patrón de diseño incorporado dentro de la estructura de otro patrón de diseño. 5.4.3 Características a no ser probadas Plan O1 y Plan 02 No se hará la prueba del reconocimiento estructural de otros patrones de diseño que no sean los que reconoce el sistema. No se realizará el reconocimiento de las directivas de pre-procesamiento excepto la directiva #include, en la compilación del código fuente. 53 EVALUACI~NEXPERIMENTAL Capítulo 5 5.4.4 Especificación de entrada Plan O1 y Plan 02 Interactivamente seleccionar el nombre del archivo que contiene la clase cliente del código a analizar y seleccionar el patrón de diseño a detectar. 5.4.5 Especificación de salida Plan O1 y Plan 02 El sistema desplegará cualquiera de los dos siguientes resultados de la búsqueda del patrón de diseño en la forma canónica del código fuente: 1. “PATRON ENCONTRADO”, desplegar los nombres de las clases que intervienen en el patrón de diseño. 2. “PATRON NO E N C O N T W O ’ , indicar las pautas a seguir para darle la forma o la estructura del patrón de diseño elegido para detectar en el código fuente analizado. 5.4.6 Identificación de pruebas Las pruebas se realizaron sobre tres conjuntos de programas de aplicación codificados en lenguaje C++: El primer conjunto de programas al que denominaremos “A” (ver anexo B), consta de programas bajados de internet utilizados para realizar el plan de pruebas del IPADICH [CAS99], en los que de antemano se sabe que fueron implementados bajo un patrón de diseño. Caso 1 2 3 Característica de Prueba Reconocimiento de patrones de diseño “abstract factory”, sobre el conjunto de programas “A”. Reconocimiento de patrones de diseño “composite”, sobre el conjunto de programas “A”. Reconocimiento de patrones de diseño “iterator”, sobre el conjunto de programas “A 11 54 Cauítulo 5 Caso 4 5 6 I 8 9 10 11 12 EVALUACI~NEXPERIMENTAL Plan O 1 Característica de Prueba Reconocimiento de patrones de diseño “abstractfactory”, sobre un programa que se sabe que incorpora el patrón de diseño “composite ”. Reconocimiento de patrones de diseño “abstractfactory ”, sobre un programa que se sabe que incorpora el patrón de diseño “iterator”. Reconocimiento de patrones de diseño “composite”, sobre un programa que se sabe que incorpora el patrón de diseño “abstractfactory”. Reconocimiento de patrones de diseño “composite”, sobre un programa que se sabe que incorpora el patrón de diseño “iterator”. Reconocimiento de patrones de diseño “iterator”, sobre un programa que se sabe que incorpora el patrón de diseño “abstractfactory”. Reconocimiento de patrones de diseño “iterator”, sobre un programa que se sabe que incorpora el patrón de diseño “composite ”. Reconocimiento de patrones de diseño “abstract factory”, sobre el conjunto de programas “B. Reconocimiento de patrones de diseño “composite”, sobre el conjunto de programas “B”. Reconocimiento de patrones de diseño “iterator”, sobre el conjunto de programas “R” ~~ 5.5 Resultados de las pruebas En el primer caso de prueba se ilustran los pasos seguidos y los resultados de ellos al evaluar la herramienta en busca del patrón de diseño; en los demás casos de prueba para no repetir todas las pantallas de la herramienta, únicamente se muestra la pantalla de resultados al buscar el patrón seleccionado en el código analizado. Los resultados obtenidos de cada caso de estudio se describen a continuación: 55 EVALUACI~NEXPERIMENTAL Capítulo 5 5.5.1 Caso de prueba 1 El primer caso se refiere a la detección del patrón de diseño abstractfactory en el código que corresponde a dicho patrón: 1. En la figura 5.1 se muestra la pantalla principal de la herramienta, esta pantalla contiene en el menú Archivo la opción Abrir. . ~ i ~ . ,.. .. ., __ ., ~~ .. ~ . ... ~~ .... . . - . .. . l Figura 5.1 Pantalla principal de la interfaz, mostrando opciones del menú Archivo. 2. Al dar clic en la opción Abrir del menú archivo aparece la ventana de diálogo que permite elegir el archivo que será analizado, figura 5.2. Figura 5.2 Ventana de diálogo para abrir archivo fuente. 56 Capítulo 5 EVALUACI~NEXPERIMENTAL 3. Una vez elegido el archivo a analizar el sistema obtiene su forma canónica y otros elementos de información del código como son las estructuras i f o switch, mostrándose esta información en el panel correspondiente en pantalla, figura 5.3. 4. Después de seleccionar el archivo a analizar, se elige el patrón de diseño a detectar en el código fuente. Desplegándose el resultado en el panel correspondiente, figura 5.4. En este caso, el patrón es encontrado y con ello se muestran los nombres de las clases del código que forman parte del patrón de diseño. Figura 5.4 Resultado de buscar el patrón de diseño ubstructfuctory 57 EVALUACI~NEXPERIMENTAL Capítulo 5 5.5.2 Caso de prueba 2 En el segundo caso de prueba se trató de reconocer el patrón de diseño composite en el código que contiene este patrón. El resultado de éste caso de prueba fue positivo, como se muestra li..a 5.5.3 Caso de prueba 3 En esta prueba se buscó el patrón de diseño iterator en el código que contiene a dicho patrón. El resultado de esta prueba fue positivo, como se muestra en la figura 5.6. 58 EVALUACI~NEXPERIMENTAL Capítulo 5 En el siguiente conjunto de pruebas se verificó la existencia de patrones de diseño en los códigos obtenidos de internet [CAS99], donde se buscó patrones de diseño para los cuales no fueron construidos estos códigos, con el fin de verificar el comportamiento de la herramienta. El resultado de estas pruebas se muestra a continuación. 5.5.4 Caso de prueba 4 En este caso de prueba, se buscó el patrón de diseño abstractfactory en el código que contiene al patrón de diseño composite. El resultado obtenido es que el código no posee relaciones del tipo ConcreteFactory, por lo tanto no se encuentra el patrón buscado, figura 5.7. I Figura 5.7'Resultado de buscar el patrón de diseño abstractfactory en el código del patrón composite 5.5.5 Caso de prueba 5 En el quinto caso de prueba, se busca el patrón de diseño abstractfactory en el código correspondiente al patrón de diseño iferator. Como se visualiza, el resultado es que el código no posee relaciones del tipo Producto ni ConcreteFactory, por lo que no se encuentra el patrón buscado, figura 5.8. 59 09 Capítulo 5 EVALUACI~NEXPERIMENTAL 5.5.7 Caso de prueba 7 En este caso de prueba, se busca el patrón de diseño composite en el código que corresponde al patrón de diseño iferator.El resultado se ilustra en la figura 5.1O, el código no posee el 5.5.8 Caso de prueba 8 En este caso de prueba se busca el patrón de diseño iterator en el código que corresponde al patrón de diseño abstructjiuctoy. El resultado se ilustra en la figura 5.11. l r,. ~qi ~ : ~-. ~ . ~1 ~ ~ ~ , . ~ i ; 3 1 ~ ~~ ~~~~ ~~~~ Figura 5.11 Resultado de buscar el patrón de diseño iterator en el código del patrón abstract factoly 61 Cauítulo 5 EVALUACI~NEXPERIMENTAL 5.5.9 Caso de prueba 9 En este caso de prueba se busca el patrón de diseño iterator en el código que corresponde al patrón de diseño composite. El resultado de la presente prueba se ilustra en la figura 5.12. El código no posee relaciones del tipo ConcreGAggregate por lo tanto la herramienta no encuentra el patrón buscado. Con el siguiente conjunto de pruebas se evalúa el comportamiento de la herramienta al verificar la existencia de los patrones de diseño en el código de la tesis de maestría [SAN941 tomada como prueba, esta no fue diseñada basándose en ningún patrón de diseño. 5.5.10 Caso de prueba 10 En este caso de prueba, se busca el patrón de diseño abstractfactory en el código de la tesis de maestría tomada como prueba. El resultado de tal evaluación se muestra en la figura 5.13, lo Único que le hace falta para encontrar el patrón son relaciones del tipo de fábricas concretas (Concrete-Factory), lo que indica que dicha tesis posee un diseño aceptable. 62 Figura 5.13 Resultado de buscar el patrón de diseño abstract factory en la tesis de maestría 5.5.11 Caso de prueba 11 En este caso de prueba se busca el patrón de diseño composite en el código de la tesis mencionada como caso de prueba. En la figura 5.14 se muestra el resultado de aplicar tal evaluación, como se visualiza no se encontró el patrón, debido a que el código analizado, no posee relaciones del tipo Composite. 4 1 t i .. - 'I t Figura 5.14 Resultado de buscar el patrón de diseño composite en la tesis de maestría 63 'sopeqnsai ap laued la ua s o p s a p sñ8aleils oyasip ap sauoqed ap oiauiyu [e apuodsauo:, B a j u ~ j ss e m ~ ~ t u p a se1 ap Iamd lap op!ua)uoj [a 'opeprue Y J I ! M S 0 4 epe3 iod B a j u r j s ogas!p ap u q w d un i!npu! apand as anb 'ipap apand as :o)ua!uiep!ue ap salayu sail ap s?ur u03 S,q3l!MS o SJI seinptu)sa uei)uan3ua as !s opueq!iaA 'sa opa 'opuez!~eue sisa as anb 08!pp lap o;ua!uiepoduroD le opiame ap opeilnsai la aua!iqo as eqatud ap ose3 aisa sa '9I 'sein8rj 'Baju.qs ogas!p ap sauoiied i!npu! iapod vied sepesa3au sasep se1 eilsanui eqanrd ap ose3 aisa ap opqnsai 13 .L%JVJJS seiq3wsa e i a ! 08!pq:, ~ ~ la anb 93snq as 'eqatud qsa u 2 eqanrd ap ose3 E I ~ S '[66SV31 laiualur ap sopeceq soS!po:, so[ ua ogas!p ap sauoiled solsa ue3snq as sose3 s!as calua!&!s so[ u 3 p o y j a u ajuiduaj sop opu&as la I( B a j u ~ j sseinptulsa oiauipd la :uaI(npu! anb '++3ua sopeluauraldq sewei8oid aiqos oyas!p ap sauoqed so1 ap olua!tu!oouo3ai 1" uapuodsauo3 sose3 sop soiaurud so1 'poyjaut ajuiduaj X B a i u ~ j sogas!p ap sauoqed so1 ap olua!urpouo3ai [a ienIeaa vied uoiez![eai as eqanrd ap sose3 saiua!@s so7 EVALUACI~NEXPERIMENTAL Capítulo 5 Fimra 5.16 Resultado de buscar el natrón de diseño .stratem 5.5.14 Caso de prueba 14 En este caso de prueba, se buscó en el código que contiene el patrón de diseño template method. El resultado de este caso de prueba es positivo como se ilustra en la figura 5.17. Figura 5.I 7 Resultado de buscar el patrón de diseño template method 65 I Ill 5.5.16 Caso de prueba 16 En esta prueba, se buscó el patrón de diseño strategy en el código que contiene el patrón de diseño iterator. El resultado de este caso de prueba se ilustra en la fi ura 5 19 . . ,, . , . . , . . ,~ . ; . ~ , , ~, . ; i . ~ ~ ~ ~ ~. .~ ~ ~ .. , . H f ' : ~~~ ~~~~ ~~~ , ~~~ ~~~ ~~ ~~~ *hudlr"".nmimO: roma i.n6nii~dslp*6nds~lirno Figura 5.19 Resultado de buscar el patrón de diseño strategy en el códieo del iterator 66 EVALUACI~NEXPERIMENTAL Capítulo 5 5.5.17 Caso de prueba 17 código que ilustra en la Figura 5.20 Resultado de buscar el patrón de diseño strategy en el código del comaosite 5.5.18 Caso de prueba 18 En el presente caso de prueba se evalúa la herramienta al buscar el patrón de diseño template method en el código correspondiente al patrón abstractafactory. En la figura 5.21 c P"mb* Aa*E,3ICION C<inrrnorecbm IOREO*CION C o n r i s M s t l o ~ IOREO*CIONIPrndY'~*OREOIClON IPrnd"noB. Canrrmsiridom HEREM i Figura 5.21 Resultado de buscar el patrón de diseño template method en el código del abstract factory. 67 . I EVALUACI~NEXPERIMENTAL Capítulo 5 el código 5.5.20 Caso de prueba 20 En este caso de prueba se evalúa la herramienta al buscar el patrón de diseño templute method en el código correspondiente al patrón composite. En la figura 5.23 se muestra el - ~ _., . .--y ',I -*I ~~~ ~ ~~~ ~~~~~ .' 1 ~ ~ ' ~~~ Figura 5.23 Resultado de buscar el patrón de diseño templute method en el código del composite. 68 . Capítulo 5 EVALUACI~NEXPERIMENTAL 5.6. Análisis de resultados Como se ilustra en los casos de prueba aplicados a la herramienta, el comportamiento de ella fue satisfactorio, ya que dio los resultados esperados de acuerdo al análisis manual realizado a cada uno de los códigos que se probaron. Estos resultados corresponden tanto a la obtención de la forma canónica del código fuente considerando la gramática completa del lenguaje C++, como a los resultados en la detección de los patrones de diseño, de los que se esperaba, como resultado que detectará el patrón de diseño buscado en códigos en los que si se encontraba el patrón presente, la no detección en cuando el código analizado no correspondía a alguno de ellos, aunque si informó que le faltaba para corresponder al patrón de diseño buscado. 69 Capítulo 6 CONCLUSIONES Capítulo 6 CONCLUSIONES Este capítulo esta dedicado a las conclusiones obtenidas en el desarrollo de esta tesis, se hacen comentarios acerca de los alcances logrados y se plantean algunos problemas no resueltos que pueden ser temas de investigación para trabajos futuros. 70 Capítulo 6 CONCLUSIONES 6.1 Conclusiones generales LOSpatrones de diseño capturan el razonamiento, atrás de soluciones probadas de Y discute el balance entre Sus altemativas. El USO de patrones de diseño se está fomentando en gran medida en la actualidad, y prueba de ello son 10s múltiples artículos mcontrados en la literatura, en 10s cuales se piantea la solución de problemas usando Pahones de diseño, sin embargo, la mayoría de herramientas actuales de ingeniería inversa todavía son negligentes en la recuperación del razonamiento de diseño. Como parte de esta tesis se.planteÓ ampliar los alcances del IPADIC++ mediante la implementación de la gramática completa del lenguaje C++, en la formulación del modelo canónico para representar las entidades de los programas escritos en C++. AI finalizar el trabajo de investigación se pudo comprobar la hipótesis planteada al inicio del trabajo. La implementación del reconocimiento de la gramática completa del lenguaje C++ en la herramienta que implementa el modelo canónico de representación de patrones de diseño, comprueba la hipótesis: Es posible la identificación automática de patrones de diseño en código fuente, de la sintaxis completa'del lenguaje C++, a travis de la implementación de un modelo de representación canónica tanto de los patrones de diseño como del código fuente a analizar. En particular para este trabajo de tesis se concluye que es posible la identificación automática de los, tres patrones de diseño implementados en el IPADIC++, adicionalmente se reconocen por comportamiento posibles strategy o template method de los patrones de diseño propuestos por.Erich Gamma [GAM951 en código fuente escrito en C++. De acuerdo'a las pruebas realizadas al sistema, se puede concluir que la herramienta compila los programas escritos en lenguaje C++ de acuerdo a la gramática completa de este lenguaje bajo el estándar ANSI-ISO, generando adecuadamente la forma canónica correspondiente al código fuente analizado y detecta adecuadamente los patrones de diseño en el código fuente. Detecta también cuando a un código le hacen falta relaciones para poder decir que corresponde a un patrón de diseño, y así mismo puede detectar la falta de patrones en el código, realizando tal detección en códigos fuente para los que se verifica la gramática completa del lenguaje C++. Para la evaluación se definieron 20 casos de pmeba y los 20 casos resultaron 100% correctos. Los casos de prueba se definieron para detectar un patrón completo, parte de un patrón, o la falta completa del patrón en el código. 6.2 Trabajos futuros El presente proyecto de investigación realizó una parte más al trabajo de investigación relacionado con patrones de diseño realizado en el área de Ingeniería de Software del cenidet, sin embargo, es necesario seguir trabajando en la misma línea de investigación para complementar esta investigación. Por lo que deben desarrollarse trabajos futuros, como es: En la implementación de los patrones de diseño planteados al inicio de esta tesis: factory method, strategy y template method, por cuestiones de análisis sintáctico , no se implemento en el sistema el reconocimiento del patrón de diseño factory method, 71 Capítulo 6 CONCLUSIONES quedando pendiente para futuros trabajos realizar las reglas gramaticales que realicen el reconocimiento de este patrón así como su implementación en la herramienta. En la implementación del reconocimiento de la gramática del lenguaje C++ para realizar la forma canónica del código fuente, se hace necesario incluir la implementación del reconocimiento de las directivas de pre-procesamiento para el lenguaje C++. Extender el sistema para la identificación de un mayor número de patrones del catálogo de Gamma et. al. [GAM95], que son importantes en el desarrollo y administración de marcos reusables de aplicaciones orientadas a objetos. Construir otro sistema que sea capaz de distinguir a patrones propios de un dominio de aplicaciones en particular. En la herramienta, las relaciones entre clases del código analizado y de los patrones de diseño se muestran en forma canónica y textual, se propone como un trabajo futuro el mostrar tales relaciones en alguna de las notaciones visuales, como por ejemplo UML, OMT, o BOOCH, lo que haría más fácil para el usuario la interpretación del resultado; ya que confrontaría de manera más legible y entendible el diseño del código analizado con la estructura de los patrones de diseño buscados. Que el sistema se extienda para que analice también código en otros lenguajes como Java, Visual Basic, Delphi, etc. A la fecha, la herramienta puede analizar código definido en uno o en varios archivos, con la restricción de que en un mismo archivo se declare e implemente la clase, se pretende a futuro eliminar tal restricción. 72 BIBLIOGRAFÍA [AHR95] Judith D. Ahrens, Noahs S. Prywes. “Transition to a legacy - and reuse Based Software Life Cycle”. IEEE computer, October 1995, pp. 27 - 36. [APP91] Doris Appleby.”Programming Languages. Paradigm and practice”. Ed McGrawHill. 1991,458 p. [BAN981 Jagdish Bansiya.”Automating Design-Pattern Identification”. Dr. Dobb’s Journal. http://www.ddi.cod.ddi/l998/1998-06/lead/lead.htm. June 1998. [BOS98] Jan Bosh. ”Design patterns as language constructs” University of KarlskronaRonneby, JOOP, mayo, 1998, pp. 18-25. [BR097] Brown, Kyle, “Design Reverse-Engineering and Automated Design Pattern Detection in Smalltalk”. Master Thesis. URL: http://www2.ncsu.ed~eos/info/tasug/kbrow~thesis2.htm, 1997 [BUD961 F.J. Budinsky, M.A. Finnie, J.M. Vlissides and P.S. Yu, ”Automatic code generation from design patterns”, IBM System Journal, Vol. 35, No. 2, 1996 - Object Technology. [BUR951 Margaret Burneti et al (eds). “Visual Object - Oriented programming” Concepts and environments. Manning Publications, 1995. [CAM971 Marcelo .Campo, Claudia Marcos and Alvaro Ortigosa. ”Framework comprehension and design patterns: a reverse engineering approach, in Proc. Of the 19Ih. Int. Conf. On Sofhvare Engineering, SEKE’97, Madrid, Spain, junio 1997. [CAS991 Félix Agustín Castro Espinosa. “Sistema de identificaión de patrones de diseño en código C++”. (Maestria en Ciencia en Ciencias Computacionales, Cuemavaca, Morelos: Cenidet, 1999), p.87. [CHAOO] Craig Chambers, Bill Hamson and John Vlissides. ”A debate on language and tool support for design patterns”, PLOPL 2000, Boston MA USA, ACM 2000. [COO981 James W. Cooper. “User Interfaces That Vary with Your Data”. Fawcette Technical Publications, junio/julio 1998 [FAY971 Fayad, M. E., Schmidt, D.C., and Johnson, R. E. ”Object-Oriented Application Frameworks: Problems and Perspectives”. Wiley, NY, 1997. - 73 [FAY971 Fayad, M. E., Schmidt, D.C., and Johnson, R. E. ”Object-Oriented Application Frameworks”. Communications of the ACM, Vol. 40, No. 10, October 1997, pp. 32-38. http://www.cs.unr.edu/-favad/frameworks, [email protected], [email protected] [FOS98] Ted Foster and Hiping Zhao. ”Modelig Transport Objects with Patterns” JOOP, enero de 1998. Pp. 26-32. [FOW99] Martin Fowler. Refactoring: Improving the Design of Existing Code. Addison-Wesley, 1999. [GAM951 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns Elements of Reusable Object-Oriented Software. Addison Wesley Professional Computing Series. 1995. [HOP931 John E. Hopcroft, Jeffrey D. Ullman Introducción a la teoría de automátas, lenguajes y computación Compañía Editorial Continental, S. A. De C.V. 1993. [JOH98] Johnson R. E. and Foote, B. Designing reusable classes, J. Object-Oriented programming. 1 , 5 (June/ July 1998).pp. 22-35. [KEL99] Rudolf K. Keller, Sébastien Robitaille, Reinhard Schauer and Patrick Pagé. ”Pattern- based reverse-engineering of design components”, Department IRO, Univesité de Montréal, ICSE ’99 Los Angeles CA, ACM 1999. pp.226-235 [KRA96] Christian Kramer, Lutz Prechelt. “Design Recovery by Automated Search for Structural Design Patterns in Object-Oriented Software”. Working Conference on Reverse Engineering, IEEE CS Press, Monterey CA, November 8-10, 1996. [MAR961 Robed, Martin. “the Open-Closed Principle”. C++ report, enero de 1996. [MIL951 Hafedh Mili, Fatma Mili y Ali Mili. “Reusing Software: Issues and Research Directions”. IEEE Transactions on Software Engineering, Vol. 21, No. 6, junio 1995. [MET--] Sitio de Metamata . “Javacc”. http://www.metamata.com/iavacc/ [NOV97] Gordon S. Novak Jr. “Software Reuse by Specialization of Generic Procedures through views”. IEEE Transactions on Software Engineering, vol. 23, No. 7, Julio de 1997. Pp. 401-417. [SPI97] Tom Spitzer, “Component Architectures DBMS”. September 1997, pp. 56 - 66. 74 [PRE95J Pree, w . (1995): Design Patterns Development, Addison-Wesley. [PRE98] Charles Rich and Linda M. Wills. ”Recognizing a programming design a graph-parsing approach”, Massachusetts Institute of Technology. IEEE Software, enero 1990. pp. 82-89 [RIC90]. Charles Rich and Linda M. Wills. ”Recognizing a programming design a graph-parsing approach”, Massachusetts Institute of Technology. IEEE Software, enero 1990. pp. 82-89 [SAN941 Rene Santaolaya Salgado, “Ambiente DE desarrollo para la programación visual de interfaces de usuario para monitoreo de procesos en línea”, Tesis de maestría, Morelos: Cenidet, mayo de 1994. [SAN991 Rene Santaolaya Salgado, “Sistema de administración de componentes de software basados en frameworks”, Proyecto 32042, Cuernavaca, Morelos: Cenidet, 1999. [SHU96] Forrest Shull, Walcélio Melo, and Victor Basili. “An Inductive Method for Discovering Design Patterns from Object-Oriented Software Systems”. Technical Report, University of Maryland, computer Science Depament, MD, 20742 USA. 1996. [THO951 Dave Thomas Component - Based Software Cosntrution: Making the Transition from Crafi to Engineering First Class the Magazine for Object Tecnology Professionals February / march 1995, pp. 12 - 13. [VIS961 Sreenivasa Viswanadha. “C++ grammar”. for Object-Oriented Software http//falconet.inria.fr/Indexof/java/tools/JavaCC/examples/CandCPLUSPLU S/, Sun Microsystems Inc. [WAT97] Sadakazu Watanabe. “Profesionalism through O 0 and Reuse”. IEEE january 1997. 75 Anexo A PATRONES DE DISEÑO RECONOCIDOS EN LA TESIS En este apéndice se muestra la información referente a los patrones de diseño reconocidos en la tesis. La estructura de los patrones se ilustra en la notación OMT. 16 Patrón de diseño Abstract Factory La intención del patrón abstract factrory es proporcionar una interface para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. La estructura del patrón abstractfactory se muestra en la figura A. 1. Cliente 1 Fabricacancreta1 I I I I I I I I I I I I I t ________ I La forma canónica del patrón de diseño abstract factory obtenida al aplicar el modelo canónico para representación de patrones de diseño es la siguiente: '%lient ACQUAINTANCE apa ACQUAINTANCE af; af; cfl HEREDA af CREATES pa, apa, p a l HEREDA apa" 77 Patrón de diseño Composite La intención del patrón de diseño composite es componer objetos en estructuras de árbol para representar jerarquías de partes completas. Composite le permite a los clientes tratar objetos individuales y composiciones de objetos uniformemente. La estructura del patrón composite se muestra en la figura A.2. I I Composite ~ Figura A.2. Estructura del patrón de' diseño composite La forma canónica del patrón de diseño composite obtenida al aplicar el modelo canónico para representación de patrones de diseño es la siguiente: '%lientACQUAINTANCE Component, Component, Leaf HEREDA Component, Composite HEREDA Component AGREGACION Component[n] " 78 Patrón de diseño Iterator La intención del patrón de diseño iterator es proporcionar ia forma de acceder a los elementos de un objeto agregado secuencialmente sin exponer su representación subyacente. La estructura del patrón iterator se muestra en la figura A.3. F * Aggregate I I * I I Figura A.3. Estructura del patrón de diseño iterator La forma canónica del patrón de diseño iterator obtenida al aplicar el modelo canónico para representación de patrones de diseño es la siguiente: "Aggregate, ConcreteAggregate HEREDA Aggregate CREATES Concretelterator, Iterator, ConcreteIterator HEREDA Iterator ACQUAINTANCE ConcreteAggregate 'I 79 Patr,.i de diseño Factory Method La intención del patrónfactory method es definir una interface para crear objetos, pero deja que las subclases decidan cual clase instanciar. Factory method deja a la clase diferir instanciación a subclases. La estructura del patrónfactory method se muestra en la figura A.4. FactoryMethodO Anoperation()* ...._.__ ............ ............ Product = FactoryMethod() FactoryMethod() 0.'.' ~ ~ ' ' ' ' 'Return ~''~ new ConcreteProduct Figura A.4 Estructura del patrón de diseñofactory method La forma canónica del patrón de diseño factory method obtenida al aplicar el modelo canónico para representación de patrones de diseño es la siguiente: 'Creator, Product, ConcreteCreator HEREDA Creator CREATES ConcreteProduct, ConcreteProduct HEREDA Product" 80 Patrón de diseño Strategy La intención del patrón strategy es definir una familia de algoritmos, encapsula cada uno y los hace intercambiables. Strategy, deja que los algoritmos varíen independientemente de los clientes que los utilizan. La estructura del patrón strategy se muestra en la figura A S . ~ Context Contextlnteríace() 3 ConcreteStrategyA AlgorimiInterface() Strategy Algonmilnterfaz() ConcreteStrategyB AlgonmiInterface() ConcreteStrategyC Algontmlnterface() La forma canónica del patrón de diseño strategy obtenida al aplicar el modelo canónico para representación de patrones de diseño es la siguiente: 'Litrategy, Context AGREGACION Strategy, ConcreteStrategy HEREDA Strategy" 81 Patrón de diseño Template Method La intención del patrón template method es definir el esqueleto de un algoritmo en una operación, difiriendo algunos pasos a cada subclase cliente. Deja que las subclases redefinan ciertos pasos de un algoritmo sin cambiar la estructura del algoritmo. La estructura del patrón template method se muestra en la figura A.6 PrimitiveOperation2() PrimitiveOperationl() PrimitiveOperation2() f I PnmitiveOperation 1() PrimitiveOperation2() Figura A.6 Estructura del patrón de diseño template method La forma canónica del patrón de diseño template method obtenida al aplicar el modelo canónico para representación de patrones de diseño es la siguiente: " Abstractclass, ConcreteClass HEREDA Abstract Class " 82 , . Anexo B Códigos utilizados en la evaluación extirimental En este apéndice se muestran los archivos utilizados en la evaluación experimental, en algunos de estos códigos se implementaron los patrones de diseño reconocidos en esta tesis. 83 Código correspondiente al patrón Composite [CAS99]. /I*** Clase Component #include <iostream.h> class Component{ public: Component(){-next= NULL;} virtual void operation(void) = O; Component* getchild(void) const (return -next;) virtual void setchild(Component* next) ( n e x t = next;} virtual int compositeDetect() {retum(O);} private: Component* n e x t ; 1; /I** Clase Composite #include "component.hpp" class Composite: public Component( public: Composite(int id)(-first = NULL; -identification = id;) virtual void add(Component*); virtual void removeLeaf(Component*); virtual void removeComposite(Component*); virtual void operation(void); void operation(Component*); virtual int compositeDetectO(retum(1);) private: int -identification; Component* -first; 1; void Composite::add(Component* c) { c-setchildCfirst);//***************verificar -fust = c; I void Composite::removeLeaf(Component*c) { Component *t; iKfirst =c){ -first = c-getchild(); c-setchild(0); 1 else{ for(t =-first; t; t = t-getchild()){ if(t-getchild() = c) break; 84 .. . .... void Composite::removeComposite(Component* c){ Component *t, *tnext; if(c-compositeDetect()) { for(t=((Composite *)c),first; t; t=inext)( tnext = t-getchild(); t-setchild(0); ) ((Composite *)c)l-first = O; 1 void Composite::operation(void) { if(_first) cout«"Composite: "«identification«endl; 1 void Composite::operation(Component* c) { static int level =O; Component "t; for(int i=O; ¡<level; i+)( COUf<<" I,; ) c-operationo; if(c-compositeDetect){ level++; for(t=((Composite *)c)--first; t; t=t-getchild()) { operation(t); 1 level-; //*** Clase Leaf #include "component.hpp" class Leaf: public Component{ public: Leaf(int id){-identification = i&) virtual void cperation(void) { cout<<"Leaf: "« -identification«endl;) private: int -identification; }; //**Clase Cliente #include "leaf.hpp" #include "composite.cpp" int main(void){ libreria a; libreria *y; Leaf 11 =new Leaf(-I); Leaf 12 = new Leaf(-2); Leaf 13 = new Leaf(-3); Leaf 14 =new Leaf(-4); 85 . . Leaf LI =new Leaf(1); Leaf L2 = new Leaf(2); Leaf L3 = new Leaf(3); Leaf L4 = new Leaf(4); Composite c l =new Composite(1); Composite c2 =new Composite(2); Composite c3 = new Composite(3); c 1.add(&ll); cl.add(&IZ); c2.add(&13); c2.add(&14); c3.add(&Ll); c3.add(&L2); cZ.add(&L3); cZ.add(&cl); c3.add(&c2); c3.operation(&c3); tout<<" 11; c2.removeLeaf(&14); c3.add(&14); c3.operation(&c3); tout<< I t "; c2.removeComposite(&c I); c3.operation(&c3); retum(0); 1 86 Código correspondiente al patrón Abstract Factory [CAS99]. /I***Clase cliente #include "d:\hodl\\ConcFacl .HPP" #include "d:\hodl\\ConcFac2.HPP" #include "d\\modl\\AProdA.HPP" #include "d:\\modl\WrodB.HPP void main0 { ConcreteFactoryl Factory0 = new ConcreteFactoryl(0); FactoryO.Prt0; AProductoA ProdAO; ProdAO = FactoryO.CreateProductoA(0); ProdAO.Prt(); AProductoB ProdBO; ProdBO = FactoryOCreateProductoB(0); ProdBO.Prt(); ll(FactoryO.CreateProductA(0))->Prt(); //(FactoryO.CreateProductB(O))->Prt(); ConcreteFactory2 Factoryl =new ConcreteFactory2(1); Factoryl .Prt(); AProductoA ProdAl; ProdAl = Factoryl .CreateProductoA(l); ProdAl.Prt(); AProductoB ProdB 1 ; ProdBl = Factoryl.CreateProductoB(I); ProdBl .Prt(); //(Factory 1.CreateProductA(l))->Prt(); //(Factory 1.CreateProductB( 1))->Prt(); } /I Termina Main. /I** Clase AbsiractFactory #ifndef A-Factory #define A-Factory class AProductoA; class AProductoB; class AbstractFactory { public: AbstractFactoryO { /I Vacia ... }; // Termina constructor de la clase virtual AProductoA *CreateProductA(int) = O; virtual AProductoB *CreateProductB(int) = O; }; // Termina clase AbsiractFactov. #endif 87 I ! /I*** Clase AproductoA #ifndef A-Producto-A #define A-Producto-A class AProductoA { public: AProductoA() { I/ Vacía ... ); //Termina constructor de la clase virtual void Prto = O; ); I/ Termina.AProductoA. #endif /I*** Clase AproductoB #ifndef A-Producto-B #define A-Producto-B class AProductoB { public: AProductoBO ( // Vacía ... }; // Termina constructor de la clase virtual void Prt() = O; ); // Termina AProductoB. #endif Clase ConcreteFactoryl #ifndef C-Factory1 #define C-Factory1 //*e* . #include <iostream.h> #include "d\imodl\MbsFact.HPP" #include "d:\\modl\\CProdAO.HPP" #include "d:\imodl\\CProdBO.HPP" class ConcreteFactoryl: public AbstractFactoiy . { private: int Identificacion; public: ConcreteFactoryl(int ID) (Identificacion = ID; ); // Termina constructor virtual AProductoA *CreateProductA(int); virtual AProductoB *CreateProductB(int); virtual void Prt(void) { cout << "ConcreteFactoryl: " << Identificacion << endl; ) // Termina la función Prt. 1; AProductoA *ConcreteFactory 1::CreateProductA(int I) ( retum(new CProductoAO(1)); ) // Termina CreateProductA. AProductoB "ConcreteFactory 1::CreateProductB(int I) { retum(new CProductoBO(1)); ) // Termina CreateProductB. #endif 88 //*** Clase ConcreteFactory2 #ifndef C-Factory2 #define C-Factory2 #include <iostream.h> #include "d\hodl\\AbsFact.HPP" #include "d:\hodl\\CProdA 1 .HPP" #include "d\hodl\\CProdB I .HPP" class ConcreteFactory2: public AbstractFactory { private: int Identificacion; public: ConcreteFactory2(int ID) { Identificacion = ID; }; I/ Termina constructo1 virtual AProductoA *CreateProductA(int); virtual AProductoB 'CreateProductBfint); virtual void Prt(void) { cout << "ConcreteFactory2: " << Identificacion << endl; } /I Termina,la función Prt. }; AProductoA *ConcreteFactory2::CreateProductA(int I) { return(new CProductoAl(1)); } /I Termina CreateProductA. AProductoB *ConcreteFactory2::CreateProductB(int I) { return(new CProductoBl(1)); } 11 Termina CreateProductB. #endif /I*** Clase CProductoAO #ifndef C-Producto-A0 #define CProductoAO #include "d:\hodl\WrodA.HPP" class CProductoAO: public AProductoA { .private: int -1; public: CProductoAO(int I) { -1 =I; }; I/ Termina constructoi virtual void Prt() ( cout << "ProductoAO: " << -1 << endl; 1; }; I1 Termina CProductoAO. #endif /I*** Clase CProductoAl #ifndef C-Producto-A 1 #define CProducto-A I #include "d:\hodl\\AProdA.HPP" class CProductoAl: public AProductoA { 89 I I I private: int -1; public: CProductoAl(int I) { -1 =I; }; /I Termina consmictor virtual void Prt() { cout << "ProductoAl : " << -1 << endl; 1; }; /I Termina CProductoAl #endif I/*** Clase CProductoBO #ihdef CProducto-BO #define C-Producto-BO #include "d\\modl\\AProdB.HPP" class CProductoBO: public AProductoB { private: int -1; public: CProductoBO(int I) { -1 - = I; }; //Termina constructor virtual void Prt() { cout << "ProductoBO: " << -1 << endl; }; // Termina CProductoBO. #endif //*** Clase CproductoBl #ihdef C P r o d u c t o B 1 #define C-Producto-B 1 #include "d:\imodl\\AProdB.HPP class CProductoB I: public AProductoB { private: int -1, public: CProductoBl(int I) { -1 = I; }; /I Termina consmictor virtual void Prt() ( cout << "ProductoBi: " << -1 << end& 1 f ; I/ Termina CProductoBl #endif 90 Código correspondiente al patrón Iterator [CAS99]. I/*** Clase Iterator template <class T> class Iterator{ public: virtual AggregateEntryQ* first() =O; virtual AggregateEntryQ* next() = O; virtual int isDone() = O; virtual T currentItem() = O; 1; /I*** Clase ConcreteIterator #include "d\\cmm\\patrones\\iterator\\Iterator.hpp" template <class T> class ConcreteIterator : public Iterato-( public: ConcreteIterator(ConcreteAggregate<T>*); virtual AggregateEntryQ* first(); virtual AggregateEnhycT>* next(); virtual int isDone(); virtual T currentItem0; private: ConcreteAggregate<D* -aggregate; 1; /I*** Clase Aggregate #include<iostream.h> #include<string.h> #include<assert.h> template <class T>class Iterator; template <class T x l a s s ConcreteIterator; template <class Dclass ConcreteAggregate; template <class 'D class Aggregate{ friend class ConcreteIteratofiP, public: virtual I t e r a t o e * createIterator() const = O; 11... ); template <class 'P class AggregateEntry{ friend class ConcreteAggregateQ; friend class ConcreteIteratofiT>; public: AggregateEntry(T value, AggregateEntry<T> *item){ val = value; n e x t = item;} T ietvaiueo {returncvai);) ~~ ~ private: 91 T -val; AggregateEntry- 'next; 1; /I*** Clase ConcreteAggregate #include "d:\\cmm\\patrones\\¡terator\\Aggregate.hpp" template <class D class ConcreteAggregate : public Aggregate-{ friend class Concretelterator<T>; public: ConcreteAggregate() (aggregateEntry =-tail -ConcreteAggregate() (remove();) = O;) void insert(T); void append(T); void remove(); int remove(T); int length(); virtual I t e r a t o m * createherator() {retum(new ConcreteIterator());} private: AggregateEntry-* aggregateEnhy; AggregateEntryO* t a i l ; 92 Código correspondiente a la tesis de maestría [SAN94]. //El archivo se nombra "SAW.CPP" (Sistema Administrador de ventmas), #include <graphics.h> #include <bios.hz #include "c:\kene\\pantallaI.Cpp"// "Pantalla" es una clase derivada de la clase "Lista". int Tecla; int gdnver = DETECT, gmode, errorcode; void Setup(); // Menf principal. void Edo-SysW(); /¡Menu principal, void Edo-ASysW(); void EdoCreaWO; void EdoACreaWO; void Edo-EditWO; void Edo-DragW(); void Edo-ASysW(); void Edo-CreaSg(); void Edo-ACreaSg(); void Edo-Fin(); . main() { // RUTINA PRINCIPAL. initgraph(&gdriver,&gmode,"C:\\TC\\BGI"); // modificado por gfm (directono de egavga.bgi) errorcode = graphresult(); if (errorcode != grOk) { pnntf ("Error grafico: %sW',grapherrormsg(errorcode)); printf ("presiona una tecla para continuar: "); getch(); exit( I); ) // if errorcode. Pantalla Scr; ScrSetUpO; closegraph(); // Aqui regresa a modo texto .... return O; ) // MM. I* #ifndef La-Pantalla #define La-Pantalla #include<bios.h> #include<fstream.h> #inclnde<math.h> #include "c:\\rene\kegmentol .cpp" #include "c:\\rene\\Mennsl .CPP" //Definiciones de la clase mouse. #include "c:\\rene\iMousel.CPP" #include "c:\kene\\Cola 1.CPP" #include "c:\\rene\\Listal .CPP" extern Objeto V; class.Pantalla: public Lista { private: unsigned Minx, MinY, MaxX, MaxY, MinWX, MinWY, MaxWX, MaxWY; unsignedC1, TamX, TamY, NH, NV; Menus Laspaletas, PaletasGrafs; Boolean in-Area(unsigned Pxl, unsigned Pyl, unsigned Px2, unsigned Py2, *I 93 unsigned Qxi, unsigned Qyl, unsigned Qx2, unsigned Qy2); void SetGraTendík void AddRes(); void DecRes(); protected: public: ClassMouse Mouse; int Mx,MY; // Guardan la posici$n actual de las coordenadas de] M ~ ~ ~ PantaMunsigned NumV = 4, unsigned NumH = 3, unsigned Claro = 8) ( static Nodo *Apt; Minx = O; MaxX = getmaxxo; MinY = O; MaxY = getmaxy(); MinWX= MinX+ScrXI; MaxWX= MaxX-ScrX2; MinWY= MinY+ScrYI; MaxWY= MaxY-ScrY2; NH = NumH; NV = NumV, CI = Claro; TamX = ((MaxWX-MinWX)+I -((NV+I)*CI))/Nv, TamY = ((MaxWY-MinWY)+ I -((NH+i)*Cl))/”; Apt = NULL; Mouse.lni(O,O,getmaxx(),getmaxy()); } I/ Constructor de la clase Pantalla. -Pantalla() ( } /I destructor Boolean Vacia(); /I Funci$n que verifica la existencia de al menos una ventana. void Set-Val(unsigned NumV = 4, unsigned NumH = 3, unsigned Claro= 8); I/ Set-Val. 11 Set-Actual. virtual void Set-Actual(); void Set-Coord(unsigned x l , unsigned yl, unsigned x2, unsigned y2,Nodo *N); void Desply(); I/ Desply. void Refresca(); /I Refresca. void Crea-V(unsigned X I , unsigned yl, unsigned x2, unsigned y2); /I Crea objeto de clase Ventana. void Crea-V(); /I Crea objeto de clase Ventana. indicado. void Get-Obj(Nodo *N); I/ Obtiene la E. de D. del nodo void Dibuja-Obj(Nodo *N); /I Dibuja el objeto indicado. void Abre-Obj(Nodo *N); 11 Abre al objeto indicado. void Close-Obj(cbar *K); I/ Cierra el objeto indicado. /I Funcién de arrastre de ventanas. void Drag-V(); void Move-V(cbar *K); // Reubica la ventana indicada. void Expand-V(char *K); /I Expande la ventana indicada. void Contrae-V(char *K); 11 Contrae la ventana indicada. void Set-C(char *K); // Ubica el cursor en la posici$n indicada. void ONC(); /I Hace visible el cursor del mouse. void OFFC(); /I Oculta el cursor del mouse. Nodo *GetBoton(unsigned Px, unsigned Py); 11 Obtiene el bot$n apuntado porel Mouse. 11 Funci$n de ayuda del estado Setup. void A-StUp(); void ACreaWO; I/ Funci#n de ayuda del estado CreaW. void -rag(); /I Funci$n de ayuda del estado Drag. 11 Funci$n de arranque del controlador de di logo. void SetUpO; 11 Funcién de creacign de ventanas. void CreaW(); 11 Funci$n para almacenar en disco una pantalla. void SaveSO; /I Funcign para editar una ventana. void EditWo; 11 funcign para redimensionar el area de una ventana. void ReSizeW(); I/ Funci$n para recuperar desde disco una ventana. void Restores(); 11 Func$n para asociar una variable a una gr fica. void SetVarW(); 11 Funci$n para arrastrar por la pantalla una ventana. void DragW(); 11 Funci$n para reacomodar en mosaico una pantalla. void Layoutso; // Funci$n para refiescar una pantalla. void RefresbS(); I/ Funci$n para asociar una gr fica de monitoreo a una ventana. Nodo *SetSegWo; \,I ~ . , 94 ..<. void ONOFF-C(); // Funcién para prender o apagar el cursor. void DelW(); I/ Funcién para borrar una ventana, void FIN(); /I Funcién de fin de la sesi$n. void Save-Scr(Pantalla Obj); // Save-Scr. ' void Restore-Scr(Pantalla Obj); // Restore-Scr. //friend ostream &operator << (ostream &Str, Pantalla Scr); //friend istream &operator >> (istream &Su, Pantalla &Scr); ) ; I /termina la clase Pantalla. unsigned ContW = O; unsigned Cx, Cy, ColorN, ColorXOR; I/ Variables globales para actualizar al objeto Px de clase Pix I* // archivo "Segmento.HPP". #ifndef Segmentos.HPP #define Segmentos.HrP #include <graphics.h> #include "c:\\rene\iDbLstl .CPP" #include "c:\kene\Wodol . C P P */ class Segmento [ private: Wxl, Wyi, Wx2, Wy2,Vxl, Vyl, Vx2, Vy2, NumW, UT, Time-Refr; unsigned Boolean Visible; Nodo*Din; DbLst Fix; public: Segmento(unsigned XI = O, unsigned Y 1 = O, unsigned X2 = getrnaxxo, unsigned Y2 = getmaxy0, unsigned Q = O); // Constructor. 11 Destructor. virtual -Segmento(); // Agrega. void Agregapiodo *N); // Agrega. void Agregapiodo *Frst, unsigned); I/ SMM. void SMM(); void Smm(); I/ Smm. void Actualiza(); >, // Actualiza. I/ Visual-ON. void Visual-ON(); /I Visual-OFF. void VisualOFFO; // Redibuja todo el segmento. void Redraw(); float GetXI(); float G e m ( ) ; float GetY I(); float GetY2(); unsigned GetXpvLO; unsigned GetXpvRO; unsigned GetYpvTO; unsigned GetYpvBO; void SetXl(unsigned VarX); void SetX2(unsigned VarX); void SetYi(unsigned Vary); void SetY2(unsigned Vary); void SetXpvL(unsigned VarX); void SetXpvR(unsigned VarX); void SetYpvT(unsigned Vary); void SetYpvBfunsigned Vary); }; /I Termina la clase Segmento. #endif 95 Código correspondiente al archivo prueIfAn.cpp, para evaluar el patrón de diseño strategy. //archivo prueIfAn cpp int a=l, b=l, c=l, d=l, e=l, 6 1 , g=l, h=l, j=i, k=l, i=o; int main(void){ if(4 { cout<<"probando"; cout<<"if( a)"<<"h"; I else if(b) { while (i<=4) {cout<<''["<<i<<''] "; i t t ; } if(c) cout«"probando if(c) h"; if(d) cout«"probando if(d) ui"; cout«"esta en if(b), paso if(c), salio de if(d)"; 1 else if(e) { i=O; while(i<=3) {cout<<"["<<i<<"]"; i++;} if(0 cout«"probando if(f)"; cout<<"esta en if(e), paso while, salio de if(0"; I i=O; do cout<<"["<<i<<"] " ; itt; }while(i<=3); if(g) cout<<"probando if(g)"; else if(h) cout<<"probando if(h)"; else if(i) cout<<"probando if(i)"; else ifíj) cout<<"probando ifíj)"; else if(k) cout<<"probando if(k)"; else cout«"probando else de if(k)"; retum(0); I ........................................................................ 96 Código correspondiente al patrón Template method. // archivo prueTM.cpp. #include ciostream.h> #include cstring.h> class ordenamiento ( int array[iO] ; public: void inicia ( 1 ; void leer ( 1 ; virtual void ordenar0 = O ; void imprimir( ) ; //otro template void TM2 0 ; voAd opPriml() ; virtual void 0pPrim2 ( ) = O ; void opPrim3 O ; ) ; //fin clase ordenamiento void ordenamiento::iniciaO( leer0; ordenar ( ) ; imprimir ( ) ; I void ordenamiento::leerO[ int i=O; for (i=o; i<io; i++)[ coutcc"\n,["c<i< < " I " ; tin>> array[il ; 1 1 void ordenamiento::imprimirO[ int i=O; for (i=O; i<10; i++) cout<<'l\n[r'cci <<"I " < c array[il ; I void ordenamiento:: TM2 ( ) { opPrim1.I) ; opPrim2 O ; opPrim3 ( ) ; 1 void ordenamiento::opPrimlO( cout<c" operacion primitiva 1"; ) void ordenamiento::opPrim30( coutc<" operacion primitiva 2 " ; I class burbuja:public.ordenamiento( public: void ordenar ( ) ; void opPrim2 ( ) ; } ; //€in clase burbuja void burbuja: :ordenar0 ( int i, j, aux; c o u t < < " ~ RBIJRBUJA'~; ~. 97 ' for (i=ü; i<g; i++) ( aux=array[il ; for(j=i+i; j < l O ; j++)' if (array[i]>array[j])( aux=array [il ; arrav[il= arraviil; void burbuja: :opPrim2O ( tout<<" operacion primitiva ) 2 de burbuja"; class shel1:public ordenamiento{ public: void ordenar ( ) ; void opPrim2 ( 1 ; ) ; //fin clase shell void shel1::ordenarO { int aux=lO; Coutcc'aORD.SHELL Prueba" ccaux; void shell : : 0pPrim2 ( ) [ tout<<" operacion primitiva 2 de shell"; class norma1:public ordenamiento[ public: , void ordenar0 ; void opPrim2 ( ) ; ) ; //fin clase normal void norma1::ordenarO { int aux=lO; COutc<"ORD. NORMAL Prueba" c<aux; ) void normal : :opPrim2( ) [ coutc<" operacion primitiva 2 de normal"; main0 ( char opcion='x'; while (opcion ! = ' s o ) ( coutcc"e1ije ordenamiento:\n"; cout<<"a) burbuja\n"; cout<<"b) shell\n"; tout< c c ) normal\n"; cout<< s ) salir\n" ; cinzzopcion; if (option=='a') burbuja ord; else if (opcion=='b')shell ord; else if (opcion=='c')normal ord; else if (opcion=='s')return(0); else coutcc"debes teclear: a, b, c O s.\n"; ord.inicia(); ) //fin while coutc c " * * * * * * PROBANDO SWITCH * * * * * * \n '' : opcion='x'; I' '( 98 while íopcion ! = ' s ' l ( coutcc"e1ije operación prim. 2:\nl'; cout<< a ) burbuja\n " ; coutcc"b1 shell\n"; coutcc"c1 normal\n,'; cout<c"sl salir\n"; cin>>opcion; switch (opcion]( case ,'a': burbuja ord; break; case 'b': shell ord; break; case ',ct : n o n a 1 ord; break; case ' s ' : return ( 0 1 ; default: coutcc"debec teclear: a, b, c ó c . . .\n"; ) //switch ord.opPrirn20; ) //fin while return ( 0 1 ; I' //€in main0 99 Anexo C FUNCIONAMIENTO DEL SISTEMA Como se mencionó en el capítulo 4 la interfaz del sistema tiene un menú que cuenta con tres opciones, en este anexo se muestran las pantallas correspondientes a las opciones de menú y se describe el funcionamiento de la interfaz del sistema. 1O0 El menú consta de tres opciones principales que son Archivo, Detección y Ayuda. El menú de Archivo mostrado en la figura C.1, es para el manejo de archivos escritos en lenguaje C++, tiene las opciones de Abrir, Cerrar y Salir. Forma canónica de código fuente Abrir Salir i .ir; Cerrar ..~-~-.- .- t L i i :, Figura C. 1 Opciones del menú Archivo AI elegir la opción Abrir del menú de Archivo se muestra una ventana de diálogo, figura C.2, donde se elige el archivo a analizar. El archivo se analiza y además, se tiene un seguimiento de todos los archivos que forman parte del código.fuente, mediante el uso de la directiva de pre-procesamiento #include, para juntar el contenido de todos los archivos en un sololistado. Figura C.2 Ventana de diálogo para seleccionar archivo con extensión cpp A continuación, se muestra el listado de los archivos que forman parte del código fuente, la forma canónica del código fuente, las estructuras ifanidadas con más de tres niveles o switch con más de tres casos, en caso de que los haya, los métodos plantilla de las funciones en caso de que haya alguno en las áreas de texto correspondientes. Se activa la opción Detección del menú principal permitiendo seleccionar el patrón de diseño a detectar en el archivo elegido, figura C.3. 101 IIAWHNO: C z p a t r o n e s ~ s t r a c t F a c t o ~ , ~ ~ #include "c:iipatmnesiv\bstractFacto~iCon< Métodos Plantilla en clases Resultado de la detección Figura C.3 Contenido de paneles después de elegir el archivo a analizar En caso de que se elija un archivo que contenga errores sintácticos, el analizador sintáctico de la gramática del lenguaje C++ muestra el error correspondiente en el panel de forma canónica del código fuente, figura C.4. Archivo 1 Deieccion Ayuda Código fuente Forma canónica de códiuo fuente Rela UARCHIVO: CIpruebaslord-sw.cpp #Include 4ostream.hz #include <string.hi. class ordenamiento ( public: array[l O]; public: void ieero; virtual void ordenarO=O; void imprimiro; 1; Ilfin clase ordenamiento Figura C.4 Contenido de panel de forma canónica del código fuente si hay error sintáctico en el archivo analizado. 102 Una vez que se elige el patrón de diseño a detectar en el código fuente, se realiza la detección y se muestran los resultados en las áreas de texto correspondientes, figura C.5 Arch% Mesdon A m a Forma canónica de Lód1mfUenie Relaciones del cód can lib Figura C.5 Pantalla resultante al elegir un patrón de diseño a detectar El menú de Detección es para elegir el patrón de diseño a buscar en el código seleccionado previamente con la opción Abrir del menú Archivo. En esta opción se clasifican de acuerdo al catálogo de Gamma, cada uno de los patrones de diseño por medio de tres submenús ilustrados en las figuras C.6, C. 7 y C.8. "archivi\ P. Estructurales #include class Component( public: ComponentOLnext EJ"L;) Figura C. 6 Submenú para patrones creacionales del menú detección 103 ComponentO(-next = NULL;) Figura C. 7 Submenú para patrones de comportamiento del menú detección /ICódigo $1 P. - Forma canónica de códiao fuente P. Comporiamiento b komponent, prueba1 AGREGACION Leaflnl ~GREGACION~ompiisite[nl,Component ~CCCIUAINTANCE Conmonent. comnosite l~cipy;,;omponent{ Camponento(-next= Figura C.8 Submenú para patrones estructurales del menú detección El menú de Ayuda contiene tres opciones mostradas en la figura C.9, cada una de estas opciones despliegan una ventana de diálogo que muestra información acerca del sistema y de los patrones de diseño (figuras C.10, C.11 y C.12). Forma canónica de código fuente Figura C.9 Opciones del menú ayuda ! 104 I /\Esta herramienta realiza la detección de Patrones de Diseno en código fuente escrito en C++. Debes elegir primero la opción abrir del menu Archivo para seleccionar el código fuente a analizar Visualizarás en pantalla dentro del área de texto correspondiente el código fuente y su forma canónica posteriormente puedes elegir el patrón de diseño que desees detectar en el código fuente, eligiéndolo de los submenus correspondientes en el menu Detección; si deseas analizar otro código fuente cierra el código fuente activo con la opción cerrar del menu Archivo lroi(l ........... il .~ Figura.C.10 Ventana de diálogo de contenido del sistema Un patrón de diseño nombra, abstrae e identifica ¡os aspectos clave de una estructura común de diseño que la hace útil para crear un diseño orientado a objetos reusable. El patrón de diseño identifica las clases participantes y sus instancias, sus funciones y colaboraciones y la distribución de sus il responsabilidades. .......... . . . 1 . Figura C.11 Ventana de diálogo de patrones de diseño CENTRO NACIONAL DE INVESTIGACiÓN Y DESARROLLO TECNOLÓGICO Herramienta para detección de patrones de diseño en código fuente C++ Elaborado por: L.I. Patricia Zavaleta Carrillo Maestría en Ciencias en Ciencias Computacionales It ........... ,. Figura C.12 Ventana de diálogo de Acerca de ... 105'