Reglas y control de calidad automatizado para el lenguaje Vensim
Abstract
Grado en Ingeniería Informática
Full text
Universidad de Valladolid ESCUELA DE INGENIER´ IA INFORM´ ATICA GRADO EN INGENIER´ IA INFORM ´ ATICA Menci´on en Ingenier´ıa del Software Reglas y control de calidad automatizado para el lenguaje Vensim Alumno: Juan Herruzo Herrero Tutora: Yania Crespo Gonz´alez-Carvajal
A mi padre, por haber sido el mejor modelo a seguir. I
II
AGRADECIMIENTOS Agradecimientos A mis padres y familia, por haberme apoyado y cuidado durante tantos a˜nos, sin ellos no habr´ıa llegado a donde estoy ahora. A mi novia, por haberme ayudado en cualquier momento aunque estuviese diluviando o granizando y haberme empujado a seguir d´ıa a d´ıa. Gracias por toda esa confianza que me has dado. A mis amigos, por estar siempre para quedar y hablar. A mi tutora, Yania Crespo, por haberme ayudado tanto y guiarme en este proyecto. A mi compa˜nero veterano Daniel Bazaco, por el gran trabajo que hizo en el plugin inicial y por ofrecerme su ayuda durante el transcurso del proyecto. Y al resto de la universidad por haberme dado una gran calidad de ense˜nanza la cual he podido aprovechar para realizar este proyecto. III
AGRADECIMIENTOS IV
RESUMEN Resumen Este Trabajo Fin de Grado se ha realizado en el marco del proyecto europeo H2020 LOCOMOTION, en este proyecto europeo, trece instituciones europeas trabajan codo con codo para desarrollar un modelo que permita estudiar c´omo poder reducir la huella de carbono generada por la sociedad para conseguir un mundo m´as sostenible. El proyecto que se desarrolla en este TFG, tiene como objetivo principal el desarrollo de en plugin para Sonarqube dedicado a analizar la calidad de Integrated Assessment Models (IAMs) desarrollados con el software de simulaci´on Vensim. Se parte del TFG de Daniel Bazaco Velasco llamado “Definici´on y comprobaci´on de est´andares de calidad en la programaci´on de IAMs en Vensim” y se contin´ua con el desarrollo implementado durante el mismo. Mediante el plugin desarrollado en este trabajo, se puede comprobar est´andares de calidad, convenciones de nombres y reglas de programaci´on en los modelos de Vensim. Adem´as, el plugin permite la comunicaci´on con un diccionario de datos externo que sirve para mantener un registro de todos los elementos existentes en los modelos. Dicho registro favorece la coordinaci´on en el desarrollo del modelo, as´ı como la comunicaci´on con otros stakeholders del proyecto Locomotion. Para la direcci´on del proyecto se ha utilizado el marco de trabajo Scrum, y se ha desarrollado utilizando Java con las librer´ıas de Sonarqube y ANTLR4. El software obtenido como resultado final se ha publicado en GitHub, con la finalidad de permitir su uso p´ublicamente. V
RESUMEN VI
ABSTRACT Abstract This capstone project has been carried out within the framework of the European project H2020 LOCOMOTION.In this European project, thirteen European institutions work hand in hand to develop a model that allows studying how to reduce the carbon footprint generated by society to achieve a more sustainable world. The project that is developed in this capstone project, has as its main objective the development of a plugin for Sonarqube dedicated to analyzing the quality of Integrated Assessment Models (IAMs) developed with the Vensim simulation software. It starts from Daniel Bazaco Velasco’s capstone project called “ Definition and verification of quality standards in the programming of IAMs in Vensim ” and the development implemented during it continues. Using the plugin developed in this work, you can check quality standards, naming conventions and programming rules in Vensim models. In addition, the plugin allows communication with an external data dictionary that serves to keep a record of all the existing elements in the models. This record favors coordination in the development of the model, as well as communication with other stakeholders of the Locomotion project. The Scrum framework has been used to manage the project, and it has been developed using Java with the Sonarqube and ANTLR4 libraries. The software obtained as a final result has been published on GitHub, in order to allow its use publicly. VII
´ INDICE GENERAL 7.16.1. Resumen final de tareas y tiempos . . . . . . . . . . . . . . . . . . . . 122 7.16.2. An´alisis de los riesgos . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 7.16.3. Gesti´on de tareas con Gitlab issue tracker . . . . . . . . . . . . . . . . 126 7.16.4.Costesimulado............................... 128 7.16.5.Costereal.................................. 128 8. Conclusiones 129 8.1. Aplicaciones reales del plugin en LOCOMOTION . . . . . . . . . . . . . . . . 130 8.2. Publicaci´on en GitHub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 8.3. L´ıneas de trabajo futuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 A. Manuales 133 A.1. Manual de despliegue e instalaci´on y Manual de mantenimiento . . . . . . . . 133 A.2.Manualdeusuario ................................. 133 A.2.1. Modificaci´on de los par´ametros de las reglas de calidad . . . . . . . . . 135 B. Resumen de enlaces adicionales 139 C. Estructura de los endpoints del diccionario de datos. 141 Bibliograf´ıa 145 XIV
LISTA DE FIGURAS Lista de Figuras 2.1. Planificaci´oninicial. ................................ 34 3.1. Tabla de GitLab Issue Tracker. . . . . . . . . . . . . . . . . . . . . . . . . . . 39 5.1. Diagrama de la API del diccionario de s´ımbolos. . . . . . . . . . . . . . . . . 60 5.2. Diagramadepaquetes................................ 64 5.3. Diagrama de clases del paquete model. . . . . . . . . . . . . . . . . . . . . . . 65 5.4. Diagrama de clases del paquete parser. . . . . . . . . . . . . . . . . . . . . . . 65 5.5. Diagrama de clases del paquete plugin. . . . . . . . . . . . . . . . . . . . . . . 66 5.6. Diagrama de clases del paquete rules. . . . . . . . . . . . . . . . . . . . . . . 66 5.7. Diagrama de clases del paquete service. . . . . . . . . . . . . . . . . . . . . . 67 5.8. Diagrama de clases del paquete utilites. . . . . . . . . . . . . . . . . . . . . . 67 7.1. Planificaci´on con las reuniones los jueves. . . . . . . . . . . . . . . . . . . . . 123 7.2. Planificaci´on final del TFG. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 8.1. Transcurso del uso del plugin en el desarrollo de LOCOMOTION. . . . . . . 131 A.1. Selecci´on de la secci´on de perfiles de calidad en SonarQube. . . . . . . . . . . 136 A.4. Modificaci´on del par´ametro de una regla. . . . . . . . . . . . . . . . . . . . . 136 A.2. Extensi´on de un perfil de calidad de SonarQube. . . . . . . . . . . . . . . . . 137 A.3. Selecci´on de regla para poder modificar sus par´ametros. . . . . . . . . . . . . 137 XV
LISTA DE FIGURAS A.5. Modificaci´on del perfil de un proyecto SonarQube. . . . . . . . . . . . . . . . 138 XVI
LISTA DE FRAGMENTOS DE C ´ ODIGO Lista de fragmentos de c´odigo 4.1. Cuerpo de la petici´on a “qaGetSymbolDefinition”del plugin de partida. . . . 47 4.2. Cuerpo de la respuesta de “qaGetSymbolDefinition”del plugin de partida. . . 47 4.3. Cuerpo de la petici´on a “qaAddSymbolDefinition”del plugin de partida. . . . 48 4.4. Propiedades propias del plugin del fichero sonar-project.properties . . . . . . 50 4.5. Estructura original del archivo generado symbolTable.json . . . . . . . . . . . 50 4.6. Separador de las vistas en el modelo . . . . . . . . . . . . . . . . . . . . . . . 51 4.7. Nombre de una vista en el modelo . . . . . . . . . . . . . . . . . . . . . . . . 52 4.8. Configuraci´on por defecto de una vista en el modelo . . . . . . . . . . . . . . 52 4.9. Declaraci´on de una variable en una vista . . . . . . . . . . . . . . . . . . . . . 52 4.10. Declaraci´on de una flecha en una vista . . . . . . . . . . . . . . . . . . . . . . 52 4.11. Declaraci´on de un comentario con texto en una vista . . . . . . . . . . . . . . 53 4.12. Declaraci´on de una vista del modelo . . . . . . . . . . . . . . . . . . . . . . . 53 5.1. Estructura nueva del archivo generado symbolTable.json . . . . . . . . . . . . 61 5.2. Estructura nueva del archivo generado dictionaryDiff.json . . . . . . . . . . . 62 5.3. Nuevas propiedades a˜nadidas a sonar scanner . . . . . . . . . . . . . . . . . . 62 6.1. Declaraci´on de la superclase en la gram´atica . . . . . . . . . . . . . . . . . . . 71 6.2. Funci´on para crear el ´arbol de derivaciones de un modelo . . . . . . . . . . . 71 6.3. Declaraci´on de un canal de ANTLR4 para los saltos de l´ınea . . . . . . . . . 71 6.4. Reglas para habilitar o deshabilitar un canal de ANLTR4 . . . . . . . . . . . 71 6.5. Lectura de la configuraci´on de sonar-project.properties desde el plugin . . . . 72 6.6. Funciones utilizadas para llamar al visitor de las views y crear la tabla de vistas 72 6.7. Creaci´on de la tabla de vistas . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.8. Filtrado de s´ımbolos por modulo . . . . . . . . . . . . . . . . . . . . . . . . . 74 6.9. Clase abstracta padre de todas las clases de reglas de control de calidad . . . 74 6.10. Gesti´on del filtrado por m´odulo en la inyecci´on . . . . . . . . . . . . . . . . . 75 6.11. Funci´on para comprobar si existen acr´onimos en los nombres de las variables 76 6.12. Diferencias entre un lookup incrustado y un lookup con una funci´on . . . . . 77 6.13. Filtrado de lookups incrustados . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.14. Sintaxis de un grupo en un modelo . . . . . . . . . . . . . . . . . . . . . . . . 78 6.15. Validaci´on del nombre de las vistas . . . . . . . . . . . . . . . . . . . . . . . . 79 6.16. Invalidaci´on autom´atica de los s´ımbolos primarios en una vista . . . . . . . . 80 6.17. Comprobaci´on de si invalidar el m´odulo y las categor´ıas de una vista . . . . . 80 6.18. Utilizaci´on de polimorfismo en la regla SubscriptCopyNameCheck . . . . . . . 81 6.19. Implementaci´on de la comprobaci´on de categor´ıas duplicadas . . . . . . . . . 83 6.20. Detecci´on de funciones din´amicas en la declaraci´on de una variable . . . . . . 84 XVII
LISTA DE FRAGMENTOS DE C ´ ODIGO 6.21. Declaraci´on de una expresi´on regular parametrizada desde SonarQube . . . . 85 6.22. Implementaci´on del filtrado en el m´etodo para inyectar m´odulos de la clase ServiceController.................................. 88 6.23. Implementaci´on del filtrado en el m´etodo para inyectar s´ımbolos de la clase ServiceController.................................. 90 6.24. Atributos de la clase Category . . . . . . . . . . . . . . . . . . . . . . . . . . 90 6.25. Aplanamiento de la jerarqu´ıa de las categor´ıas . . . . . . . . . . . . . . . . . . 91 6.26. Declaraci´on de un s´ımbolo con la funci´on GET DIRECT CONSTANTS. . . . 92 6.27. Declaraci´on de un s´ımbolo con la funci´on GET DIRECT DATA . . . . . . . . 93 6.28. Multiples llamadas a archivos excel externos . . . . . . . . . . . . . . . . . . . 93 6.29. L´ogica para seleccionar que ´ındices inyectar . . . . . . . . . . . . . . . . . . . 94 6.30. Algoritmo para clasificar los s´ımbolos al generar el archivo de diferencias. . . 95 6.31. Llamadas utilizadas para realizar una petici´on al diccionario de datos. . . . . 97 6.32. Funci´on responsable de a˜nadir a una categor´ıa una subcategor´ıa. . . . . . . . 97 6.33. Funciones responsables de crear una categor´ıa y una subcategor´ıa. . . . . . . 98 6.34. Funci´on responsable de invalidar una categor´ıa. . . . . . . . . . . . . . . . . . 99 A.1. Ejemplo de llamar al an´alisis con par´ametros inline. No recomentado actualmente......................................... 133 A.2. Plantilla del archivo de configuraci´on sonar-project.properties . . . . . . . . . 134 C.1. Estructura de la petici´on al endpoint authenticate de la API . . . . . . . . . 141 C.2. Estructura de la respuesta del endpoint authenticate de la API . . . . . . . . 141 C.3. Estructura de la respuesta del endpoint qaGetSymbolDefinition de la API . . 141 C.4. Estructura de la petici´on al endpoint qaAddSymbolsDefinition de la API . . . 142 C.5. Estructura de la respuesta del endpoint qaGetIndexesDefinition de la API . . 143 C.6. Estructura de la petici´on al endpoint qaAddIndexesDefinition de la API . . . 143 C.7. Estructura de la petici´on y respuesta del endpoint qaGetCategories y qaAddCategoriesdelaAPI................................ 143 C.8. Estructura de la petici´on y respuesta del endpoint qaGetModules y qaAddModulesdelaAPI ................................. 143 C.9. Estructura de la petici´on al endpoint qaGetAcronyms de la API . . . . . . . 144 C.10.Estructura de la petici´on al endpoint qaGetUnitSystem de la API . . . . . . 144 XVIII
LISTA DE TABLAS Lista de Tablas 2.1. Tabladerequisitos.................................. 14 2.2. Product Backlog inicial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3. Divisi´on de la historia de usuario 4. . . . . . . . . . . . . . . . . . . . . . . . . 20 2.4. Divisi´on de la historia de usuario 5. . . . . . . . . . . . . . . . . . . . . . . . . 20 2.5. Divisi´on de la historia de usuario 6. . . . . . . . . . . . . . . . . . . . . . . . . 21 2.6. ProductBacklogfinal................................ 23 2.7. Riesgo “Comprensi´on del proyecto de partida”. . . . . . . . . . . . . . . . . . 23 2.8. Riesgo “Flexibilidad horaria del equipo de trabajo”. . . . . . . . . . . . . . . 24 2.9. Riesgo “Dificultad de comprensi´on del c´odigo de partida”. . . . . . . . . . . . 25 2.10. Riesgo “Cambio en la estructura del archivo Vensim”. . . . . . . . . . . . . . 26 2.11. Riesgo “Gram´atica no completa”. . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.12. Riesgo “Historia de usuario mal definida”. . . . . . . . . . . . . . . . . . . . . 27 2.13. Riesgo “Mutabilidad de las historias de usuario”. . . . . . . . . . . . . . . . . 28 2.14. Riesgo “Falta de organizaci´on en el equipo de trabajo”. . . . . . . . . . . . . 28 2.15. Riesgo “Comunicaci´on entre las partes poco fluida”. . . . . . . . . . . . . . . 29 2.16. Riesgo “Incompatibilidad horaria en el equipo de trabajo”. . . . . . . . . . . 29 2.17. Riesgo “Barrera ling¨u´ıstica”. . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.18. Riesgo “P´erdida del c´odigo fuente”. . . . . . . . . . . . . . . . . . . . . . . . . 30 2.19. Riesgo “Falta de conocimientos del stack de desarrollo ”. . . . . . . . . . . . . 31 XIX
LISTA DE TABLAS 2.20. Riesgo “Limitaciones del stack actual de desarrollo ”. . . . . . . . . . . . . . . 31 2.21. Riesgo “Problemas de sincronizaci´on con el diccionario de datos del proyecto ”. 32 2.22. Riesgo “Cancelaci´on del proyecto LOCOMOTION”. . . . . . . . . . . . . . . 32 2.23. Riesgo “Restricciones debidas a fuerza mayor ”. . . . . . . . . . . . . . . . . . 33 2.24. Presupuesto simulado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 6.1. Cobertura obtenida en los tests . . . . . . . . . . . . . . . . . . . . . . . . . . 101 7.1. TareasdelSprint0................................. 103 7.2. TareasdelSprint1................................. 104 7.3. TareasdelSprint2................................. 105 7.4. TareasdelSprint3................................. 106 7.5. TareasdelSprint4................................. 107 7.6. TareasdelSprint5................................. 109 7.7. TareasdelSprint6................................. 111 7.8. TareasdelSprint7................................. 113 7.9. TareasdelSprint8................................. 114 7.10.TareasdelSprint9................................. 117 7.11.TareasdelSprint10 ................................ 118 7.12.TareasdelSprint11 ................................ 121 7.13. Resumen tiempo estimado e invertido por Sprint . . . . . . . . . . . . . . . . 124 7.14. Agrupaci´on de las incidencias por etiqueta . . . . . . . . . . . . . . . . . . . . 127 7.15. Agrupaci´on de las incidencias por release . . . . . . . . . . . . . . . . . . . . . 127 7.16.Costesimulado.................................... 128 XX
CAP´ ITULO 1. INTRODUCCI ´ ON Cap´ıtulo 1 Introducci´on 1.1. Contexto Este Trabajo Fin de Grado est´a realizado en convenio con GEEDS (GIR Grupo e Investigaci´on en Energ´ıa, Econom´ıa y Din´amica de Sistemas) [13], grupo coordinador del proyecto europeo LOCOMOTION (Low-carbon society: an enhanced modelling tool for the transition to sustainability). [27]. El proyecto LOCOMOTION es el sucesor del proyecto MEDEAS [31], ambos pertenecientes al programa Horizon 2020 [12]. El alumno Daniel Bazaco Velasco public´o el curso pasado su TFG, llamado “Definici´on y comprobaci´on de est´andares de calidad en la programaci´on de IAMs en Vensim” [4]. El cual, tiene como objetivo la creaci´on de un plugin para la plataforma SonarQube [45] junto a la definici´on y desarrollo de un conjunto de reglas de calidad necesarias para la comprobaci´on de convenci´on de nombres y otras reglas para el lenguaje de programaci´on Vensim[55] en el que est´a escrito el proyecto LOCOMOTION. Tomando el TFG de Daniel Bazaco como predecesor, se tratar´a de ampliar el trabajo ya realizado por este alumno. Se seguir´a desarrollando el plugin para SonarQube, teniendo en cuenta la secci´on “L´ıneas de trabajo futuras”descrita en el TFG de Daniel Bazaco. 1.1.1. Introducci´on a LOCOMOTION LOCOMOTION es un IAM (Integrated Assessment Models) [5], es decir, un modelo que permite hacer simulaciones a nivel global para poder comprobar el efecto en diferentes aspectos de distintas pol´ıticas. Esto permite al interesado poder tomar decisiones teniendo de base un modelo que estima la factibilidad, eficiencia y coste de las medidas consideradas. Las estimaciones generadas pertenecer´an a distintos ´ambitos como el econ´omicos, energ´etico y tecnol´ogico. 1
1.1. CONTEXTO Este modelo es desarrollado apoy´andose en otros modelos como pueden ser World6 [44], TIMES [18], LEAP [48], GCAM [40], C.Roads [9] y MEDEAS [31], su predecesor. El objetivo es realizar un modelo m´as robusto, ´util y transparente. El lenguaje principal en el que est´a desarrollado LOCOMOTION es Vensim, un lenguaje de modelado de din´amica de sistemas. El problema de este lenguaje es que es privativo y niega el acceso libre al uso del modelo, por eso, existe un proyecto interno en LOCOMOTION con el objetivo de transpilar [23], tanto el modelo, como el motor de simulaci´on a python. Esta traspilaci´on permitir´ıa el acceso libre al c´odigo por cualquier usuario. 1.1.2. Introducci´on a Vensim Vensim es un programa utilizado para la generaci´on de modelos de din´amicas de sistemas. Destaca por su eficiencia, funcionalidad y flexibilidad, adem´as cuenta con una interfaz gr´afica. Cada modelo generado est´a compuesto por s´ımbolos, vistas y grupos. Un s´ımbolo define un aspecto del modelo, puede tener una unidad, un comentario y una o varias ecuaciones que lo definen. Estas ecuaciones pueden a su vez contener m´as s´ımbolos y de este modo generar una red de interconexiones. En el momento de hacer la simulaci´on del modelos, Vensim va realizando saltos de tiempo fijos en los cuales recalcula el valor de los s´ımbolos y as´ı ver la evoluci´on del sistema. Existen varios tipos de s´ımbolos en Vensim, a continuaci´on se encuentra una lista con los tipos de s´ımbolos que son relevantes para LOCOMTION. [61]: Variables auxiliares: Cualquier s´ımbolo que dependa del tiempo o de otros s´ımbolos que sean variables. Niveles: Son variables din´amicas, que se calculan a partir de su valor en la iteraci´on anterior de la simulaci´on. Datos: Estas son variables independientes de las dem´as variables del modelo, sin embargo si que dependen de informaci´on externa al modelo. Se suelen utilizar para comparar el modelo respecto a la realidad. Constantes: Un s´ımbolo cuyo valor no cambia respecto al tiempo. Aun as´ı, estas variables pueden ser modificadas por el usuario durante la simulaci´on. Tambi´en existen un tipo especial de constantes llamadas Contantes inmutables, las cuales no pueden ser modificadas durante la simulaci´on. 2
CAP´ ITULO 1. INTRODUCCI ´ ON Por ´ultimo, tambi´en podemos utilizar las constantes iniciales, las cuales tienen al inicio de la simulaci´on su valor generado utilizando diversos s´ımbolos del modelo. Una vez generadas se mantienen constantes en el tiempo. Subscripts: Son s´ımbolos que funcionan como un diccionario, es decir, pueden almacenar pares de informaci´on clave-valor, que podr´a ser recuperada m´as adelante mediante una clave. Pueden ser subconjuntos de otros subscripts o copias de los mismos, en este caso no pueden tener m´as valores propios o de un tercer subscripts. Lockups: Son funciones num´ericas no lineales, en las cuales se definen los valores de x e y. Mediante estas funciones se puede obtener el valor asignado a y, si damos el valor de x. Reality checks: Estas ecuaciones se utilizan para aportar informaci´on adicional sobre el modelo y poder verificar la consistencia de unidades. Son a˜nadidas a las ecuaciones del resto de tipos de s´ımbolos. Una vista es la representaci´on gr´afica de un subconjunto de s´ımbolos del sistema. En cada vista, se pueden a˜nadir los s´ımbolos que el usuario desee y observar las conexiones entre ellos mediante flechas, los s´ımbolos a˜nadidos en una vista pueden ser de tipo defined oprimary si en la vista se est´a definiendo como se genera el valor del s´ımbolo, es decir, se muestra su ecuaci´on mostrando todos los s´ımbolos que aparecen en dicha ecuaci´on, o de tipo shadow osecondary si solo se lee el valor del s´ımbolo [56]. Tambi´en se pueden a˜nadir gr´aficas que muestran como se ha ido modificando el estado de uno a varios s´ımbolos seleccionados. Un grupo es una forma de agrupar a los s´ımbolos en conjuntos que pueden tener relaci´on sem´antica, su principal objetivo es mantener el c´odigo fuente organizado y poder realizar inspecciones de los resultados m´as r´apidas, actualmente, solo existe un grupo en el c´odigo fuente de LOCOMOTION, el cual contiene las variables internas de Vensim [57]. 1.1.3. Introducci´on a SonarQube La plataforma web de c´odigo abierto llamada SonarQube [45], permite analizar de forma est´atica c´odigos escritos en diversos lenguajes de programaci´on con el fin de evitar malas pr´acticas y bugs no detectados. SonarQube utiliza una serie de reglas creadas por el usuario u obtenidas de un paquete por defecto. Cuando se activa una de estas reglas para el an´alisis, en el momento que falle generar´a un issue. Un issue puede indicar un problema en el c´odigo, su gravedad, la ubicaci´on, el tipo y una posible forma de resolverlo. 3
1.4. ESTRUCTURA DE LA MEMORIA 10
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Cap´ıtulo 2 Requisitos y Planificaci´on 2.1. Marco de desarrollo ´agil Scrum Para el desarrollo de este proyecto se ha seguido el marco de desarrollo ´agil Scrum. Podemos definir Scrum como un framework (marco de trabajo) para la gesti´on de productos, proyectos y servicios complejos que facilita un desarrollo mantenido e incremental [24]. Se decidi´o usar Scrum porque al ser un marco de desarrollo ´agil nos resultar´ıa m´as sencillo implementar cambios, debido a unos requisitos iniciales poco espec´ıficos y que pueden ir cambiando a lo largo del proyecto seg´un var´ıen las necesidades del cliente. Otro de los motivos para utilizar este marco de trabajo son los resultados obtenidos cada poco tiempo que pueden ser entregados al cliente para su aceptaci´on o propuesta de cambios. A continuaci´on se definir´an los artefactos, roles y eventos deScrum. 2.1.1. Artefactos Durante el proyecto se crean tres artefactos [24], que son: Product Backlog: Lista de funcionalidades, productos o acciones que conforman el producto a crear. Se compone de historias de usuario que pueden irse completando, detallando o a˜nadiendo m´as historias de usuario a medida que se va desarrollando el proyecto y priorizando unas sobres otras. Sprint Backlog: Lista de funcionalidades o tareas seleccionadas del Product Backlog que se incorporan al Sprint actual para llevarse a cabo durante el mismo. Una vez a comenzado el Sprint (Sprint se define en el apartado 2.1.3), el Sprint Backlog no puede ser modificado. 11
2.1. MARCO DE DESARROLLO ´ AGIL SCRUM Incremento: Resultado del Sprint que incrementa el valor del producto. Se conforma por todas las tareas, escenarios, historias de usuario y cualquier elemento que se haya desarrollado durante el Sprint. 2.1.2. Roles Scrum tiene tres roles [37], que son: Product Owner: El Product Owner es el responsable del producto final, se ocupa de decidir cu´ales ser´an las tareas a realizar para maximizar el valor del producto. Esto lo lleva a cabo generando el Product Backlog, es el ´unico que puede editar dicho artefacto. El valor del producto es subjetivo y depender´a de qu´e producto se desarrolla. Por ejemplo en el caso de un producto comercial, el valor se podr´ıa ver como el ROI (Return of Investment) del producto. En cualquier caso, ser´a decisi´on del Product Owner cu´al es el valor a maximizar y c´omo lograrlo. Scrum Master: El Scrum Master vela por el buen funcionamiento del proyecto, ayudando y ense˜nando las pr´acticas de Scrum y protegiendo al equipo de interferencias externas. Se asegura de que todo el mundo entiende y sigue las gu´ıas de Scrum. Hay que entender que no es el gestor del proyecto, el Scrum Master no manda qu´e hacer a nadie, ya que es el propio equipo el que decide en qu´e se trabaja. Equipo de desarrollo: El Equipo de desarrollo (development team) es el responsable de construir el producto que especifica el Product Owner. Es un equipo multidisciplinar formado habitualmente de 5 a 9 personas, con la capacidad de poder realizar todas las tareas necesarias para el desarrollo, desde hacer an´alisis, hasta las implementaciones y despliegues. Son un equipo auto gestionado y pueden funcionar de forma independiente. Para llevar el desarrollo a cabo, el equipo decide la cantidad de tareas del Product Backlog (respetando el orden dictado por el Product Owner en la medida que se pueda) que se van a hacer en el Sprint. Estas tareas son a˜nadidas al Sprint Backlog. 2.1.3. Eventos Scrum tiene cinco eventos [43] que ocurren durante el ciclo de vida del proyecto. Estos eventos tienen una duraci´on previamente fijada y se realizan peri´odicamente en unas fechas marcadas para facilitar la comunicaci´on eficaz entre los miembros del equipo. Estos eventos son: Sprint: Es un ciclo de trabajo de menos de 4 semanas, normalmente de 2 semanas. Se hacen 12
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON de forma continuada durante todo el proyecto, es decir nada m´as acaba uno empieza el siguiente. En cada Sprint se realiza un Sprint Backlog y una vez ha llegado la fecha fin de dicho Sprint se cierra, se hayan acabado todas las tareas o no. Si han quedado tareas pendientes, ser´a decisi´on del equipo qu´e hacer. Algunas opciones son: Pasar la tarea autom´aticamente al siguiente Sprint o devolver la tareas al Product Backlog para m´as adelante. Sprint Planning: Cada Sprint necesita su Sprint Backlog, este artefacto es generado en el Sprint Planning, en estas reuniones de aproximadamente dos horas se re´une todo el equipo (el Product Owner es opcional pero recomendable) y se decide qu´e llevar a cabo en el Sprint. Una vez decidido, la reuni´on se centra en c´omo realizar dichas tareas, realizar estimaciones de tiempo y si fuese necesario a˜nadir o eliminar alguna de las tareas previamente aceptadas. Daily Scrum: Son reuniones t´ıpicamente diarias de m´aximo 15 minutos, suelen hacerse de pie para fomentar que se realice de forma r´apida y efectiva. Su objetivo principal es la coordinaci´on entre los miembros del equipo de desarrollo. No deber´ıa de haber decisiones extendidas sino solo sincronizar trabajos y prever futuros obst´aculos que puedan ocurrir. Sprint Review: Una vez ha acabado el Sprint se realiza esta reuni´on de aproximadamente 1-2 horas. En ella de analiza el incremento de funcionalidad del producto que se ha llevado a cabo en el Sprint. En dicha reuni´on puede asistir gente externa del equipo de desarrollo y preguntar dudas sobre el incremento. Tambi´en esta reuni´on sirve para que el Product Owner aprenda de la situaci´on actual y como deber´a enfocar o adaptar el Product Backlog para el futuro. Si hubiese que resumir esta reuni´on en dos palabras ser´ıan: Inspecci´on y adaptaci´on. Sprint Retrospective: Reuni´on que se hace acto seguido del Sprint Review, con una duraci´on de alrededor de hora y media. Es muy similar a su reuni´on predecesora, pero con una diferencia fundamental, si el Sprint Review se centraba en el producto, el Sprint Retrospective se centra en el proceso de desarrollo. Es un momento para que el equipo discuta qu´e problemas existen y qu´e cosas no se est´an haciendo de forma eficiente y qu´e soluciones se proponen. Pero no solo hay que centrarse en los problemas, tambi´en es conveniente comunicar qu´e medidas s´ı funcionan y hacen que el trabajo sea m´as eficiente. Esta reuni´on es una buena oportunidad para que el Scrum Master tome note de posibles problemas y act´ue ante ellos para actuar como facilitador para el resto del equipo. 2.2. Adaptaci´on de Scrum al proyecto Scrum es un marco de trabajo abierto que puede ser adaptado para cada proyecto, se puede concretar qu´e individuos toman el papel de cada rol, la duraci´on de los Sprints, las caracter´ısticas de las reuniones, etc. 13
2.3. REQUISITOS Este proyecto involucra ´unicamente a dos personas: la tutora (Yania Crespo) y el alumno (Juan Herruzo). Estas condiciones no son las ideales para poder aplicar Scrum y por ello se realizar´a una adaptaci´on de este marco de trabajo. La tutora (Yania Crespo) conoce m´as en profundidad el proyecto LOCOMOTION, al formar parte del equipo del mismo. Ella har´a de intermediaria entre las directrices y requerimientos pedidos por GEEDS y el equipo de este proyecto. Por lo tanto, tendr´a el rol de Product Owner. Adem´as, la tutora cuenta con una gran experiencia en el ´ambito de las metodolog´ıas ´agiles y en Scrum al haber dirigido varios proyectos utilizando este marco de trabajo. Por lo tanto, tambi´en realizar´a el rol de Scrum Master a pesar de no considerarse una buena pr´actica seg´un Scrum. Por ´ultimo, el equipo de desarrollo estar´a compuesto ´unicamente por el estudiante Juan Herruzo, el autor de este TFG. Cada Sprint tendr´a una duraci´on de dos semanas y, se ha considerado que no es necesario hacer una daily (reuni´on diaria). Por ello se realizar´a una weekly, es decir una reuni´on a la semana y se utilizar´a la plataforma de mensajer´ıa instant´anea rocket para poder comunicarse en cualquier otro momento. En cada Sprint se realizar´a un Sprint Planning al inicio del mismo, una weekly a la mitad y un Sprint Review ySprint Retrospective al finalizar el Sprint. 2.3. Requisitos Los requisitos mostrados en la Tabla 2.1 son los requisitos que han sido recolectados a lo largo del proyecto. Tabla 2.1: Tabla de requisitos. C´odigo Nombre Descripci´on R1 Generaci´on de una nueva gram´atica que permita el an´alisis de las views de Vensim. Ampliaci´on de la gram´atica con el objetivo de poder analizar l´exica y sint´acticamente la secci´on del modelo donde se definen las vistas. Este an´alisis debe contener al menos la informaci´on relativa al nombre (m´odulo, categor´ıa y subcategor´ıa) e informaci´on sobre qu´e s´ımbolos forman parte de la vista. Se diferenciar´a entre cu´ales son s´ımbolos principales y cu´ales son s´ımbolos secundarios o shadows. Contin´ua en la p´agina siguiente 14
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Tabla 2.1 – Viene de la p´agina anterior C´odigo Nombre Descripci´on R2 Filtrado de los s´ımbolos del modelo mediante el m´odulo al que pertenecen. Creaci´on de la funcionalidad para poder seleccionar qu´e s´ımbolos del modelo pueden tener issues en la ejecuci´on del control de calidad. Los s´ımbolos seleccionados son aquellos que tienen como m´odulo principal aquel por el que se desea filtrar. R3 Actualizaci´on de la regla sobre el nombrado de variables para tener en cuenta los acr´onimos. Actualizaci´on de la regla de nombrado de las variables para que el uso de los acr´onimos guardados en el diccionario de datos no genere issues. R4 Parametrizaci´on de las caracter´ısticas mutables de las reglas. Actualizaci´on de las reglas que contengan una caracter´ıstica modificable, concretamente, expresiones regulares y n´umeros, generar propiedades de estas caracter´ısticas que puedan ser modificadas con Quality profiles de SonarQube. R5 Inyecci´on en el diccionario de datos de los m´odulos detectados como nuevos . Inyecci´on en el diccionario de datos de los m´odulos que han sido detectados como nuevos, lo m´odulos que ya est´en almacenados en el diccionario de s´ımbolos no deben ser reinyectados. R6 Inyecci´on en el diccionario de s´ımbolos de categor´ıas y subcategor´ıas detectadas como nuevas. Inyecci´on en el diccionario de s´ımbolos de categor´ıas y subcategor´ıas que han sido detectados como nuevas, las categor´ıas y subcategor´ıas que ya est´en almacenados en el diccionario de s´ımbolos no deben ser reinyectados. Si se detecta una subcategor´ıa nueva de una categor´ıa ya almacenada en el diccionario, solo se deber´a inyectar la subcategor´ıa. R7 Inyecci´on de las referencias a tablas Excel externas detectadas nuevas al diccionario de datos. Inyecci´on en el diccionario de datos de las referencias a tablas Excel externas que han sido detectados como nuevas tiendo la referencia al s´ımbolo al que pertenecen, las referencias a tablas Excel externas que ya est´en almacenados en el diccionario de s´ımbolos no deben ser reinyectados. Contin´ua en la p´agina siguiente 15
2.3. REQUISITOS Tabla 2.1 – Viene de la p´agina anterior C´odigo Nombre Descripci´on R8 Validaci´on de las inyecciones. Limitar la inyecci´on al diccionario de s´ımbolos a elementos considerados como v´alidos por el an´alisis, es decir, que no hayan generado ninguna issue y que adem´as no existan ya en el diccionario de s´ımbolos. Este requisito se aplica a cualquier elemento que haya que subir al diccioaniro de s´ımbolos. R9 Actualizaci´on de la inyecci´on de s´ımbolos. Ampliaci´on de la inyecci´on de s´ımbolos para que contengan la nueva informaci´on sobre sus m´odulos y categor´ıas. R10 Creaci´on de una nueva regla que detecte lookups incrustados. Creaci´on de una regla que genere una issue cuando se detecten lookups que est´en incrustados en el modelo. Un lookup incrustado hace referencia a que los puntos que definen el lookup se encuentran declarados en el propio c´odigo. La issue generada debe tener una gravedad de INFO si la cantidad de datos incrustados es menor o igual a 4 o MAJOR si es mayor a este n´umero. Este n´umero debe de ser una propiedad modificable en SonarQube. R11 Creaci´on de una nueva regla que detecte la declaraci´on de s´ımbolos en el grupo de control. Creaci´on de una nueva regla que genere una issue cuando exista un s´ımbolo que no sea de control declarado en la zona de control generada por defecto por Vensim, tambi´en se debe generar una issue en el caso en el que un s´ımbolo de control no est´e declarado en esta zona. Los s´ımbolos de control por defecto son: TIME, TIME STEP, INITIAL TIME, FINAL TIME, SAVEPER. Esta lista de s´ımbolos deben de ser una propiedad modificable en SonarQube. R12 Creaci´on de una nueva regla que compruebe el nombre de las vistas. Creaci´on de una nueva regla que genere una issue cada vez que el nombre de una vista no siga las directrices de la convenci´on de nombres. Contin´ua en la p´agina siguiente 16
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Tabla 2.1 – Viene de la p´agina anterior C´odigo Nombre Descripci´on R13 Creaci´on de una nueva regla que detecte fallos en las unidades de cada s´ımbolo. Creaci´on de una nueva regla que genere una issue cada vez que las unidades de un s´ımbolo no est´en contenidas en la lista de unidades almacenada en el diccionario de datos del proyecto. Existe una excepci´on, si un s´ımbolo no tiene unidades se declarar´a con la unidad Dmnl (dimensionless). R14 Creaci´on de una nueva regla que revise el nombre de las copias de los subscripts. Creaci´on de una nueva regla que genere una issue cada vez que el nombre de un subscript copy no siga las directrices de la convenci´on de nombres. R15 Creaci´on de una nueva regla que revise la informaci´on sobre las referencias a tablas Excel externas de cada s´ımbolo. Creaci´on de una nueva regla que genere una issue cada vez que la informaci´on sobre las referencias a tablas Excel externas detectada en local y la almacenada en el diccionario de datos no sean id´enticas. Esta issue se generar´a sobre el s´ımbolo al que pertenece la referencia externa. R16 Creaci´on de una nueva regla que compruebe que no existen categor´ıas o subcategor´ıas con el mismo nombre Creaci´on de una nueva regla que genere una issue en las subcategor´ıas que tengan el mismo nombre que otras subcategor´ıas o que otras categor´ıas, el nombre de cada categor´ıa y subcategor´ıa tiene que ser ´unico. R17 Creaci´on de una nueva regla que compruebe que se cumple la convenci´on de nombres en las variables delayed Creaci´on de una nueva regla que genere una issue en las variables de tipo delayed (las cuales son las que utilizan las funciones DELAYED oSMOOTH y sus derivadas) cuando no cumplan con la convenci´on de nombres. Por convenio estas variables deber´an tener como prefijo —delayed — a no ser que est´en vinculadas con la contante TIME STEP en cuyo caso deber´an tener el prefijo —delayed TS — R18 Generaci´on de documentaci´on que contenga las diferencias encontradas entre los s´ımbolos de modelo programado en el .mdl y los s´ımbolos del diccionario de datos. Generaci´on de un documento json que contenga todas las diferencias que se han detectado entre los elementos locales y los almacenados en el diccionario de datos del proyecto. El nombre de este documento ser´a dictionaryDiff.json. Este documento se generar´a si y solo si, ha sido especificado en las propiedades del sonar scanner. Contin´ua en la p´agina siguiente 17
2.4. PRODUCT BACKLOG Tabla 2.1 – Viene de la p´agina anterior C´odigo Nombre Descripci´on R19 Actualizaci´on de la documentaci´on generada al ejecutar sonar scanner. Actualizaci´on del documento json generado con nombre symbolTable.json, se debe a˜nadir como m´ınimo, informaci´on relativa al m´odulo, categor´ıa y subcategor´ıa de cada s´ımbolo y las referencias a tablas excel externas de los s´ımbolos que lo requieran. R20 Creaci´on autom´atica de una carpeta que contenga los archivos generados por el plugin y la parametrizaci´on de su nombre. Creaci´on de una carpeta en la cual se guardar´an todos los documentos generados en local al realizar el esc´aner. Esta carpeta debe estar ubicada en la ruta donde se ejecuta dicho esc´aner y debe tener por defecto el nombre auxiliary files. Este nombre debe de ser modificable utilizando una propiedad de sonar scanner. R21 Ampliaci´on del conjunto de propiedades del archivo de configuraci´on de sonar scanner. Ampliaci´on del conjunto de propiedades existentes en el archivo de configuraci´on de sonar scanner, como m´ınimo se debe a˜nadir la opci´on de inyectar o no los elementos nuevos detectados. R22 Mantenimiento del alcance actual del plugin Mantenimiento de todas las funcionalidades y reglas actuales del plugin, se deben modificar las funcionalidades del plugin inicial para que sigan funcionando si cambian aspectos cr´ıticos del plugin. 2.4. Product Backlog Utilizando los requisitos de la Tabla 2.1, se genera un Product Backlog inicial para poder ser utilizado en el marco de trabajo Scrum adaptado al proyecto. El Product Backlog contiene historias de usuario, la cuales explican de forma general una funcionalidad del software escrita desde la perspectiva del usuario final o cliente. La estructura general de una historia de usuario es: “Como hrol del clientei, quiero hintenci´on u objetivo del clienteipara hbeneficio que le aportar´a al clientei.”. Si una historia de usuario tiene una complejidad demasiado grande como para ser afrontada en un Sprint esta pasar´a a ser denominada una ´epica o epic en ingl´es y es recomendable dividirla en historias de usuario m´as peque˜nas. En el plugin solo existe un rol, el de un programador Vensim en el proyecto LOCO18
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON MOTION o en cualquier otro proyecto que adopte una serie de convenciones y reglas de programaci´on, este rol ser´a referenciado con la palabra “usuario”. En la Tabla 2.2 se puede encontrar la lista de historias de usuario ordenadas de mayor a menor prioridad, esta ordenaci´on se realiz´o en conjunto con la tutora del TFG, Yania Crespo, al inicio del proyecto, actuando como Product Owner. Este Product Backlog inicial intenta estructurar las ideas generales de los requisitos en grupos para empezar a comprender los flujos de desarrollo que existir´an en el futuro, es necesario hacer una revisi´on y subdividir las historias en otras m´as peque˜nas para as´ı representar con una mayor granularidad la lista de requisitos existente. C´odigo Descripci´on US1 Como usuario quiero poder seguir realizando todas las acciones que se pueden realizar con el plugin en su estado inicial. US2 Como usuario quiero poder analizar la representaci´on textual de la parte de las vistas de los modelos de Vensim almacenada en archivos .mdl para verificar que la sintaxis es correcta. US3 Como usuario quiero poder filtrar que s´ımbolos generan issues mediante el m´odulo al que pertenecen. US4 Como usuario quiero recibir m´as avisos sobre errores en el modelo de los que existen actualmente para poder mejorar la calidad del modelo de Vensim. US5 Como usuario quiero poder configurar partes del funcionamiento del esc´aner. US6 Como usuario quiero que todos los elementos nuevos sean inyectados al diccionario de datos del proyecto para poder llevar un registro de ellos. Tabla 2.2: Product Backlog inicial. La historia de usuario US1 no es una historia realizable en un Sprint en s´ı, sino que deber´a ser hecha durante todo el desarrollo. Se define para prevenir que se puedan realizar modificaciones el en c´odigo original sin una justificaci´on. Viene siendo similar a una restricci´on en la descripci´on de requisitos funcionales, de informaci´on, no funcionales y restricciones. Las historias US4, US5 y US6 son consideradas ´epicas y es necesario subdividirlas en historias de usuario menos complejas, pero que sigan cumpliendo los requisitos establecidos. Estas subdivisiones se fueron realizando a lo largo del proyecto. Las subdivisiones que se consiguieron al final pueden ser encontradas en la Tabla 2.3 para la historia de usuario US4, en la Tabla 2.4 para la historia de usuario US5 y en la Tabla 2.5 para la historia de usuario US6. 19
2.5. RIESGOS Riesgo 4 Cambio en la estructura del archivo Vensim Descripci´on Los desarrolladores del software de simulaci´on, Vensim podr´ıan modificar la estructura del fichero del modelo, haciendo que la gram´atica desarrollada quede obsoleta. Amenaza u Oportunidad Amenaza Probabilidad 1 Impacto 10 Importancia (P*I) 10 Categor´ıa Secundario Estrategia Aceptado. Se fijar´a una versi´on oficial en el proyecto LOCOMOTION para evitar el riesgo durante el TFG. Si se modificase la estructura y se quisiese utilizar el plugin nuevamente, habr´ıa que rehacer la gram´atica para que pudiese volver a ser utilizable. Tabla 2.10: Riesgo “Cambio en la estructura del archivo Vensim”. Riesgo 5 Gram´atica no completa Descripci´on Vensim tiene una gran cantidad de funcionalidades, puede que alguna de ellas no est´en previstas en la gram´atica desarrollada. Amenaza u Oportunidad Amenaza Probabilidad 9 Impacto 7 Importancia (P*I) 63 Categor´ıa Prioritario Estrategia Mitigado. Se utilizar´a la documentaci´on de Vensim para cubrir la mayor parte de las funcionalidades que ofrece. Plan de contingencia En caso de que se descubra una funcionalidad sin cubrir, se modificar´a la gram´atica para que se tenga en cuenta. Tabla 2.11: Riesgo “Gram´atica no completa”. 26
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Riesgo 6 Historia de usuario mal definida Descripci´on Al analizar una nueva funcionalidad a implementar, puede comprenderse de manera err´onea y llevar a cabo un desarrollo no ´util. Amenaza u Oportunidad Amenaza Probabilidad 5 Impacto 10 Importancia (P*I) 50 Categor´ıa Principal Estrategia Mitigado. Se cerciorar´a durante los Sprint planing cuales son las historias de usuario a desarrollar, confirmando por parte del equipo que se ha entendido correctamente y siendo verificado por el Scrum Master. Adicionalmente, en la weekly se revisar´a y analizar´a lo realizado a mitad de Sprint para cerciorarse de ir por el camino adecuado. Tabla 2.12: Riesgo “Historia de usuario mal definida”. 27
2.5. RIESGOS Riesgo 7 Mutabilidad de las historias de usuario Descripci´on Al proyecto LOCOMOTION involucra a una gran cantidad de organizaciones de todo Europa. Esto implica que pueda haber m´as variabilidad en los requisitos por culpa de retrasos en la coordinaci´on entre organizaciones. Amenaza u Oportunidad Amenaza Probabilidad 8 Impacto 9 Importancia (P*I) 72 Categor´ıa Prioritario Estrategia Mitigado. Se utilizar´a un marco de trabajo ´agil para poder asimilar la variabilidad del cambio. Plan de contingencia Si se produce un cambio en una o varias historias de usuario, se deber´an de volver a analizar y asegurar de que el cambio requerido ha sido validado por todas las partes involucradas, una vez asegurado, se realizar´an las modificaciones oportunas. Tabla 2.13: Riesgo “Mutabilidad de las historias de usuario”. Riesgo 8 Falta de organizaci´on en el equipo de trabajo Descripci´on Este TFG es el proyecto m´as grande en el que he participado hasta el momento, pueden darse casos en los que la complejidad de organizaci´on sea demasiado grande y haya problemas organizativos. Amenaza u Oportunidad Amenaza Probabilidad 6 Impacto 7 Importancia (P*I) 42 Categor´ıa Principal Estrategia Mitigado. Se realizar´an reuniones semanalmente con la tutora para ir informando de la situaci´on actual del proyecto y de posibles inconvenientes que se hayan descubierto. Tabla 2.14: Riesgo “Falta de organizaci´on en el equipo de trabajo”. 28
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Riesgo 9 Comunicaci´on entre las partes poco fluida Descripci´on Durante el desarrollo del proyecto puede que sea necesario ponerse en contacto con el tutor. Podr´ıa darse la posibilidad de que no se pueda hallar ninguna v´ıa de comunicaci´on. Amenaza u Oportunidad Amenaza Probabilidad 6 Impacto 10 Importancia (P*I) 60 Categor´ıa Prioritario Estrategia Evitado. Se utilizar´a la plataforma de mensajer´ıa instant´anea de la escuela rocket [42] para mantener una v´ıa de comunicaci´on siempre abierta. Tabla 2.15: Riesgo “Comunicaci´on entre las partes poco fluida”. Riesgo 10 Incompatibilidad horaria en el equipo de trabajo Descripci´on El equipo de trabajo tendr´a otras tareas externas al proyecto, las cuales pueden dificultar los horarios para las reuniones. Amenaza u Oportunidad Amenaza Probabilidad 6 Impacto 3 Importancia (P*I) 18 Categor´ıa Secundario Estrategia Mitigado. Antes de comenzar el proyecto, cada miembro del equipo de trabajo expondr´a sus incompatibilidades horarias, Teniendo en cuenta estas incompatibilidades, se puede buscar el mejor momento para realizar las reuniones. Si un d´ıa en concreto uno de los miembro no pudiese asistir a la reuni´on, lo avisar´a para as´ı poder cambiarla de hora. Tabla 2.16: Riesgo “Incompatibilidad horaria en el equipo de trabajo”. 29
2.5. RIESGOS Riesgo 11 Barrera ling¨u´ıstica Descripci´on El proyecto LOCOMOTION involucra a gente con lenguas maternas distintas, gran parte de esas lenguas no son comprendidas por el equipo de desarrollo y esto provocar´ıa problemas a la hora de comunicarse con otros miembro del proyecto. Amenaza u Oportunidad Amenaza Probabilidad 10 Impacto 7 Importancia (P*I) 70 Categor´ıa Prioritario Estrategia Evitado. Desde el principio el proyecto impuso como lengua oficial el ingl´es. Este idioma no presenta problemas al equipo de desarrollo. Tabla 2.17: Riesgo “Barrera ling¨u´ıstica”. Riesgo 12 P´erdida del c´odigo fuente Descripci´on El desarrollo del plugin es realizado solo por una persona en un ´unico dispositivo, cabe el riesgo de que ese dispositivo deje de funcionar y se pueda perder parte o la totalidad del c´odigo desarrollado. Amenaza u Oportunidad Amenaza Probabilidad 2 Impacto 10 Importancia (P*I) 20 Categor´ıa Prioriatio Estrategia Mitigado. Se usar´a el controlador de versiones, git [14] con un repositorio en remoto, este ser´a el repositorio oficial de la escuela, Gitlab. Plan de contingencia En caso de fallo del dispositivo, se reemplazar´a dicho dispositivo y se recuperar´a al ´ultima versi´on resguardada en el repositorio remoto. Tabla 2.18: Riesgo “P´erdida del c´odigo fuente”. 30
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Riesgo 13 Falta de conocimientos del stack de desarrollo Descripci´on El proyecto utiliza ANTLR y java con librer´ıas de SonarQube. El equipo de desarrollo nunca ha trabajado con ANTLR ni con las librer´ıas de SonarQube. El tiempo requerido para comprender su funcionamiento puede ser mayor al esperado. Amenaza u Oportunidad Amenaza Probabilidad 4 Impacto 6 Importancia (P*I) 24 Categor´ıa Secundario Estrategia Mitigado. Se estudiar´a ANTLR y el funcionamiento de las librer´ıas de SonarQube a priori de empezar el proyecto Tabla 2.19: Riesgo “Falta de conocimientos del stack de desarrollo ”. Riesgo 14 Limitaciones del stack actual de desarrollo Descripci´on Al depender de librer´ıas y software de terceros, puede darse el caso de que estos no permitan ciertas funcionalidades requeridas. Amenaza u Oportunidad Amenaza Probabilidad 3 Impacto 9 Importancia (P*I) 27 Categor´ıa Secundario Estrategia Aceptado. En caso de que se encuentre una limitaci´on, se buscar´an alternativas a la implementaci´on. No se contempla un cambio en el stack de desarrollo debido a la gran cantidad de tiempo que llevar´ıa traspilar el c´odigo actual. Plan de contingencia En caso de no encontrar alternativas a la implementaci´on, se pedir´a una revisi´on de la historia de usuario pertinente para que sea complaciente con las limitaciones. Tabla 2.20: Riesgo “Limitaciones del stack actual de desarrollo ”. 31
2.5. RIESGOS Riesgo 15 Problemas de sincronizaci´on con el diccionario de datos Descripci´on El plugin tiene conexi´on con un diccionario de datos del proyecto, el cual est´a tambi´en en desarrollo. Su conexi´on se hace mediante una API, la cual podr´ıa cambiar en el futuro o carecer de end points necesarios para el correcto funcionamiento del plugin. Amenaza u Oportunidad Amenaza Probabilidad 8 Impacto 7 Importancia (P*I) 56 Categor´ıa Principal Estrategia Mitigado. Se establecer´a una l´ınea de comunicaci´on con el equipo de desarrollo del diccionario de datos del proyecto. Esta comunicaci´on se realizar´a mediante un issue tracker definido en el repositorio gitlab oficial de LOCOMOTION. Tabla 2.21: Riesgo “Problemas de sincronizaci´on con el diccionario de datos del proyecto ”. Riesgo 16 Cancelaci´on del proyecto LOCOMOTION Descripci´on El TFG forma parte del proyecto LOCOMOTION, puede darse el caso de que dicho proyecto fuese cancelado durante el desarrollo del TFG. Amenaza u Oportunidad Amenaza Probabilidad 1 Impacto 4 Importancia (P*I) 4 Categor´ıa Secundario Estrategia Mitigado. El plugin no solo se utilizar´a en LOCOMOTION, al finalizar el desarrollo se har´a publico en un repositorio en github [15]. Para que as´ı pueda ser utilizado por otras personas. Si el proyecto LOCOMOTION fuese cancelado, se seguir´ıa teniendo un objetivo real para llevar a cabo el desarrollo del plugin. Tabla 2.22: Riesgo “Cancelaci´on del proyecto LOCOMOTION”. 32
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Riesgo 17 Restricciones debidas a fuerza mayor Descripci´on En la actualidad pueden ocurrir eventos que impongan ciertas restricciones que interfieran con el desarrollo del plugin. Por ejemplo, este TFG se empieza durante la pandemia causada por el virus SARS-CoV-2, existen restricciones de movilidad y en los entornos de trabajo. Amenaza u Oportunidad Amenaza Probabilidad 10 Impacto 10 Importancia (P*I) 100 Categor´ıa Prioritario Estrategia Mitigado. Como se prev´e que sigan activas las restricciones, las reuniones se har´an de manera online usando las plataformas jitsi [1] y WebEx [7] Plan de contingencia Si se impusieran nuevas restricciones que afectasen al entorno de desarrollo, se har´ıa, si fuese posible, una reuni´on de emergencia en la cual se analizar´ıa en qu´e afectan las nuevas restricciones y qu´e pasos realizar para poder continuar con el desarrollo. En caso de no ser posible siquiera una reuni´on online, se utilizar´a el sistema de mensajer´ıa instant´anea rocket o el servicio de email de la universidad. Mientras no se pudiese analizar la situaci´on, el equipo de desarrollo continuara implementando el Sprint Backlog del Sprint actual en el que se llegue. Tabla 2.23: Riesgo “Restricciones debidas a fuerza mayor ”. 2.6. Planificaci´on Este TFG se realiza asociado a una beca en el proyecto LOCOMOTION. El periodo de beca del TFG es de 6 mesas ampliables hasta 12. Para realizar la planificaci´on inicial se asumir´a que la duraci´on ser´a de 6 meses. Si fuese necesario se ampliar´a y reestructurar´a en el futuro, al saber que el inicio de la beca es el 14 de Septiembre de 2020, tenemos como fecha de fin de beca el d´ıa 14 de Marzo de 2021. Durante este periodo de beca se priorizar´a el desarrollo del plugin frente a la escritura de la memoria, esto se debe a que en la beca solo se incluye la realizaci´on del plugin. Pese a ello, se ir´an tomando notas de los avances que se vayan haciendo por Sprint para poder ser luego utilizados a la hora de escribir la memoria. El TFG est´a definido en el Grado de Ingenier´ıa Inform´atica de la UVa con 12 cr´editos ECTS [54]. Cada uno de estos cr´editos equivale a 25 horas de trabajo, [53] por lo que el el proyecto supondr´a 300 horas de trabajo aproximadamente. 33
2.7. PRESUPUESTO Figura 2.1: Planificaci´on inicial. Desde el principio se decidi´o tener Sprints de 2 semanas, con un total de 10 Sprints de desarrollo, 9 de ellos para implementaci´on de nuevas funcionalidades y 1 extra como contingencia. Estos Sprints se iniciar´ıan en Lunes. Por otra parte, los primeros 3 meses del TFG se realizar´an en paralelo con otras 5 asignaturas del grado. Por ello se decidi´o incluir un Sprint de descanso en el momento que se estim´o que habr´ıa m´as carga por parte de las asignaturas, esta semana se implant´o entre el d´ıa 23 de Noviembre de 2020 hasta el 6 de Diciembre de 2020. Adem´as, durante el periodo de vacaciones de Navidad no se realiz´o ning´un Sprint en activo. Pese a ello se pens´o utilizar este tiempo para otro tipo de tareas como el rafactoring y limpieza del c´odigo. El periodo de vacaciones de Navidad se estipul´o entre los d´ıas 20 de Diciembre de 2020 y 18 de Enero de 2021. En este per´ıodo se incluy´o tambi´en la realizaci´on de ex´amenes del primer cuatrimestre en convocatoria ordinaria. En la Figura 2.1 puede encontrarse la planificaci´on inicial en forma de diagrama de Gantt. 2.7. Presupuesto 2.7.1. Presupuesto simulado El equipo de desarrollo est´a constituido por un programador junior, teniendo en cuenta el “XVII Convenio colectivo estatal de empresas de consultor´ıa y estudios de mercado y de la opini´on p´ublica.”[32], se considera que el salario de un programador junior a partir del 31 de Diciembre de 2019 es de 15.860,56 eal a˜no, realizando 1800 horas anuales. A parte de este salario, la organizaci´on debe pagar alrededor de un 30,9 % extra del salario base a la Seguridad Social [19]. Por lo tanto el precio total anual es 20.761,47 eque implica un precio de 11,53 epor hora. Como la duraci´on del TFG ser´a de 300 horas, conlleva un precio total de 3.459 erespecto a los recursos humanos. 34
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON En cuanto a hardware, el desarrollo del TFG se realizar´a en un port´atil Lenovo Y52015IKBN valorado en 850 e. Seg´un la agencia tributaria, los equipos para procesos inform´aticos tienen un coeficiente de amortizaci´on m´aximo del 25 % [2]. Teniendo en cuenta que la duraci´on estimado del TFG es de seis meses, resulta en una amortizaci´on de 106,25 e. Respecto al software, el desarrollo se ha desarrollado utilizando el entorno de desarrollo integrado de JetBrains, llamado Intellij IDEA cuyo precio es de 14,90 epor mes [21], por lo tanto tenemos un total de 89,40 e. El resto de software utilizado para el desarrollo del proyecto y la comunicaci´on entre los miembros del equipo de proyecto son gratuitos. No se tendr´an en cuenta costes de las necesidades b´asicas como luz y agua, al haberse realizado el desarrollo desde las instalaciones universitarias y desde el alojamiento del alumno. Se tendr´a un margen de contingencia del 12 % para poder afrontar posibles futuros imprevistos. En la Tabla 2.24 se puede ver el presupuesto calculado. Sueldo 3.459 e Hardware 106,25 e Software 89,40 e Sub-total 3.654,65 e Margen de contingencias 438,56 e Total 4.093,21 e Tabla 2.24: Presupuesto simulado. 2.7.2. Presupuesto real El presupuesto real incluye la remuneraci´on por la beca y la amortizaci´on del port´atil utilizado para el desarrollo. El entorno de desarrollo no ha sido necesario adquirirlo, esto se debe a que el entorno de desarrollo es obtenido de forma gratuita gracias a ser estudiante universitario. [20] El sueldo de la beca es de 300 ebrutos mensuales, a estos hay que a˜nadir 48,41 eextras de seguridad social que dan un total de 348,41 emensuales. La beca tiene una duraci´on de seis meses prorrogables hasta doce meses. Por ello la base prevista para el sueldo es de 348,41x6 = 2090,46 e La amortizaci´on del port´atil es de 106,25 e. Por lo tanto el presupuesto total final es de 2.196,71 e 35
3.2. TECNOLOG´ IAS PARA EL DESARROLLO DEL PLUGIN Al tratarse de una dependencia del proyecto, esta puede ser gestionada con Maven, adem´as gracias es esto, se puede incrustar la generaci´on de la gram´atica a partir de su definici´on en el proceso de compilaci´on y empaquetado el plugin. 3.2.7. Dyson Dyson [25] es una tecnolog´ıa que permite generar mocks de APIs RESTful en node de forma r´apida y sencilla, tan solo se necesita un archivo con la configuraci´on escrita en JavaScript. Esta API mockeada se utiliza para poder realizar pruebas de integraci´on en aislamiento respecto a la comunicaci´on entre el plugin y el diccionario de datos del proyecto sin necesidad de comunicarse con el servidor real y tener el riego de hacer inyecciones de elementos no v´alidos. 3.2.8. PostMan PostMan [39] es una tecnolog´ıa que permite realizar peticiones y consultas a una API y poder ver la respuesta que devuelve. Su uso puede ser similar a curl. Se decide utilizar PostMan sobre curl por su forma de poder guardar peticiones para poder ser repetidas r´apidamente aparte de tener interfaz gr´afica que en este caso se prefiere. Se utiliza para poder verificar un correcto funcionamiento del diccionario de datos del proyecto ya que, al tratarse este de otro proyecto en desarrollo, pueden darse situaciones en las cuales alguno de los endpoints deje de funcionar correctamente. En estos casos se avisa a los responsables del desarrollo del diccionario de datos del proyecto creando una incidencia en el servidor GitLab dedicado de LOCOMOTION. 3.2.9. Junit y Mockito JUnit [51] es un framework utilizado para crear test unitarios para el lenguaje de programaci´on Java. Este framework es utilizado junto a Mockito [33], otro framework. Mockito es utilizado para simular objetos para as´ı poder realizar tests en aislamiento. 3.2.10. JaCoCo JaCoCo [34] es una herramienta utilizada en el entorno de realizar casos de prueba la cual nos permite analizar la cobertura de los tests, pudiendo visualizar qu´e secciones del c´odigo 42
CAP´ ITULO 3. TECNOLOG´ IAS UTILIZADAS son ejecutadas al lanzar una bater´ıa de pruebas generando un informe con los resultados al final de la ejecuci´on. Estas secciones pueden realizarse de diversas formas, por clase, por funci´on, por l´ınea, por decisi´on y por condici´on. 43
3.2. TECNOLOG´ IAS PARA EL DESARROLLO DEL PLUGIN 44
CAP´ ITULO 4. AN ´ ALISIS Cap´ıtulo 4 An´alisis 4.1. An´alisis inicial del proyecto de partida Como se ha indicado anteriormente, este TFG parte de un Trabajo previo realizado por Daniel Bazaco Velasco llamado “Definici´on y comprobaci´on de est´andares de calidad en la programaci´on de IAMs en Vensim” [4]. El objetivo de dicho Trabajo fue la creaci´on inicial de un plugin para la plataforma SonarQube que permitiese el control de calidad mediante la comprobaci´on de reglas de programaci´on y convenciones de nombres en los archivos de modelos generados por el software de simulaci´on llamado Vensim. Para comenzar este TFG, se debe iniciar realizando un an´alisis de la situaci´on actual del proyecto, para ello se utiliza la memoria del TFG anterior y el c´odigo fuente desarrollado. Este an´alisis describe de forma resumida el estado del plugin al inicio de este TFG con el objetivo de poner en contexto y facilitar el entendimiento del resto de la memoria. Al cierre del proyecto anterior, el plugin acab´o con un total de 15 reglas de control, la capacidad de parsear las declaraciones de los s´ımbolos del modelo y la posibilidad de inyecci´on y recuperaci´on de s´ımbolos del diccionario de s´ımbolos. 4.1.1. Parser y Visistors Un parser permite extraer la estructura l´exica y sint´actica de un archivo mediante una serie de reglas las cuales forman una gram´atica. Este plugin utiliza la herramienta ANTLR, en su versi´on cuarta para la generaci´on del parser para los modelos de Vensim. 45
4.1. AN ´ ALISIS INICIAL DEL PROYECTO DE PARTIDA Para generar ese parser, ANTLR necesita la creaci´on de una gram´atica en espec´ıfico para los archivos de Vensim. Actualmente el plugin cuenta con un ´unico archivo donde est´a agregada toda la gram´atica, llamado Model.g4. Para continuar con la explicaci´on es necesario comentar que los archivos de modelo de Vensim pueden ser divididos en cuatro secciones principales: Declaraci´on de s´ımbolos. Declaraci´on de vistas. Declaraci´on de gr´aficas. Declaraci´on de meta-datos. Actualmente el plugin es capaz de analizar y extraer un ´arbol de derivaci´on de la primera secci´on. De aqu´ı, utilizando un visitor llamado RawSymbolVisitor obtiene el nombre del s´ımbolos, su tipo, las l´ıneas en las que aparece, los posibles ´ındices que pueda utilizar, las unidades, el comentario y las dependencias que tenga con el resto de s´ımbolos del modelo. Un visitor permite recorrer un ´arbol de derivaciones nodo a nodo estipulando qu´e eventos se deben realizar al llegar a un nodo de un tipo en concreto, por ejemplo RawSymbolVisitor tiene eventos al detectar ciertos nodos que le permiten extraer la informaci´on citada anteriormente. En la versi´on de partida, el plugin no tiene forma de poder descubrir la categor´ıa o el m´odulo primario y/o secundario de los s´ımbolos. 4.1.2. Diccionario de datos del proyecto En la situaci´on actual del plugin, existe un sistema de comunicaci´on con un diccionario de datos externo. Este sirve para poder almacenar y visualizar s´ımbolos que se consideran v´alidos y as´ı preservar los atributos de cada uno de ellos. El diccionario de datos del proyecto es un instrumento de compartici´on y control de la informaci´on entre los diferentes modeladores del proyecto, encargados de modelar y programar m´odulos diferentes. En la versi´on de partida, la comunicaci´on entre el plugin para SonarQube y el diccionario de datos del proyecto se realiza mediante dos endpoints: qaGetSymbolDefinition Este endpoint de la API permite recuperar s´ımbolos considerados v´alidos. Su funcionamiento se basa hacer una petici´on POST con la lista de s´ımbolos que se desea recuperar en formato JSON. Un ejemplo de la petici´on puede ser encontrado en el Fragmento de c´odigo 4.1. 46
CAP´ ITULO 4. AN ´ ALISIS 1{ 2"symbols": [ 3"symbolA", 4"symbolB" 5] 6} Fragmento de c´odigo 4.1: Cuerpo de la petici´on a “qaGetSymbolDefinition”del plugin de partida. La respuesta del diccionario es un objeto Json que contiene una lista con todos los s´ımbolos validos existentes, teniendo en cuenta cu´ales se hab´ıan requerido en el request. Un ejemplo de la respuesta puede ser encontrada en el Fragmento de c´odigo 4.2. Se puede ver que se manda informaci´on extra que actualmente no es utilizada por el plugin como pueden ser los modelos o las categor´ıas. 1{ 2"symbols": [ 3{ 4" name ": " symbolA ", 5" definition ": " definitionexampleforsymbolA ", 6" unit ": "Kg", 7" isindexed ": " false ", 8" indexes ": [], 9"modules": { 10 " main ": " IAMNumberOne ", 11 " secondary ": [] 12 }, 13 " category ": " CategoryExampleTopLevel ", 14 " ProjectTypeOfValue ": " Constant ", 15 " ProgrammingSymbolType ": " Constant " 16 } 17 ], 18 " modules ": [...] , 19 " indexes ": [...] , 20 " categories ": [...] 21 } Fragmento de c´odigo 4.2: Cuerpo de la respuesta de “qaGetSymbolDefinition”del plugin de partida. qaAddSymbolDefinition El segundo endpoint con el que el plugin se comunica con el diccionario de datos del proyecto, es el inverso a “qaGetSymbolDefinition”, se utiliza para inyectar nuevos s´ımbolos en el diccionario de s´ımbolos. Tambi´en se realiza con una petici´on POST la cual tiene un cuerpo similar al recibido del endpoint anterior, pero con algunos matices, la estructura puede ser encontrada en el Fragmento de c´odigo 4.3. Como se puede ver, los principales cambios son que el m´odulo es extra´ıdo de cada s´ımbolo e inyectado a nivel global, esto quiere decir que cada petici´on que se env´ıe tiene que contener los s´ımbolos del mismo m´odulo, adem´as desaparece ProjectTypeOfValue ya que este par´ametro es asignado de forma manual utilizando un cliente web del diccionario de datos del proyecto, una vez se han agregado los s´ımbolos en el mismo. 47
4.1. AN ´ ALISIS INICIAL DEL PROYECTO DE PARTIDA 1{ 2"symbols": [ 3{ 4" name ": " symbolA ", 5" definition ": " definitionexampleforsymbolA ", 6" unit ": "Kg", 7" isindexed ": " false ", 8" category ": " CategoryExampleTopLevel ", 9" ProgrammingSymbolType ": " Constant " 10 } 11 ], 12 " indexes ": [...] , 13 " module ": " moduleName ", 14 } Fragmento de c´odigo 4.3: Cuerpo de la petici´on a “qaAddSymbolDefinition”del plugin de partida. La respuesta del servidor estar´a vac´ıa si todos los s´ımbolos han podido ser inyectados de forma correcta, o devolver´a un Json con el nombre de cada s´ımbolo err´oneo y el motivo de fallo. Existe un tercer endpoint que se utiliza para realizar la autenticaci´on con el servidor, envinado un usuario y contrase˜na v´alidos, se recibir´a un token con el que se podr´an realizar las futuras consultas. Este token se enviar´a al servidor en la cabecera de las peticiones con la siguiente estructura Authorization: Bearer <Token>. 4.1.3. Reglas El principal objetivo del plugin es poder avisar de fallos en el modelo de Vensim, estos fallos no son relativos a una estructura err´onea o a fallos sint´acticos, si no que se refieren a fallos en seguir las convenciones y reglas de programaci´on utilizadas por LOCOMOTION o por cualquier otro proyecto en el futuro. Las 15 reglas actuales descritas en la introducci´on pueden ser agrupadas respecto a qu´e parte representan de estas convenciones y reglas. Para comenzar, se encuentras 6 reglas de control de nombres de los s´ımbolos, existe una por cada tipo distinto de s´ımbolo que se revisa. Se encuentran reglas de nombrado para: Variables, Constantes, Lookups, RealityCheck, Subscript y SubscriptValue. Por otro lado, existen otras 2 reglas que revisan que todos los s´ımbolos, independientemente de su tipo, contengan un comentario y una unidad. Tambi´en existen 6 reglas relacionadas con el diccionario de datos del proyecto, 5 de ´estas verifican que existe uniformidad entre los s´ımbolos encontrados en el modelo y los s´ımbolos v´alidos del diccionario y la otra regla comprueba que cada s´ımbolo existe en el diccionario, ya que de no ser as´ı es considerado no v´alido. La peculiaridad de este conjunto de reglas es que 48
CAP´ ITULO 4. AN ´ ALISIS si cuando se realiza el an´alisis con el plugin no se consigue una conexi´on con el diccionario de datos del proyecto, son desactivadas. Por ´ultimo, la regla n´umero 15 hace una comprobaci´on de n´umeros m´agicos. Es decir, busca que no haya n´umeros en el modelo que se repitan demasiadas veces. Esta repetici´on de n´umeros m´agicos es considerada una mala pr´actica y por ello se intenta evitar. Dependiendo del n´umero de repeticiones del n´umero se puede considerar como un fallo de tipo informativo o como un fallo grave. Cuando una de estas 15 reglas detecta un fallo, este es almacenado en forma de una issue para posteriormente ser enviado a SonarQube. 4.1.4. Estructura y control del flujo En la secci´on “8.9. Estructura general del c´odigo” de la memoria del TFG de Daniel Bazaco se encuentra una buena explicaci´on de la estructura y flujo de actividad del plugin cuando este es ejecutado [4]. Esta estructura del plugin consiste en cinco paquetes: parser Donde se encuentran las clases relacionadas con la gram´atica y los modelos. plugin Donde se encuentra el n´ucleo de un plugin de Sonarqube rules Donde se encuentran todas las reglas service Donde se encuentran las clases responsables de la comunicaci´on con el diccionario de s´ımbolos utilities Donde se encuentran clases comunes como constantes o helpers. 4.1.5. Configuraciones del plugin El plugin cuenta con diversos par´ametros que pueden ser modificados para dar m´as flexibilidad al usuario final. Para este plugin existen dos formas de poder configurarlo. 49
4.2. ESTRUCTURA DE LOS ARCHIVOS DE SALIDA GENERADOS Cambiando la configuraci´on de SonarScanner SonarScanner utiliza un fichero de configuraci´on llamado sonar-project.properties. En este se pueden a˜nadir pares clave valor que despu´es pueden ser recuperados por el plugin. Existen alguna claves por defecto utilizadas por SonarScanner, pero se pueden a˜nadir m´as claves personalizadas. En el Fragmento 4.4 se pueden ver todas las claves personalizadas utilizadas por el plugin. 1# Url de la API del diccionario de s´ı mbolos . 2vensim . dictionaryService =<URL > 3# Nombre del usuario del diccionario de s´ı mbolos . 4vensim . dictionaryUsername =< Username > 5# Contrase ~na del usuario del diccionario de s´ı mbolos . 6vensim . dictionaryPassword =< Password > 7# Propiedad de tipo boolean que dicta si se hace registro de las respuestas del diccionario de s´ı mbolos o no , por defecto es false . 8vensim . logServerMessages = true 9# Nombre del archivo de salida del registro de la ejecuci ´on, si no se a~n ade esta propiedad , el registro se realizar ´a por la salida estandar . 10 vensim . logFile = log .txt Fragmento de c´odigo 4.4: Propiedades propias del plugin del fichero sonarproject.properties Modificando los Quality Profile de SonarQube Dentro de SonarQube existen una serie de perfiles de calidad. ´ Estos se utilizan para poder definir qu´e reglas se quieren utilizar en qu´e momentos y cu´ales no y para qu´e lenguajes. Es una funcionalidad muy ´util para cuando en un proyecto existen varios grupos trabajando sobre un mismo conjunto de archivos, pero cada uno sobre una tem´atica diferente, podr´ıan existir varios Quality Profiles, cada uno de ellos con las reglas pertinentes para cada trabajador. A parte de poder activar o desactivar reglas, tambi´en se pueden cambiar par´ametros de ellas si el plugin lo soporta. En la versi´on del plugin de la que se parte, solo existe una regla que est´e parametrizada, se trata de la regla de control de los n´umeros m´agicos, la cual permite elegir un umbral que indique el n´umero de repeticiones m´aximas que se pueden dar en un n´umero antes de que este sea descrito como fallo. 4.2. Estructura de los archivos de salida generados En el plugin original existe un archivo que se genera al acabar la ejecuci´on de un an´alisis. En dicho archivo se encuentra toda la informaci´on relativa a los s´ımbolos detectados en los modelos que se haya analizado. La estructura que tiene es la que se muestra en el Fragmento de c´odigo 4.5. Se puede ver c´omo exporta todos los datos extra´ıdos de cada s´ımbolo como son el nombre, tipo, l´ıneas de aparici´on, dependencias, unidades y comentarios. 1[ 2{ 3" file ": " WILIAM . mdl ", 50
CAP´ ITULO 4. AN ´ ALISIS 4"symbols": { 5"\"%_PHS_overcapacity_vs_potential\"": { 6" type ": " VARIABLE ", 7" lines ": [ 82 9], 10 "dependencies": [ 11 "Available_FE_elec_stored_PHS_TWh", 12 ], 13 " units ": " percent ", 14 " comment ": " Overcapacity as a percentage of the total installed capacity over the \ rmaximum potential . If no overcapacity , then =100 %." , 15 } 16 } 17 ] Fragmento de c´odigo 4.5: Estructura original del archivo generado symbolTable.json Este archivo generado recibe el nombre de symbolTable.json. Este archivo se utiliz´o para validaci´on con programadores Vensim que revisaran un modelo descrito en un .mdl y los datos extra´ıdos por el plugin. 4.3. An´alisis inicial de posibles modificaciones Teniendo en cuenta los nuevos requisitos generados para este TFG que pueden ser encontrados en la Secci´on 2.1. Existen diversas modificaciones que tienes que ser realizadas al plugin actual. A continuaci´on se explicar´an cuatros cambios de los m´as importantes. En esta secci´on se analizar´a qu´e cambios se deben hacer, pero no se explicar´a la forma de su implementaci´on, para poder ver como se ha llevado a cabo la implementaci´on puede leerse en el Cap´ıtulo 6. 4.3.1. An´alisis de la gram´atica Uno de los principales cambios en la gram´atica es extenderla para poder hacer el reconocimiento l´exico y sint´actico de la secci´on donde se declaran las vistas. Para poder hacer este an´alisis, primero es necesario explicar cu´al es la estructura l´exica y sint´actica de las vistas. La estructura de las vistas puede dividirse en cuatro bloques [59]: Separador Al inicio de la declaraci´on de todas las vistas encontramos un separador, en la versi´on de Vensim utilizada en LOCOMOTION puede verse en el Fragmento de c´odigo 4.6 1\\\ - - -/// Sketch information - do not modify anything except names 2V300 Do not put anything below this subsection - it will be ignored 51
5.1. ESTRUCTURA DE LAS PETICIONES AL DICCIONARIO DE DATOS DEL PROYECTO qaAddSymbolsDefinition Este endpoint tambi´en ha sido modificado. Se ha a˜nadido la misma estructura relacionada con los Excels descrita anteriormente y, aparte, al trabajar ahora con m´odulos de una forma m´as predominante, se decide a˜nadir el nombre del m´odulo dentro de la definici´on de cada s´ımbolo y no de manera global en la petici´on, de este modo en una ´unica petici´on se podr´ıan enviar todos los s´ımbolos a inyectar. De igual manera que en el caso de qaGetSymbolDefinition se han eliminado elementos en la petici´on que no se identificaban correctamente como s´ımbolos. En este caso se ha eliminado el env´ıo de ´ındices por esta v´ıa. La respuesta no se ha alterado. La nueva estructura de la petici´on a este endpoint puede ser vista en el Fragmento de C´odigo C.4. qaGetIndexesDefinition Este es un nuevo endpoint. Como su nombre indica, este punto de conexi´on se utiliza para recibir informaci´on relativa a los ´ındices guardados en el diccionario de datos del proyecto. En el plugin inicial esta informaci´on es enviada en la respuesta de qaGetSymbolDefinition. Al haber sido eliminada dicha informaci´on de la respuesta de que se obtiene de qaGetSymbolDefinition, es necesario la creaci´on de este nuevo endpoint. La petici´on en este caso es una petici´on de tipo GET. La respuesta devuelve un array con todos los ´ındices existentes en el diccionario de datos del proyecto. La estructura que tiene esta respuesta puede ser encontrada en el Fragmento de C´odigo C.5. qaAddIndexesDefinition Se necesita un sistema para poder inyectar ´ındices en el diccionario de datos del proyecto. Inicialmente estos eran enviados mediante la petici´on a qaAddSymbolDefinition. Sin embargo, al haber sido eliminado de ah´ı, ahora se necesita un nuevo endpoint. La estructura de la petici´on es similar a la de la respuesta de qaGetIndexesDefinition y se puede encontrar descrita en el Fragmento de C´odigo C.6. La respuesta estar´a vac´ıa si todo ha sido inyectado correctamente, o contendr´a un mensaje de error por cada ´ındice que sea err´oneo. qaGetCategories Con este servicio sucede lo mismo que en el caso de qaGetIndexesDefinition. Exist´ıa en qaGetSymbolDefinition originalmente, pero ahora se ha extra´ıdo y generado un endpoint nuevo. La petici´on es de tipo GET, por lo que no tiene ninguna informaci´on extra sobre qu´e categor´ıas se desea solicitar. La respuesta devuelve todas las categor´ıas almacenadas en el diccionario de datos del proyecto. Su estructura puede verse en el Fragmento de C´odigo C.7. En el proyecto LOCOMOTION solo se permite un nivel de jerarqu´ıa en las categor´ıas, es por ello que este plugin solo permite categor´ıas y subcategor´ıas de esas categor´ıas. 58
CAP´ ITULO 5. DISE ˜ NO qaAddCategories Con el nuevo plugin se podr´an descubrir a partir del c´odigo del archivo .mdl las categor´ıas que existen en los modelos analizados. Es por ello que ahora es necesario tener alg´un modo de poder inyectarlos en el diccionario de s´ımbolos. Para ello se crea este endpoint el cual, usando una sintaxis id´entica a la utilizada en las respuestas de qaGetCategories, por ello su estructura se puede ver en el mismo Fragmento de C´odigo de c´odigo C.7. Al igual que el resto de endpoints utilizados para la inyecci´on de elementos, la respuesta estar´a vac´ıa si est´a todo correcto, o una lista de errores de las categor´ıas que no se han podido inyectar. qaGetModules Este endpoint es generado a causa de haber sido extra´ıdo la obtenci´on de m´odulos de qaGetSymbolDefinition. La petici´on es de tipo GET si ninguna informaci´on extra. La estructura de la respuesta se puede encontrar en el Fragmento de C´odigo C.8 qaAddModules Al igual que con las categor´ıas, el plugin final podr´a extraer los m´odulos de las vistas analizadas de los modelos de Vensim. Por tanto, para mantener el m´aximo de informaci´on en el diccionario de s´ımbolos, se crear´a una forma de inyectar estos nuevos m´odulos. La petici´on tiene la misma estructura que qaGetModules que puede ser encontrada en el Fragmento de C´odigo C.8. La respuesta sigue la misma t´ecnica que el resto, vac´ıa si todo se ha inyectado correctamente, o una lista de errores de los m´odulos que no hayan podido ser inyectados. qaGetAcronyms Actualmente seg´un las reglas de nombrado de LOCOMOTION, los s´ımbolos de tipo variable no pueden tener may´usculas en su nombre a excepci´on de cuando son acr´onimos. Esta parte de reconocer acr´onimos a la hora de verificar nombres ser´a a˜nadida nueva en el plugin y, por ende, es necesario una forma de recuperar del diccionario de datos cu´ales son los acr´onimos permitidos en el proyecto. Para ello se crea este endpoint, el cual, recibe una petici´on de tipo GET, y devuelve una lista completa de todos los acr´onimos almacenados en el diccionario. La estructura de la respuesta se puede encontrar en el Fragmento de C´odigo C.9. No existe un servicio para poder inyectar acr´onimos autom´aticamente. Esto se debe a que se decidi´o que era preferible a˜nadir los v´alidos manualmente en el diccionario de datos a tener que estar filtrando por todos los falsos positivos que se pudiesen dar si se automatizase. qaGetUnitSystem En LOCOMOTION existe un conjunto de unidades oficiales. A esto le llamamos el Sistema de Unidades del proyecto. Estas son las ´unicas unidades que puede tener cualquier s´ımbolo del modelo. Para poder verificar esta condici´on, es necesario tener una 59
5.2. ESTRUCTURA DE LOS ARCHIVOS DE SALIDA GENERADOS forma de recuperar cu´ales son estas unidades v´alidas. Para ello se crea este punto de conexi´on, el cual con una petici´on de tipo GET, devuelve la lista de todas las unidades v´alidas que existen en el diccionario de datos del proyecto. La estructura de la respuesta puede verse en el Fragmento de C´odigo C.10. No existe una forma automatizada de inyectar estas unidades. Esto se debe a que este tipo de informaci´on no es obtenible en el modelo, si no que tiene que ser la direcci´on del proyecto quien decida cu´ales son las unidades a usar y las inserten manualmente en el diccionario de datos mediante el cliente web. En la figura 5.1 se puede ver un diagrama que representa la nueva API del diccionario de s´ımbolos. Figura 5.1: Diagrama de la API del diccionario de s´ımbolos. 5.2. Estructura de los archivos de salida generados Teniendo en cuenta todos los datos que se van a poder extraer gracias al nuevo plugin, se actualiza la estructura del archivo generado symbolTable.json para que pueda contener todos estos nuevos datos. En el Fragmento de C´odigo 5.1 puede encontrarse esta nueva estructura. 60
CAP´ ITULO 5. DISE ˜ NO Adem´as, es necesario dise˜nar la estructura para el nuevo archivo que exponga las diferencias existentes ente el an´alisis en local y el diccionario de s´ımbolos. En el Fragmento de C´odigo 5.2 se puede encontrar la estructura de este nuevo archivo. Este archivo recibir´a el nombre dictionaryDiff.json 1[ 2{ 3" file ": " WILIAM . mdl ", 4"symbols": { 5"\"%_PHS_overcapacity_vs_potential\"": { 6" type ": " VARIABLE ", 7" lines ": [ 82 9], 10 "dependencies": [ 11 "Available_FE_elec_stored_PHS_TWh", 12 ], 13 " primary ": " energy - electricity - PHS_generation ", 14 "shadows": [ 15 " energy - electricity - PHS_generation " 16 ], 17 " units ": " percent ", 18 " comment ": " Overcapacity as a percentage of the total installed capacity over the \ rmaximum potential . If no overcapacity , then =100 %." , 19 " group ": " null ", 20 " notValidBecause ": " ViewNameCheck ", 21 " isFiltered ": false , 22 "indexes": [ 23 " REGIONS_I " 24 ] 25 } 26 }, 27 " views ": [ 28 { 29 " module ": " land_and_water ", 30 " lines ": [ 31 38316 32 ], 33 " category ": " land ", 34 " subcategory ": " RES_land_requirements " 35 } 36 ], 37 "modules": [ 38 { 39 " name ": " energy . perception_PE_scarcity ", 40 " notValidBecause ": " ViewNameCheck ", 41 " lines ": [ 42 31039 43 ] 44 } 45 ], 46 " categories ": [ 47 { 48 " name ": "COAL ", 49 " lines ": [ 50 40357 51 ], 52 " level ": 1, 53 " super ": null , 61
5.3. ESTRUCTURA DEL ARCHIVO DE CONFIGURACI ´ ON 54 " notValidBecause ": " CategoryDuplicatedCheck " 55 } 56 ] 57 } 58 ] Fragmento de c´odigo 5.1: Estructura nueva del archivo generado symbolTable.json 1[ 2{ 3" file ": " WILIAM . mdl ", 4"symbols": { 5" missmatches ": {} , 6" not_found_in_DB ": [], 7" not_found_in_local ": [] 8}, 9"indexes": { 10 " missmatches ": {} , 11 " not_found_in_DB ": [], 12 " not_found_in_local ": [] 13 }, 14 "indexes_values": { 15 " missmatches ": {} , 16 " not_found_in_DB ": [], 17 " not_found_in_local ": [] 18 }, 19 "modules": { 20 " not_found_in_DB ": [], 21 " not_found_in_local ": [] 22 }, 23 " categories ": { 24 " missmatches ": {} , 25 " not_found_in_DB ": [], 26 " not_found_in_local ": [] 27 } 28 } 29 ] Fragmento de c´odigo 5.2: Estructura nueva del archivo generado dictionaryDiff.json 5.3. Estructura del archivo de configuraci´on Para poder cumplir con los requisitos del proyecto es necesario generar un nuevo conjunto de propiedades en el archivo de configuraci´on de SonarQube, la lista con las nuevas propiedades puede encontrarse en el Fragmento de C´odigo 5.3. 1vensim . dictionary . getDiff 2vensim . dictionary . inject 3vensim . dictionary . inject . modules 4vensim . dictionary . inject . categories 5vensim . dictionary . inject . symbols 6vensim . view . module . name 7vensim . view . module . separator 8vensim . view . category . separator 62
CAP´ ITULO 5. DISE ˜ NO 9vensim.auxiliaryFiles.directoryName Fragmento de c´odigo 5.3: Nuevas propiedades a˜nadidas a sonar scanner Para una mayor facilidad a la hora de saber c´omo usar las nuevas propiedades, se genera una documentaci´on que explicar para qu´e sirve cada una de ellas y toda esta informaci´on se podr´a utilizar como plantilla de este archivo de propiedades en el futuro. La plantilla de la configuraci´on puede ser encontrada en el Fragmento de C´odigo A.2 en el Anexo 1. 5.4. Estructura del c´odigo y paquetes Para poder hacer la implementaci´on de todos los nuevos requisitos de este proyecto es necesario crear nuevas clases y paquetes. La estructura que tendr´a el nuevo plugin puede ser encontrada a continuaci´on en esta secci´on y se presenta utilizando diagramas de clases y de paquetes. Se utilizar´a un esquema de colores generado al final del proyecto para representar cu´al es el estado de cada clase o paquete: Amarillo Clases o paquetes que ya exist´ıan en el plugin original y no han sido modificados. Naranja Clases o paquetes que ya exist´ıan en el plugin original y que han sido modificados pero de sin a˜nadir funcionalidad nueva por si mismo. Se podr´ıa decir que son modificaciones leves o modificaciones que ocurren en consecuencia de otras. Azul Clases o paquetes que ya exist´ıan pero que han sido altamente modificados para a˜nadir nuevas funcionalidades. Verde Clases o paquetes completamente nuevos. En la figura 5.2 se muestra el diagrama de paquetes del plugin. Posteriormente se tienen los diagramas de clases de cada paquete, en la figura 5.3 el del paquete model, en la figura 5.4 el del parser, en la figura 5.5 el del plugin, en la figura 5.6 el del rules, en la figura 5.7 el del service y en la figura 5.8 el del utilities. 63
5.4. ESTRUCTURA DEL C ´ ODIGO Y PAQUETES Figura 5.2: Diagrama de paquetes. 64
CAP´ ITULO 5. DISE ˜ NO Figura 5.3: Diagrama de clases del paquete model. Figura 5.4: Diagrama de clases del paquete parser. 65
5.4. ESTRUCTURA DEL C ´ ODIGO Y PAQUETES Figura 5.5: Diagrama de clases del paquete plugin. Figura 5.6: Diagrama de clases del paquete rules. 66
CAP´ ITULO 5. DISE ˜ NO Figura 5.7: Diagrama de clases del paquete service. Figura 5.8: Diagrama de clases del paquete utilites. 67
6.3. HISTORIA DE USUARIO 3 guraci´on de sonar-scanner. La lista con todas las configuraciones posibles de este plugin puede encontrare en la Secci´on 4.3.4. En este caso se utilizar´a la clave vensim.view.module.name Si el usuario ha seleccionado un m´odulo a filtrar, ser´a necesario iterar por la lista de s´ımbolos comprobando cu´ales pertenecen a ese m´odulo, ya sean primarios o secundarios, y marcando cu´ales deben ser filtrados. La funci´on responsable de aplicar este filtro puede verse en el Fragmento 6.8. 1public static void filterModule ( SymbolTable table , String moduleName ) { 2for ( Symbol symbol : table . getSymbols () ) { 3boolean filtered = true; 4for ( Module module : symbol . getModules () ) { 5if ( module . getName () . equals ( moduleName )) { 6filtered = false ; 7break ; 8} 9} 10 symbol . setFiltered ( filtered ); 11 } 12 } Fragmento de c´odigo 6.8: Filtrado de s´ımbolos por modulo Se decide marcarlos como filtrados, y no borrarlos, por el hecho de que existen dependencias entre s´ımbolos a la hora de comprobar las reglas de calidad, por lo que si en este momento los s´ımbolos filtrados fuesen borrados, podr´ıa haber tanto falsos positivos como falsos negativos a la hora de comprobar las reglas. Una vez se tienen marcados cu´ales elementos est´an filtrados y cu´ales no, es necesario realizar una comprobaci´on a la hora de generar las issues que compruebe esta propiedad de los s´ımbolos. Esto se lleva a cabo utilizando la interfaz existente que implementan todas las reglas de calidad llamada VensimCheck. Se a˜nade una funci´on llamada addIssue la cual es la responsable de a˜nadir una issue a la lista de issues cuando sea necesario. Como se quiere a˜nadir una funci´on ya implementada, se transforma la interfaz y se convierte en una clase abstracta, esta clase puede ser encontrada en el Fragmento de c´odigo 6.9. 1public abstract class VensimCheck { 2 3abstract void scan ( VensimVisitorContext context ); 4 5public void addIssue ( VensimVisitorContext context , Issue issue , boolean isFiltered ){ 6if (! isFiltered ){ 7context . addIssue ( issue ); 8} 9 10 } 11 } Fragmento de c´odigo 6.9: Clase abstracta padre de todas las clases de reglas de control de calidad Por otra parte, cuando existe un filtro en activo, es necesario tambi´en restringir los elementos que se inyectan en el diccionario de datos del proyecto. Solo se deben inyectar el 74
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS m´odulo filtrado y sus s´ımbolos. Para llevar esto a cabo, se decide que la mejor opci´on es modificar la clase que almacena la informaci´on sobre las vistas ViewTable y simular que solo se ha detectado el m´odulo a filtrar. La manera de simularlo se puede encontrar en el Fragmento 6.10 1if (! moduleName . isEmpty ()) { 2[...] 3viewTable . setModules ( Set .of (new Module ( moduleName ))); 4} Fragmento de c´odigo 6.10: Gesti´on del filtrado por m´odulo en la inyecci´on Esta simulaci´on har´a que solo se inyecten los s´ımbolos y el m´odulo pertinente, la explicaci´on de por qu´e esto es as´ı se puede encontrar en la secci´on de las historias de usuarios 6.1 y 6.2. Una vez a˜nadida esta funci´on y modificadas todas las reglas de control de calidad que deban llamarla para poder a˜nadir issues, se da por concluida la historia de usuario 3. 6.4. Historia de usuario 4 6.4.1. Historia de usuario 4.1 Historia: “Como usuario quiero que no se generen issues si una variable sigue el convenio de nombres, pero contiene en su nombre un acr´onimo definido en el diccionario de datos del proyecto”. Pasamos ahora a hacer la primera mejora de una de las reglas que ya existen en el plugin de inicio. Se trata de un problema que se da a la hora de comprobar los nombres de los s´ımbolos de tipo variable. El nombre de estos siempre tiene que estar escrito en min´usculas, pero existe una excepci´on. Se trata del caso del uso de acr´onimos. Se pueden a˜nadir acr´onimos que est´en validados en el diccionario de datos del proyecto. Esta excepci´on no est´a contemplada en el plugin de partida. Si, por ejemplo, tenemos un acr´onimo valido con nombre H2O y una variable con nombre H2O delta change, en el plugin de inicio se marcar´ıa como que no sigue el convenio de nombres cuando realmente s´ı que lo sigue. Para llevar a cabo la implementaci´on de esta historia de usuario, primero necesitamos recuperar del diccionario de datos del proyecto esa lista de acr´onimos. Esta lista se puede recuperar del diccionario de datos gracias a la nueva incorporaci´on de un endpoint en la API llamado qaGetAcronyms, descrito en la Secci´on 5.1. En el anexo C se puede encontrar la estructura detallada de todos los endpoints que tiene la API. Como se prev´e que se vayan a crear nuevas llamadas a futuros endpoints del diccionario de s´ımbolos, se decide refactorizar la clase responsable de enviar las peticiones (ServiceConnectionHandler) de un modo que existan dos m´etodos (sendPOSTRequest y 75
6.4. HISTORIA DE USUARIO 4 sendGETRequest) que reciban la url de destino y los posibles datos a enviar, de esta forma crear nuevas llamadas a endpoints ser´a solo a˜nadir una nueva funci´on con la url de destino y los datos necesarios. Una vez se recupera esta lista de acr´onimos, es necesario almacenarla de un modo que las reglas de control puedan acceder a ella. Actualmente estas reglas reciben como par´ametro un objeto de tipo VensimVisitorContext el cual contiene informaci´on sobre la tabla de s´ımbolos, tanto la local como la recibida del diccionario de datos, y el ´arbol de derivaciones generado por el parser. En esta clase, teniendo en cuenta que en un futuro se recibir´an m´as datos del diccionario de datos, se decide crear otra nueva clase, DataBaseRepresentation responsable de almacenar toda la informaci´on proveniente del diccionario de s´ımbolos. Por lo tanto en la clase VensimVisitorContext, se sustituye la tabla de s´ımbolos remota por esta nueva clase. DataBaseRepresentation actualmente contiene la tabla de s´ımbolos remota y la tabla de acr´onimos. Teniendo la tabla de acr´onimos ya en VensimVisitorContext, la regla de control de los nombres de las variables ya puede acceder a ella y, por lo tanto, comprobar la existencia de acr´onimos. Para realizar esta comprobaci´on se decide realizar un algoritmo que pase a min´usculas todas las ocurrencias de acr´onimos en una copia del nombre de la variable antes de comprobar si sigue el convenio de nombre. Se decide pasar a min´usculas los acr´onimos y no borrarlos directamente para evitar situaciones en las que se pueda generar dos barras bajas seguidas lo cual no seguir´ıa la convenci´on de nombre. Ej: current H2O stored La funci´on que contiene este algoritmo puede encontrarse en el Fragmento 6.11. Una vez llamada esta funci´on, la regla de control puede continuar con su flujo original con una ligera excepci´on: en el caso de que no se pueda conectar con el diccionario de s´ımbolos sea por el motivo que sea, no se podr´an recuperar los acr´onimos v´alidos, dado este caso pueden surgir gran cantidad de falsos positivos. Por ese motivo, si el plugin no ha podido conectar y recuperar la lista de acr´onimos del diccionario de s´ımbolos, en cada issue de la regla de nombrado de variable que se genere se a˜nadir´a el siguiente comentario: “WARNING: Could not connect with the acronyms database. This variable could be well written.”; 1private boolean checkIfVariableHaveAnAcronym ( String name , List < String > acronyms ){ 2String trimmedName = name; 3for( String acr : acronyms ){ 4if( trimmedName . matches (" .*(^| _ |\") " +acr+"($|_|\") .*")) 5trimmedName = trimmedName . replace (acr , acr . toLowerCase ()); 6} 7return checkVariableFollowsConvention(trimmedName); 8} Fragmento de c´odigo 6.11: Funci´on para comprobar si existen acr´onimos en los nombres de las variables 76
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS 6.4.2. Historia de usuario 4.2 Historia: “Como usuario quiero ser informado si existe alg´un s´ımbolo de tipo lookup el cual tenga incrustada su declaraci´on en el modelo”. Para implementar esta regla primero es necesario entender que es un lookup incrustado. Los lookups se pueden declarar principalmente de dos maneras, con una llamada a una funci´on o embebiendo los datos. En el fragmento 6.12 se pueden ver las dos formas. Se puede apreciar que en el caso del lookup incrustado se tiene todos sus datos en forma de lista y hace que sea dif´ıcil de leer, de ah´ı el motivo de que se quieran evitar. 1Incrustado : 2" Net_coal_extraction_de_Castro_PhD_ - _Scen_I "( 3[(0 ,0) -(10 ,10) ] ,(1985 ,1378.15) ,(1986 ,1422.43) ,(1987 ,1466.37) ,(1988 ,1509.97) ,(1989 ,1553.27\ 4) ,(1990 ,1596.27) ,(1991 ,1639) ,(1992 ,1681.45) ,(1993 ,1723.6) ,(1994 ,1765.43) ,(1995 ,1806.88\ 5) ,(1996 ,1847.87) ,(1997 ,1888.31) ,(1998 ,1928.08) ,(1999 ,1967.04) ,(2000 ,2005.02) ,(2001,\ 62041.85) ,(2002 ,2077.35) ,(2003 ,2111.34) ,(2004 ,2143.61) ,(2005 ,2174.01) ,(2006 ,2202.36) \ 7,(2007 ,2228.55) ,(2008 ,2252.45) ,(2009 ,2274) ,(2010 ,2293.18) ,(2011 ,2310) ,(2012 ,2324.5) \ 8,(2081 ,925.587) ,(2082 ,898.96) ,(2083 ,871.837) ,(2084 ,844.332) ,(2085 ,816.56) ,(2086 ,788.637\ 9,(2087 ,760.675) ,(2088 ,732.784) ,(2089 ,705.067) ,(2090 ,677.624) ,(2091 ,650.543) ,(2092,\ 10 623.906) ,(2093 ,597.787) ,(2094 ,572.25) ,(2095 ,547.351) ,(2096 ,523.135) ,(2097 ,499.642) ,\ 11 (2098 ,476.902) ,(2099 ,454.936) ,(2100 ,433.76) ) 12 ~ MToe/Year 13 ~ | 14 15 Llamando a una funci ´on: 16 17 GDPpc_ANNUAL_GROWTH_SSP2_LT( 18 GET_DIRECT_LOOKUPS ( ’/ model_parameters / economy / economy .xlsx ’, ’World ’, ’ time_index_GDPpc ’\ 19 , ’SSP2_GDP ’)) 20 ~ Dmnl 21 ~ | Fragmento de c´odigo 6.12: Diferencias entre un lookup incrustado y un lookup con una funci´on Para implementar esta historia de usuario se crea una nueva regla de control, llamada EmbeddedLookupCheck y ser´a la responsable de generar issues en los s´ımbolos de tipo lookup incrustados. Se crea tambi´en un nuevo visitor que detecte d´onde hay lookups incrustados. ´ Este es llamado por la propia regla de control. La forma de funcionar se basa en buscar en el ´arbol de derivaciones un bloque de tipo numberList olookupPointList los cuales son las sintaxis utilizadas para incrustar los datos de un lookup y contar la cantidad de repeticiones que tiene, 77
6.4. HISTORIA DE USUARIO 4 esta son a˜nadidas a una tabla junto al s´ımbolo al que pertenecen. Al acabar se devuelve esta tabla a la regla. Para tener en cuenta la posibilidad de filtrado por m´odulo, es necesario incluir la tabla de s´ımbolos en el visitor. En el Fragmento 6.13 se puede ver como se marcan a filtrar los lookups incrustados. 1@Override 2public Void visitLhs ( ModelParser . LhsContext ctx ) { 3 4if (symbols == null) { 5logger.unique(" Symbol table unassigned in EmbeddedLookupVisitor " , LoggingLevel.INFO); 6} 7else if (! symbols . hasSymbol ( ctx .Id () . getText () )) { 8logger . error (" Found symbol \" " + ctx .Id (). getText () + "\" that is not in the symbol table " ); 9} 10 else { 11 Symbol symbol = symbols . getSymbol ( ctx . Id (). getText () ); 12 isSymbolFiltered = symbol . isFiltered (); 13 } 14 return null ; 15 } Fragmento de c´odigo 6.13: Filtrado de lookups incrustados Cuando la regla recibe la lista, itera sobre ella anotando issues en todos los s´ımbolos en los que se ha detectado un conjunto de datos incrustado. La gravedad de la issue depende del n´umero de datos incrustados. La regla tiene un l´ımite en el cual pasa de ser una incidencia de tipo INFO a una MAJOR, este l´ımite se parametriza para poder ser modificado en un quality profile. 6.4.3. Historia de usuario 4.3 Historia: “Como usuario quiero ser informado si existe alg´un s´ımbolo dentro del grupo de control que no sea de control y viceversa”. Esta historia de usuario usa el concepto de grupo [58]. Un grupo en Vensim permite realizar agrupaciones de s´ımbolos. Por defecto existe el grupo de control el cual contiene las variables que existen en un modelo de Vensim por defecto. En el Fragmento de c´odigo 6.14 se pude ver la sintaxis de un grupo en un modelo. Un s´ımbolo pertenece al grupo m´as pr´oximo superior. 1******************************** 2Control 3********************************~ 4Variables relating to vensim control 5| Fragmento de c´odigo 6.14: Sintaxis de un grupo en un modelo 78
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS Para llevar a cabo la implementaci´on, se amplia RawSymbolVisitor para que guarde los grupos en los s´ımbolos. Para ello cada vez que se detecta un grupo en el modelo se guarda en el visitor para poder a˜nadirlo en todos los s´ımbolos pr´oximos hasta encontrar el siguiente grupo que sobrescriba este grupo. Existe un caso especial al principio del modelo y es que puede haber s´ımbolos que no pertenecen a ning´un grupo. El grupo es guardado en un nuevo atributo de los s´ımbolos. Con esta informaci´on almacenada se puede crear la nueva clase para la regla (SymbolGroupCheck) la cual itera por toda la lista de s´ımbolos comprobando si cada s´ımbolo est´a en un grupo adecuado o no. Los s´ımbolos que deben aparecer exclusivamente en el grupo de control se parametr´ızan para que estos puedan ser modificados si en un futuro cambian. Por defecto son los siguientes: TIME TIME STEP INITIAL TIME FINAL TIME SAVEPER La l´ogica que utiliza la regla es bastante directa, generar una issue en un s´ımbolo cuando este est´a en el grupo de control, pero no es uno de los s´ımbolos permitidos, o bien cuando el s´ımbolo no aparece en el grupo de control, pero s´ı que es uno de los s´ımbolos que deber´ıa. 6.4.4. Historia de usuario 4.4 Historia: “Como usuario quiero ser informado si existe alguna vista que no siga las reglas de nombrado”. Esta historia de usuario necesita la creaci´on de una nueva regla, el nombre de la clase asignada nueva es ViewNameCheck. Esta nueva regla utiliza la tabla de vista, que es iterada para comprobar las vistas una a una. Las vistas tienen informaci´on sobre su m´odulo y su(s) categor´ıa(s), por lo que para comprobar si el nombre es v´alido se comprueba si los nombres de los m´odulos y de las categor´ıas son v´alidos. En el Fragmento 6.15 se puede ver la funci´on para realizar la validaci´on. Esta comprobaci´on utiliza una expresi´on regular parametrizada. 1private boolean generateIssue ( View view ) { 2if (view . getModule () == null || ! view . getModule (). getName () . matches ( getRegexp ())) 3return true ; 4 79
6.4. HISTORIA DE USUARIO 4 5if (view . getCategory () == null || ! view . getCategory () . getName (). matches ( getRegexp ())) 6return true ; 7return view . getSubcategory () != null && ! view . getSubcategory () . getName () . matches ( getRegexp ()); 8} Fragmento de c´odigo 6.15: Validaci´on del nombre de las vistas Si una vista no tiene un nombre correcto debe ser invalidada y todos sus s´ımbolos tambi´en. No se debe invalidar autom´aticamente tambi´en el m´odulo o la categor´ıa ya que estos pueden estar bien escritos. Para ello es necesario volver a comprobar los nombres antes de invalidarlos. En el Fragmento 6.16 se puede ver como cuando se invalida una vista, se invalidan autom´aticamente los s´ımbolos y en el Fragmento 6.17 se puede ver c´omo se comprueba si se puede invalidar el m´odulo o las categor´ıas. 1public class View extends IssuableAbs { 2[...] 3@Override 4public void setAsInvalid ( String invalidReason ) { 5super .setAsInvalid(invalidReason); 6primarySymbols . forEach ( symbol -> symbol . setAsInvalid ( invalidReason )); 7} 8} Fragmento de c´odigo 6.16: Invalidaci´on autom´atica de los s´ımbolos primarios en una vista 1private void invalidateView ( View view ){ 2view.setAsInvalid(this. getClass () . getSimpleName ()); 3 4if (view . getModule () != null && ! view . getModule (). getName () . matches ( getRegexp ())){ 5view . getModule () . setAsInvalid ( this. getClass (). getSimpleName () ); 6} 7if (view . getCategory () != null && ! view . getCategory () . getName (). matches ( getRegexp ())){ 8view . getCategory () . setAsInvalid ( this. getClass (). getSimpleName ()); 9} 10 if (view . getSubcategory () != null && ! view . getSubcategory (). getName () . matches ( getRegexp ())){ 11 view . getSubcategory () . setAsInvalid ( this. getClass () . getSimpleName () ); 12 } 13 } Fragmento de c´odigo 6.17: Comprobaci´on de si invalidar el m´odulo y las categor´ıas de una vista En la descripci´on de las issues se desea a˜nadir los separadores que se deber´ıan usar, pero para ello es necesario conocer los separadores que existen entre el m´odulo y la categor´ıa as´ı como entre la categor´ıa y la subcategor´ıa. Para poder acceder a esta informaci´on es necesario modificar los datos que reciben las reglas almacenados en VensimVisitorContext y a˜nadir el objeto que almacena las propiedades declaradas por el usuario en sonar-project.properties. 80
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS 6.4.5. Historia de usuario 4.5 Historia: “Como usuario quiero ser informado si existe alg´un s´ımbolo cuya unidad no se encuentre en el sistema de unidades definido en el diccionario de datos del proyecto”. Para implementar esta regla es necesario incluir una nueva llamada a la API que devuelva el conjunto de unidades v´alidas en el proyecto. Esta comunicaci´on se realiza de manera similar a las ya existentes, El conjunto de unidades v´alidas para el proyecto es almacenado en DataBaseRepresentation para que pueda ser accedido por las reglas. Se crea la regla DictionaryUnitSymbolCheck la cual itera por toda la tabla de s´ımbolos y va comprobando que las unidades de cada uno de ellos est´an contenidas en el conjunto de unidades v´alidas. Existe una excepci´on, los s´ımbolos de tipo function,subscript y los subscript value son ignorados debido a que son adimensionales. 6.4.6. Historia de usuario 4.6 Historia: “Como usuario quiero ser informado si existe alguna copia de un s´ımbolo de tipo subscript y no siga las reglas de nombrado”. En esta historia de usuario se utiliza parte de la gram´atica que hasta ahora no se utilizaba, se trata de la copia de subscripts. La informaci´on de si un subscript est´a definido como una copia de otro se almacena en una nueva clase que hereda de los s´ımbolos. Se modifica el visitor RawSymbolVisitor para que al detectar la regla de copiar un subscript genere uno nuevo pero con el flag de copia activo. Este subscripts se va a almacenar de la misma manera que el resto de s´ımbolos en la tabla de s´ımbolos. Se crea una nueva regla llamada SubscriptCopyNameCheck que funciona de manera similar al resto de reglas de calidad que comprueban los nombres de los s´ımbolos. Es decir, itera toda la lista de s´ımbolos seleccionando solo los de tipo subscript que sean copias y comprueba mediante una expresi´on regular, que el nombre del s´ımbolo cumpla la convenci´on de nombres. Una cualidad significativa de esta regla es que usa el polimorfismo existente en Java como se puede ver en el Fragmento 6.18 1@Override 2public void scan ( VensimVisitorContext context ) { 3SymbolTable table = context . getParsedSymbolTable () ; 4 5for ( Symbol symbol : table . getSymbols () ) { 6if ( symbol . getType () == SymbolType . SUBSCRIPT ) { 7Subscript subscript = ( Subscript ) symbol ; 81
6.4. HISTORIA DE USUARIO 4 8if ( subscript . isCopy () && ! checkSubscriptNameFollowsConvention ( subscript . getToken () )) { 9[...] 10 } 11 } 12 } 13 } Fragmento de c´odigo 6.18: Utilizaci´on de polimorfismo en la regla SubscriptCopyNameCheck 6.4.7. Historia de usuario 4.7 Historia: “Como usuario quiero ser informado si existe alguna discrepancia entre las referencias a tablas Excel encontradas en local y las referencias guardadas en el diccionario de datos del proyecto”. Esta historia de usuario utiliza la informaci´on que algunos s´ımbolos tienen sobre las referencias a tablas Excel externas que existen, por lo que es necesario extraer esta informaci´on. En la Secci´on de la historia de usuario 6.5 se explica estos datos que se quieren extraer y c´omo se extraen. Para poder realizar esta comprobaci´on es necesario recuperar esta informaci´on de la API del diccionario de datos, por lo que la estructura de qaGetSymbolDefinition es modificada para que contenga la informaci´on sobre los Excels. La estructura de esta llamada se puede ver en el Anexo C. Se modifican las clases y funciones responsables de generar la tabla de s´ımbolos a partir de los datos recibidos del diccionario de datos del proyecto para que a˜nadan la informaci´on referente a los Excel en los s´ımbolos en los que sea necesario. Una vez ya se tiene la informaci´on de los Excels del diccionario, se crea una nueva clase para la regla de control de calidad llamada DictionarySymbolExcelRefMismatchCheck. Esta regla funciona como el resto de reglas que comprueba desigualdades entre el an´alisis local y la informaci´on almacenada en el diccionario de datos del proyecto. Es decir, solo se comprueban si existe la tabla de s´ımbolos del diccionario y cuando es llamada itera la tabla de s´ımbolos buscando por cada uno de ellos su id´entico en la tabla recuperada del diccionario de datos. Si encuentra el s´ımbolo entonces comprueba la igualdad entre las dos instancias de ExcelRef, si no fuesen iguales se genera una issue. 6.4.8. Historia de usuario 4.8 Historia: “Como usuario quiero ser informado si existe alguna subcategor´ıa cuyo nombre no sea ´unico en el conjunto de categor´ıas y subcategor´ıas”. Esta historia de usuario es requerida por una limitaci´on que existe en el diccionario de datos, el cual no permite que existan dos categor´ıas o subcategor´ıas con el mismo nombre. 82
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS Esto se debe a que en el diccionario de datos las categor´ıas son guardadas en una ´unica tabla independientemente de su jerarqu´ıa. Si una categor´ıa es subcategor´ıa de otra simplemente tendr´a una referencia a ella. En esta tabla est´a especificado que los nombres sean ´unicos, es por esto que hay que evitar la duplicaci´on de nombre de categor´ıas independientemente de su nivel jer´arquico. Toda la informaci´on necesaria para implementar esta regla ya est´a almacenada en la clase VensimVisitorContext que reciben todas las reglas como par´ametro a la hora de analizar. Se crea la clase CategoryDuplicatedCheck para implementar esta regla. La l´ogica de esta regla es m´as compleja que el resto por todas las situaciones que se pueden dar. A continuaci´on se describen todas las posibles situaciones detectadas y c´omo se han gestionado: Dos categor´ıas con el mismo nombre: Se trata de la misma categor´ıa, no es una duplicaci´on. Dos subcategor´ıas con el mismo nombre de la misma categor´ıa: Se trata de la misma subcategor´ıa, no es una duplicaci´on. Dos subcategor´ıas con el mismo nombre de distintas categor´ıas: Se trata de una duplicaci´on, es necesario marcar una de las dos como inv´alida y generar una issue. Para elegir cu´al de las dos invalidar, primero se comprueba si hay alguna ya guardada en el diccionario de datos del proyecto. Si una de las dos est´a ya almacenada, se invalida la otra. En caso de que ninguna de las dos est´e en el diccionario de datos, se invalida la primera en aparecer en la lista de subcategor´ıas. Una categor´ıa y una subcategor´ıa con el mismo nombre: Se trata de una duplicaci´on, es necesario marcar una de las dos como inv´alida y generar una issue. Para elegir cu´al de las dos invalidar primero se comprueba si hay alguna ya guardada en el diccionario de datos del proyecto. Si una de las dos est´a ya almacenada, se invalida la otra. En caso de que ninguna de las dos est´e en el diccionario de datos, se invalida la subcategor´ıa. La implementaci´on consta de dos bucles unos primero para las subcategor´ıas y luego otro para las categor´ıas. En el Fragmento 6.19 se pueden ver estos dos bucles. 1while (! subcategoryList . isEmpty () ) { 2Category currentSubcategory = subcategoryList . remove (0) ; 3if ( dbSubcategoryList . contains ( currentSubcategory )) { 4alreadyInDB . add ( currentSubcategory ); 5}else { 6if ( generateIssue ( subcategoryList , categoryList , dbCategoryList , alreadyInDB , currentSubcategory )) { 7[...] 8} 9} 10 } 83
6.6. HISTORIA DE USUARIO 6 ´ındices. Estos son mandados mediante otro servicio llamado qaAddIndexDefinition que no contiene informaci´on sobre el m´odulo. Esta inyecci´on de ´ındices puede ser vista en la secci´on dedicada a la historia de usuario 6.6. 1public void injectNewSymbols (List <Symbol > foundSymbols , List < Module > modules , SymbolTable dbSymbolTable ) { 2[..] 3List < Module > validModules = modules . stream () . filter ( Module :: isValid ). collect ( Collectors . toList () ); 4 5List < Symbol > newSymbols = foundSymbols . stream () 6. filter ( symbol -> ! dbSymbolTable . hasSymbol ( symbol . getToken () . trim () ) && hasToFetchSymbolFromDB ( symbol )) 7. filter ( Symbol :: isValid ) 8. filter ( Predicate . not ( Symbol :: isFiltered )) 9. filter ( symbol -> symbol . getPrimaryModule () != null && validModules . contains ( symbol . getPrimaryModule ())) 10 . collect ( Collectors . toList ()); 11 12 if (! newSymbols . isEmpty ()) { 13 inyectSymbols ( validModules , newSymbols ); 14 }else { 15 logger . info ("No new symbols to inject "); 16 } 17 18 inyectNewIndexes ( foundSymbols , dbSymbolTable ); 19 20 } Fragmento de c´odigo 6.23: Implementaci´on del filtrado en el m´etodo para inyectar s´ımbolos de la clase ServiceController 6.6.3. Historia de usuario 6.3 Historia: “Como usuario quiero que las categor´ıas y subcategor´ıas nuevas detectadas sean inyectadas al diccionario de s´ımbolos del proyecto”. Esta historia de usuario tiene el mismo flujo de trabajo que la historia de usuario 6.1. Tanto la lista de categor´ıas local como la lista de categor´ıas del diccionario de datos se consiguen de la misma forma. La llamada al diccionario de datos en este caso se realiza mediante el servicio qaGetCategories. Existe una diferencia crucial aun as´ı. Esta es la jerarqu´ıa de las categor´ıas, aunque todas sean implementadas por la misma clase. Algunas pueden ser subcategor´ıas de otras, por lo que tienen que estar relacionadas. Los atributos de la clase Category se pueden ver en el Fragmento 6.24. 1public class CategoryImpl extends IssuableAbs implements Comparable < Category >, Category { 2private Category superCategory ; 3private final String name ; 4private Set < Category > subcategories ; 5 90
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS 6[...] 7} Fragmento de c´odigo 6.24: Atributos de la clase Category Como se mencion´o anteriormente, por limitaciones en el diccionario de datos, los nombres de todas las categor´ıas y subcategor´ıas deben de ser ´unico. Para la gesti´on de la jerarqu´ıa, la comunicaci´on con el diccionario de datos se realiza mediante una lista de categor´ıas, cada una de ellas con informaci´on sobre su nombre, su nivel en la jerarqu´ıa (0 significa que no tiene supercategor´ıa) y su supercategor´ıa, si la tuviese. La estructura exacta se puede ver en el Anexo C. Esto implica que es necesario un mecanismo de aplanamiento de las jerarqu´ıas que tienen las categor´ıas y convertirlas en una lista plana. Esta transformaci´on de una estructura jer´arquica de categor´ıas a una estructura en lista se puede ver en el Fragmento 6.25. El aplanamiento solo est´a pensado para cuando existe un ´unico nivel de jerarqu´ıa, requisito que existe en las categor´ıas de LOCOMOTION. 1 2public class ViewTable { 3[...] 4private final CategoryMap categoriesList ; 5 6[...] 7 8public List < Category > getCategories () { 9return categoriesList.getCategories(); 10 } 11 12 public List < Category > getSubcategories () { 13 return categoriesList . getCategories () . stream () . flatMap ( cat -> cat . getSubcategories () . stream ()). collect ( Collectors . toList () ); 14 } 15 16 public List < Category > getCategoriesAndSubcategories () { 17 return Stream . concat ( getCategories (). stream () , getSubcategories (). stream()) 18 . collect ( Collectors . toList ()); 19 } 20 [...] 21 } Fragmento de c´odigo 6.25: Aplanamiento de la jerarqu´ıa de las categor´ıas La gesti´on de los nombres de categor´ıas duplicados ya se realiza en la historia de usuario 4.8 por lo que ahora en la inyecci´on solo hay que preocuparse de si una categor´ıa o subcategor´ıa es v´alida. Una vez que se tiene la lista plana de categor´ıas y subcategor´ıas tanto del an´alisis local como del diccionario de datos, se puede realizar la llamada al servicio de la API qaAddCategories, enviando ´unicamente las categor´ıas v´alidas y que no est´an ya en el diccionario de datos del proyecto. 91
6.6. HISTORIA DE USUARIO 6 6.6.4. Historia de usuario 6.4 Historia: “Como usuario quiero que los s´ımbolos inyectados contengan la categor´ıa y subcategor´ıa a la que pertenecen”. Para llevar a cabo esta historia de usuario se trata simplemente de a˜nadir el campo category en el JSON de cada s´ımbolo que se env´ıa en el servicio qaAddSymbolDefinition. En la historia de usuario 6.2 est´a explicado como se realiza esta adici´on, sustituyendo la idea de m´odulo por la de la categor´ıa. Un punto a tener en cuenta es que el diccionario de datos est´a esperando como dato la categor´ıa m´as inferior en la jerarqu´ıa. Esto se consigue haciendo que cada s´ımbolo guarde la categor´ıas de m´as bajo nivel que la representa. 6.6.5. Historia de usuario 6.5 Historia: “Como usuario quiero que los s´ımbolos inyectados contengan las referencias a tablas excel externas cuando existan en dicho s´ımbolo”. Esta historia de usuario utiliza la informaci´on que algunos s´ımbolos tienen sobre las referencias a tablas Excel externas que existen, por lo que es necesario extraer esta informaci´on. Primero una descripci´on de qu´e se va a extraer y de d´onde. En LOCOMOTION se utilizan varias funciones que sirven para llamar a tablas externas, estas son: GET DIRECT CONSTANTS GET DIRECT LOOKUPS GET DIRECT DATA Hay que tener en cuenta que en Vensim existen aun m´as funciones que se utilizan para esta finalidad, pero las cuales no son utilizadas en LOCOMOTION y por eso no nos centramos en ellas en esta versi´on del plugin. Los argumentos de las tres son los mismos, a excepci´on de GET DIRECT LOOKUPS y GET DIRECT DATA que tienen uno mas. A continuaci´on se explican los par´ametros en com´un teniendo de ejemplo la funci´on GET DIRECT CONSTANTS que se puede ver en el Fragmento 6.26. 1"’a’_demand_projection_minerals_Rest"[materials]= 2GET_DIRECT_CONSTANTS (’ model_parameters / materials / materials . xlsx ’, ’World ’, ’ a_demand_proyection_minerals_rest*’) 3~ 4~ | 92
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS Fragmento de c´odigo 6.26: Declaraci´on de un s´ımbolo con la funci´on GET DIRECT CONSTANTS. Los datos que nos interesan de la funci´on son: Ruta al archivo Excel referenciado: model parameters/materials/materials.xlsx Nombre de hoja en el archivo Excel: World Nombre del rango de celdas que contienen los datos: a demand proyection minerals rest* Por otra parte las funciones GET DIRECT LOOKUPS yGET DIRECT DATA tienen los par´ametros que se pueden ver en el Fragmento 6.27. 1afforestation_program_2020_W : INTERPOLATE ::= 2GET_DIRECT_DATA (’ model_parameters / land_and_water / land_and_water .xlsx ’, ’ World_land ’, 3’time_afforestation_index ’, ’afforestation_program ’) 4~ 5~ | Fragmento de c´odigo 6.27: Declaraci´on de un s´ımbolo con la funci´on GET DIRECT DATA En estas dos funciones se cuenta con un par´ametro m´as que define el nombre del rango de celdas que contiene la informaci´on sobre la serie de coordenadas, en el caso del ejemplo ser´ıa time afforestation index. Para poder almacenar este tipo de informaci´on se crea una nueva clase de datos llamada ExcelRef. Cada instancia de esta clase almacena el nombre de la ruta al archivo Excel y tambi´en un conjunto de tripletas donde se guarda el nombre de la hoja, el rango de celdas donde est´an los datos, y si existe, el rango de celdas donde se encuentra la serie de coordenadas. Se permite que en una instancia puede haber varias tripletas debido a que en Vensim se puede definir m´ultiples referencias como se puede ver en el Fragmento 6.28. 1CF_ini_RES_elec [ hydro ]: INTERPOLATE ::= 2GET_DIRECT_DATA (’ model_parameters / energy / energy . xlsx ’, ’World ’, ’ time_RES_nuclear_index ’\ 3, ’CF_ini_hydro ’) ~~| 4CF_ini_RES_elec [ geot_elec ]= 5GET_DIRECT_CONSTANTS (’ model_parameters / energy / energy . xlsx ’, ’ World ’ , ’ CF_ini_geot_elec ’\ 6) ~~| 7CF_ini_RES_elec [ solid_bioE_elec ]= 8GET_DIRECT_CONSTANTS (’ model_parameters / energy / energy . xlsx ’, ’ World ’ , ’ CF_ini_bioE_elec ’\ 9) ~~| Fragmento de c´odigo 6.28: Multiples llamadas a archivos excel externos 93
6.6. HISTORIA DE USUARIO 6 Una vez se tiene la clase que define las instancia que guardan los datos, se modifica el visitor RawSymbolVisitor para que, cuando en una declaraci´on de s´ımbolo detecte el uso de una de estas tres funciones, extraiga la informaci´on y se asocie con los s´ımbolos pertinentes. Por ´ultimo, se modifica la llamada a qaAddSymbolVisitor para que se pueda a˜nadir esta informaci´on en los s´ımbolos en los que se ha detectado. 6.6.6. Historia de usuario 6.6 Historia: “Como usuario quiero que los ´ındices se inyecten y se recuperen de forma independiente al resto de s´ımbolos”. Para hacer una inyecci´on y recuperaci´on independiente de los ´ındices, es necesario crear dos nuevas peticiones al diccionario de datos. En este caso se definen qaGetIndexesDefinition yqaAddIndexesDefinition, en el Anexo C se puede encontrar la estructura de sendos servicios. Al no querer inyectar elementos duplicados y como cada´ındice tiene un nombre y una lista de valores posibles, es necesario comprobar si cada´ındice detectado existe ya en el diccionario y de ser as´ı comprobar si todos los valores del ´ındice detectado est´an en el diccionario, si alguno de los valores detectados no est´a en el diccionario de s´ımbolos, es necesario inyectar todo el ´ındice. En el Fragmento 6.29 se muestra c´omo se realiza esta l´ogica de elecci´on de que ´ındices inyectar. 1for ( Symbol index : filteredindexes ) { 2if ( dbSymbolTable . hasSymbol ( index . getToken () .trim () )) { 3Symbol dbIndex = dbSymbolTable . getSymbol ( index . getToken () ); 4 5List < Symbol > localDependencies = index . getDependencies (). stream (). sorted () . collect ( Collectors . toList () ); 6List < Symbol > dbDependencies = dbIndex . getDependencies () . stream () . sorted () . collect ( Collectors . toList () ); 7Boolean toSend = false ; 8int i = 0; 9while (i < lo cal Dep end enc ies . size () && ! toSend ) { 10 if (! localDependencies .get(i). dbEquals ( dbDependencies . get(i))) { 11 indexesToSend . add ( index ); 12 toSend = true; 13 } 14 i++; 15 } 16 17 }else { 18 indexesToSend . add ( index ); 19 } 20 } Fragmento de c´odigo 6.29: L´ogica para seleccionar que ´ındices inyectar 94
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS 6.7. Historia de usuario 7 Historia: “Como usuario quiero que al ejecutar un esc´aner se generen documentos auxiliares que contengan informaci´on relativa a los elementos que contiene el modelo”. El plugin original realiza la generaci´on de un archivo llamado symbolTable.json el cual contiene informaci´on (nombre, unidades, dependencias, comentario, tipo y l´ıneas de aparici´on) de cada s´ımbolo de cada modelo, su estructura se puede ver en el fragmento 4.5. Para realizar esta historia de usuario es necesario modificar la estructura de salida de este archivo y, adem´as, crear un archivo nuevo que contenga las diferencias encontradas entre el an´alisis local y el diccionario de datos del proyecto. El nuevo archivo ser´a llamado dictionaryDiff.json. Las estructuras de estos nuevos archivos pueden ser encontradas en 5.1 para symbolTable.json y en 5.2 para dictionaryDiff.json. Por lo tanto hay tres pasos a realizar: Modificar la clase responsable de generar symbolTable.json JsonSymbolTableBuilder es la clase responsable de generar el archivo de salida con los s´ımbolos detectados. Las modificaciones en esta clase se basan en ampliar la generaci´on del JSON de salida, replicando las estructuras originales de esta clase. Iterando primero por la tablas de s´ımbolos de los cuales se extraen todo sus atributos y se transforman en un objeto JSON. Y despu´es por la tabla de las vistas en la cual se extrae tambi´en informaci´on de los atributos como pueden ser su m´odulo y categor´ıa. Crear la clase responsable de generar dictionaryDiff.json JsonDictionaryDiffBuilder es el nombre de la nueva clase, funciona de forma similar a la clase anterior, con la diferencia de que ´esta necesita comprobar qu´e elementos son diferentes entre el an´alisis local y el diccionario de datos del proyecto. Se comprueba qu´e elementos solo existen en el an´alisis local y qu´e elementos solo existen en el diccionario de datos. Se considera que dos s´ımbolos son el mismo si tienen el mismo nombre y estos serian iguales si el resto de sus propiedades son iguales. En el Fragmento de C´odigo 6.30 se puede ver el algoritmo que clasifica los s´ımbolos en estos tres grupos. 1Js onO bje ctB uil der miss mat chBuil der = Json . crea teObjectBui lder () ; 2JsonArrayBuilder missingLocalBuilder = Json . createArrayBuilder (); 3JsonArrayBuilder missingDBBuilder = Json.createArrayBuilder(); 4 5for ( Symbol symbol : localSymbols ) { 6 7if ( dbTable . hasSymbol ( symbol . getToken () )) { 8Symbol dbSymbol = dbTable . getSymbol ( symbol . getToken ()); 9 10 if (! symbol . dbEquals ( dbSymbol )) { 11 missmatchBuilder.add(symbol.getToken(), symbolDiffToJson( symbol , dbSymbol )); 12 } 13 dbTable . removeSymbol ( symbol . getToken () ); 14 }else { 15 if( symbol . isValid () ) 95
6.8. REFACTORIZACI ´ ON Y CALIDAD DEL C ´ ODIGO 16 missingDBBuilder . add ( symbol . getToken () ); 17 } 18 } 19 20 List < Symbol > dbSymbols = dbTable . getSymbols (). stream () . filter ( symbol -> ! ignoreTypes . contains ( symbol . getType () )). sorted ( Comparator . comparing ( Symbol :: getToken )). collect ( Collectors . toList () ); 21 22 for ( Symbol dbsymbol : dbSymbols ) { 23 missingLocalBuilder . add ( dbsymbol . getToken ()); 24 } Fragmento de c´odigo 6.30: Algoritmo para clasificar los s´ımbolos al generar el archivo de diferencias. Crear clase responsable de gestionar la generaci´on de archivos. OutputFilesGenerator es la nueva clase responsable de esta gesti´on. En el plugin original esta responsabilidad reca´ıa sobre la clase que creaba el ´unico archivo que se generaba, pero en la actualidad al existir dos distintos es recomendable que se encargue otra clase. De esta forma, adem´as, se facilita el poder crear nuevos archivos en el futuro. Esta clase se encarga de recibir las tablas necesarias para generar todos los archivos de salida y llama a las clases responsables de esta generaci´on d´andoles a cada una de ellas las tablas que necesita para poder crear su archivo. Con estas tres tareas completadas, solo queda que una vez a finalizado el an´alisis del plugin se pasen las tablas de s´ımbolos y vistas a OutputFilesGenerator y mandar la creaci´on de archivos externos. 6.8. Refactorizaci´on y calidad del c´odigo A lo largo del desarrollo se han llevado a cabo modificaciones en la calidad tanto del c´odigo original como del c´odigo nuevo desarrollado. En esta secci´on se hablar´a de las tres m´as interesantes desde el punto de vista del estudiante. 6.8.1. Env´ıo de peticiones al diccionario de datos ServiceConnectionHandler es la clase responsable de enviar peticiones al diccionario de datos. En el plugin original solo tenia tres m´etodos, autenticarse, recibir s´ımbolos del diccionario y enviar s´ımbolos al diccionario. Entre el segundo y tercer m´etodo exist´ıa un duplicidad en el c´odigo. Esta duplicidad se ver´ıa muy agravada si se empezasen a a˜nadir los nuevos m´etodos necesarios para realizar las peticiones al resto de nuevos servicios que se ha necesitado crear. Por esta raz´on se decidi´o abstraer la l´ogica del env´ıo de peticiones, tanto GET como POST a dos m´etodos privados de la clase, con incluso un tercer m´etodo en com´un a estos dos que recibe la petici´on generada y la manda. 96
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS Gracias a esta refactorizaci´on, al crear un nuevo m´etodo destinado a comunicarse con el diccionario de datos se pas´o de necesitar m´as de 40 l´ıneas de c´odigo mayoritariamente duplicado, a la llamada de una funci´on que contiene el nombre de servicio de destino y los posibles datos. En el Fragmento de C´odigo 6.31 se puede ver una llamada GET y una llamada POST utilizando los nuevos m´etodos. 1sendPOSTRequest ( serviceUrl , " qaAddSymbolsDefinition ", symbols , token ); 2sendGETRequest ( serviceUrl , "qaGetModules", token ) ; Fragmento de c´odigo 6.31: Llamadas utilizadas para realizar una petici´on al diccionario de datos. 6.8.2. Gesti´on de creaci´on de categor´ıas Antes de explicar la mejora de calidad del c´odigo y refactorizaci´on es necesario explicar el contexto en el que estamos. Al principio cuando se crearon las categor´ıas, no exist´ıa ning´un tipo de comprobaciones. Cualquier categor´ıas pod´ıa tener cualquier otra supercategor´ıa, por lo que se generar´ıan jerarqu´ıas de m´as de un nivel que no est´an permitidas en LOCOMOTION y tambi´en podr´ıan haber jerarqu´ıas c´ıclicas que no pueden existir. Tambi´en se pod´ıa generar varias veces la misma categor´ıa, creando duplicados de ella. Esto gener´o problemas a la hora de poder invalidar s´ımbolos de categor´ıas err´oneas a la vez de complicar el c´odigo con necesidad de realizar comprobaciones en muchas partes del c´odigo sin estar centralizadas en una. Para mejorar estos problemas se realizaron varios cambios. Primero, se restringi´o la forma de crear relaciones entre categor´ıas, se cambia para que solo se pueda dictaminar que una categor´ıa es hija de otra. En esa llamada se har´a la referencia inversa y se har´an comprobaciones para evitar referenciarse a s´ı mismo o crear jerarqu´ıas de m´as de un nivel de profundidad. En el Fragmento 6.32 se encuentra la implementaci´on de esta funci´on. Con esta funci´on se evitan todos los problemas con la jerarqu´ıa. 1public void addSubcategory ( CategoryImpl subcategory ) { 2if (this.getSuperCategory() != null) { 3throw new IllegalStateException(" Subcategories can ’t have new subcategories "); 4} 5 6if ( subcategory . getSubcategories () != null) { 7throw new IllegalStateException(" Supercategories can ’t be added as subcategories "); 8} 9if ( subcategory . equals ( this)) { 10 throw new IllegalArgumentException(" Category can have himself as subcategory ."); 11 } 12 13 if ( subcategory . getSuperCategory () != null) { 14 throw new IllegalStateException(" Category " + subcategory . getName () + " already have a supercategory : " + subcategory . getSuperCategory () . getName ()); 97
6.8. REFACTORIZACI ´ ON Y CALIDAD DEL C ´ ODIGO 15 } 16 17 subcategory.setSuperCategory(this); 18 if ( subcategories == null) { 19 subcategories = new HashSet < >() ; 20 } 21 this. subcategories . add ( subcategory ); 22 } Fragmento de c´odigo 6.32: Funci´on responsable de a˜nadir a una categor´ıa una subcategor´ıa. Para evitar los problemas de duplicidad, se genera una factor´ıa de categor´ıas la cual gestiona que categor´ıas y subcategor´ıas se han creado ya dentro de un contexto. Esta factor´ıa est´a implementada dentro de la clase CategoryMap. La ´unica manera de poder a˜nadir nuevas categor´ıas en esta estructura es mediante el uso de una funci´on destinada a crear categor´ıas. Esta funci´on antes de crear una nueva comprueba si ya tiene almacenada una con el mismo nombre. Si es as´ı, devuelve una referencia a la ya creada. Para poder a˜nadir subcategor´ıas en estas nuevas categor´ıas es necesario utilizar otra funci´on de CategoryMap la cual utiliza una l´ogica similar a la primera pero esta vez para la creaci´on de subcategor´ıas. Para obligar a que haya que usar estas dos funciones a la hora de gestionar las categor´ıas se crea una interfaz (Category), la cual no da acceso a la adici´on de nuevas subcategor´ıas. La implementaci´on de estas dos funciones se puede encontrar en el Fragmento 6.33. 1public Category createOrSelectCategory ( String categoryName ) { 2if (map . containsKey ( categoryName )) { 3return map.get( categoryName ); 4}else { 5CategoryImpl c = new CategoryImpl(categoryName); 6c.setSubcategories(new HashSet < >() ); 7map .put ( categoryName , c ); 8return c; 9} 10 } 11 public Category addSubcategoryTo ( String category , String subcategory ) { 12 CategoryImpl categoryImpl; 13 if ( getCategory ( category ) == null) { 14 throw new IllegalArgumentException(" Category not found " ); 15 }else { 16 categoryImpl = (CategoryImpl) getCategory(category); 17 } 18 CategoryImpl c = new CategoryImpl(subcategory); 19 categoryImpl . addSubcategory (c); 20 return c; 21 } Fragmento de c´odigo 6.33: Funciones responsables de crear una categor´ıa y una subcategor´ıa. 6.8.3. Gesti´on de invalidar elementos dependientes de uno inv´alido La ultima modificaci´on a comentar es la que se realiza a la forma de invalidar los elementos ya sean s´ımbolos, m´odulos, categor´ıas, etc. 98
CAP´ ITULO 6. IMPLEMENTACI ´ ON Y PRUEBAS Al inicio, si una regla quer´ıa invalidar una categor´ıa por tener mal su nombre, tambi´en ten´ıa que invalidar a todos los s´ımbolos pertenecientes a esta categor´ıa, haciendo que existiesen dependencias innecesarias entre clases. Para arreglar esto se modifica la forma de invalidar cada elemento para que estos tenga la responsabilidad de invalidar a otros elementos que los tengan como dependencia. Para poder hacer esto es necesario primero tener una interfaz en este caso llamada Issuable que define un m´etodo para invalidar. Todos los elementos que pueden ser invalidados implementan esta interfaz. Una vez se tienen todas las clases de los elementos que pueden invalidarse implementando esta nueva interfaz, cualquiera puede llamar a los m´etodos de invalidaci´on del resto sin tener que saber su clase concreta. En el Fragmento 6.34 se puede ver un ejemplo de lo que sucede si se invalida una categor´ıa que debe invalidar a todos los s´ımbolos que existen en ella. 1@Override 2public void setAsInvalid ( String invalidReason ) { 3super .setAsInvalid(invalidReason); 4if( subcategories != null) subcategories . forEach ( symbol -> symbol . setAsInvalid(" Supercategory inheritance : " + invalidReason )); 5} Fragmento de c´odigo 6.34: Funci´on responsable de invalidar una categor´ıa. Esta refactorizaci´on se corresponde con la combinaci´on de dos muy conocidas del Cat´alogo de Refactorizaciones de Fowler [29] llamada Extract interface yUse supertype where possible. 6.8.4. Limpieza de malas pr´acticas Para la calidad del c´odigo se usaron herramientas de an´alisis est´atico de c´odigo. Concretamente se utilizaron dos herramientas, el an´alisis de c´odigo integrado en IntelliJ IDEA y SonarQube para Java. Con la utilizaci´on de estas herramientas se pas´o de tener un proyecto con m´as de 200 code smells y m´as de 10 vulnerabilidades y reducirlos en un 90 % hasta tener menos de 30 code smells con cero bugs detectados y dos vulnerabilidades ´unicas. Estos ´ultimos no se corrigieron debido a que la reestructuraci´on que habr´ıa que hacer para evitar alguno de ellos no compensa teniendo en cuneta su gravedad, por ejemplo, existen bloques de entre 6 a 10 l´ıneas que aparecen duplicados los cuales son marcados como issues. Otro motivo son m´etodos que existen y devuelven resultados que actualmente no se utilizan en el plugin, pero que pueden ser de inter´es en futuras versiones, estos m´etodos y sus respuestas son tambi´en marcados como issues. 99
7.5. SPRINT 3 29/10/2020-11/11/2020) y usado durante el desarrollo como ya ocurr´ıa con el proyecto del que parte este TFG, se actualiza el archivo de gitlab responsable de gestionar el CI/CD. A mitad del Sprint en la reuni´on weekly se informa por parte de la tutora que existen casos en los cuales la gram´atica nueva genera excepciones y no realiza un an´alisis correcto. Un ejemplo de uno de estos casos es la existencia de un n´umero impar de comillas en los comentarios de una vista. A partir de esta reuni´on se decide dar por cerradas las tareas del Sprint actual y generar dos nuevas, se podr´ıa ver como el cierre temprano del Sprint actual y el inicio de uno nuevo, pero se decide mantenerlo en el mismo para tener consistencia en el tiempo de los Sprints a lo largo del proyecto. Durante la segunda semana del Sprint se corrigen los fallos detectados en la gram´atica y se crean nuevos modelos de prueba que tengan en consideraci´on los casos en los cuales la gram´atica fall´o. 7.5. Sprint 3 29/10/2020-11/11/2020) La Tabla 7.4 tiene un resumen de las tareas realizadas durante este Sprint. Tarea Tiempo estimado Tiempo invertido Estado Despliegue versi´on 1.1 2h 45m Completado Recuperaci´on de los acr´onimos del diccionario de datos 10h 9h 35m Completado Documentaci´on 5h 4h 10m Completado Total 17h 14h 30m 100 % Completado Tabla 7.4: Tareas del Sprint 3 Para empezar este Sprint se decide publicar la primera release del nuevo plugin, en este caso la versi´on 1.1 que por ahora solo tiene como nueva funcionalidad el filtrado por m´odulos. La gesti´on del despliegue en el servidor oficial de LOCOMOTION donde se encuentra alojado una instancia en ejecuci´on de SonarQube (gitlab-locomotion.infor.uva.es) es de la tutora, por lo que por mi parte mis responsabilidades son asegurar que la versi´on a publicar es estable y sin fallos detectados. Cuando se tiene la confianza de que la versi´on est´a lista, se hace un merge a la rama master del repositorio remoto y se avisa a la tutora de que ya est´a disponible la versi´on 1.1 para despliegue. Una vez acabados los preparativos para el despliegue se pasa a realizar la siguiente tarea del Sprint, la recuperaci´on de acr´onimos del diccionario de datos. 106
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO Para poder realizar esta lectura de acr´onimos desde el diccionario de s´ımbolos es necesario generar un nuevo punto de conexi´on con la API que actualmente no existe. Al final se decide crear un nuevo punto llamado qaGetAcronyms para as´ı mantener la consistencia de nombre de los puntos que existen actualmente (qaGetSymbolDefinition yqaAddSymbolDefinition). En el ap´endice C se encuentra la estructura de todos los end points de la API al final del desarrollo. Una vez definidos el nombre y la estructura se puede pasar a implementar la recuperaci´on. Para empezar se crea un mock de este end point utilizando dyson. De este modo se pueden hacer ya pruebas reales pese a que todav´ıa no est´e implementado el servicio en la API oficial del diccionario de datos. En la secci´on de implementaci´on de la historia de usuario 4.1 se pueden encontrar consideraciones que se tuvieron en cuenta a la hora de implementar esta recuperaci´on de acr´onimos. Por ´ultimo, en este Sprint se empieza a escribir esta memoria. Se est´a utilizando L A T EXpara escribirla. En el momento de este Sprint mis conocimiento sobre L A T EXson escasos por lo que ser´a necesario destinar un fragmento del tiempo planificado para documentar en aprender como funciona L A T EX. 7.6. Sprint 4 12/11/2020-25/11/2020) La Tabla 7.5 tiene un resumen de las tareas realizadas durante este Sprint. Tarea Tiempo estimado Tiempo invertido Estado Regla de nombrado de variable consciente de los acr´onimos 7h 30m 10h 45m Completado Bug: Las issues de los n´umeros m´agicos no son filtradas 3h 15m 3h 35m Completado Parametrizaci´on de las expresiones regulares de las reglas. 3h 3h 50m Completado Documentaci´on. 2h 1h Completado Total 15h 45m 19h 10m 100 % Completado Tabla 7.5: Tareas del Sprint 4 Por incompatibilidades de agenda con la hora a la que se realizaban las reuniones, se decide cambiar la hora de las reuniones y, por ende, la fecha de inicio y fin de los Sprints, esta cambiar´a de ser los lunes a ser los jueves. Para empezar el Sprint se va a actualizar la regla de comprobaci´on de nombre de variables 107
7.7. SPRINT 5 10/12/2020-23/12/2020) para que tenga en cuenta a los acr´onimos. Tal y como est´a en la actualidad el paso de las tablas de s´ımbolos tanto la local como la del diccionario de datos a las reglas, implica que extender los datos a pasar no sea sencillo, por ello antes de modificar la regla se decide mejorar ese paso de datos. Para ello se crean las clases: DataBaseRepresentation yAcronymList y se modifica la clase VensimVisitorContext para que las utilice. La explicaci´on m´as detallada de esta modificaci´on puede ser encontrada en la secci´on de implementaci´on de la historia de usuario 4.1. Una vez se tienen los datos de los acr´onimos a disposici´on de la regla de nombrado de variables ya se puede implementar el cambio que tambi´en puede encontrarse detallado en la implementaci´on de la historia de usuario 4.1. Cuando se acab´o de implementar el cambio en la regla, se lleg´o a la conclusi´on de que la estructura de paquetes actual del plugin no iba a soportar la creaci´on de nuevas clases almacenadoras de datos como pueden ser las dos nuevas creadas en este Sprint. Por ello se decide crear un nuevo paquete llamado model en el cual se almacenar´an todas las clases cuya responsabilidad sea el almacenamiento de datos. A este nuevo paquete son incorporadas las clases: Symbol,SymbolTable,SymbolType,View,ViewTable,DataBaseRepresentation, AcronymList yVensimVisitorContext. Estas clases estaban anteriormente en el paquete de parser. Una vez hecho este cambio se pasa a arreglar el bug de los n´umeros m´agicos. Cuando se realiz´o el filtro no se tuvo en cuenta que los n´umero m´agicos tienen su propio visitor que es llamado directamente desde la regla de calidad que los comprueba. Por ello est´an completamente desacoplados de sus respectivos s´ımbolos. Una vez detectado el problema, se modifica la implementaci´on de la regla para que tenga en cuenta el filtrado. La explicaci´on detallada de la modificaci´on puede ser encontrada en la secci´on de la implementaci´on de la historia de usuario 3. Por ´ultimo en el Sprint se quiere modificar la forma de cambiar las convenciones de nombrado que siguen las reglas de calidad, las cuales dentro del plugin est´an implementadas como expresiones regulares. Actualmente esta expresiones regulares est´an hard coded en el c´odigo, por lo que se prefiere utilizar la capacidad de parametrizaci´on que posee SonarQube. Una explicaci´on detallada de c´omo se ha llevado a cabo esta implementaci´on puede ser encontrada en la secci´on implementaci´on de la historia de usuario 5.1. 7.7. Sprint 5 10/12/2020-23/12/2020) La Tabla 7.6 tiene un resumen de las tareas realizadas durante este Sprint. 108
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO Tarea Tiempo estimado Tiempo invertido Estado Extracci´on de las categor´ıas de los nombre de las views 5h 5h 50m Completado Inyecci´on y reciprocaci´on de m´odulos y categor´ıas del diccionario de datos 11h 10h 45m Completado Inyecci´on en el diccionario de las relaciones de los s´ımbolos con los m´odulos y las categor´ıas 8h 4h 50m Completado Documentaci´on. 2h 1h 40m Completado Total 26h 23h 5m 100 % Completado Tabla 7.6: Tareas del Sprint 5 Este Sprint comienza ampliando los datos que se extraen de las vistas, ahora tambi´en se extraer´a la categor´ıa y subcategor´ıa. Para ello primero es necesario saber cual es el separador que se utilizar´a entre la categor´ıa y la subcategor´ıa por lo que se crea una nueva propiedad en el fichero de configuraci´on de sonar-scanner llamada vensim.view.category.separator. Con la inclusi´on de esta nueva propiedad pueden darse configuraciones que no tengan sentido, como por ejemplo que se defina el separador entre categor´ıa y subcategor´ıa, pero no el de m´odulo y categor´ıa. Por ello se decide crear un nuevo nivel de aviso en el logger del plugin el cual sea WARNING este se utilizar´a para avisar de problemas que no rompan el plugin, pero afecten a su funcionalidad. Ahora que se puede obtener el separador de categor´ıa/subcategor´ıa se realizan las modificaciones necesarias en la clase ViewTableVisitor para que extraiga las categor´ıas. La explicaci´on de la implementaci´on puede ser encontrada en la secci´on de implementaci´on de la historia de usuario 2. Para evitar trabajar con cadenas de texto que no tienen un valor sem´antico ´util, se decide crear dos nuevas clases: Category yModule las cuales contendr´an toda la informaci´on relativa a las categor´ıas y los m´odulos respectivamente. Sendas clases ser´an creadas en el paquete model. Una vez extra´ıdas correctamente las categor´ıas se comienza a trabajar en los nuevos servicios que tendr´a que brindar la API del diccionario de datos para que se puedan realizar las inyecciones de m´odulos y categor´ıas, actualmente solo existe qaAddSymbolDefinition que no permite una inyecci´on de m´odulos y categor´ıas independiente de s´ımbolos. Para la recuperaci´on de estos datos solo existen qaGetSymbolDefinition el cual devuelve una gran cantidad de datos combinados en un ´unico Json. Estos datos no tienen una relaci´on pura sem´antica con los s´ımbolos. Al igual que el servicio de inyecci´on, tambi´en est´a vinculado a los s´ımbolos que se ha pedido al diccionario que devuelva. 109
7.8. NAVIDADES Al final, para modularizar m´as la forma de comunicarse con la API y a su vez mejorar el significado sem´antico de las peticiones se deciden crear cuatro nuevos puntos de conexi´on, dos para los m´odulos y poder realizar inyecci´on y recuperaci´on de datos, y otros dos para las categor´ıas con la misma funcionalidad que los descritos para los m´odulos. Para mantener la consistencia de nombrado con las conexiones de la API existentes se deciden los siguientes nombres de los end points: qaGetModules qaAddModules qaGetCategories qaAddCategories La estructura de las peticiones y de las respuestas puede ser encontrada en el Anexo C. La implementaci´on para realizar esta inyecci´on y recuperaci´on puede ser vista en la secci´on de implementaci´on de la historia de usuario 6.1 para los m´odulos y en la secci´on implementaci´on de la historia de usuario 6.3 para las categor´ıas. Una vez se tiene ya la conexi´on bidireccional de m´odulos y categor´ıas con el diccionario de datos se continua adaptando los puntos de conexi´on iniciales qaGetSymbolDefinition y qaAddSymbolDefinition para que permitan realizar la comunicaci´on de cual es el m´odulo y la categor´ıa de cada s´ımbolo independientemente del resto. Una vez m´as la estructura de estas dos peticiones puede ser encontrada en el Anexo C y la implementaci´on de este cambio en las secciones de las historias de usuario 6.2 y 6.4 para los m´odulos y las categor´ıas respectivamente. 7.8. Navidades Oficialmente durante las navidades no se realiza ning´un Sprint. As´ı se realiz´o la planificaci´on del proyecto debido a que estas fechas son muy pr´oximas a los ex´amenes de convocatoria ordinaria de las asignaturas del primer cuatrimestre y se prefiere destinarlas a estudiar. No obstante, se dedica algo de tiempo a realizar una refactorizaci´on ligera y limpieza del c´odigo. Esta refactorizaci´on y limpieza utilizan el apoyo de los analizadores de c´odigo. Es decir, programas que hacen lo mismo que la finalidad de este plugin pero para el lenguaje Java. Los detalles de estas modificaciones se pueden encontrar en la secci´on de Refactorizaci´on y calidad del c´odigo. Se dedica tambi´en tiempo a continuar escribiendo la memoria. 110
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO 7.9. Sprint 6 21/01/2021-3/2/2021 La Tabla 7.7 tiene un resumen de las tareas realizadas durante este Sprint. Tarea Tiempo estimado Tiempo invertido Estado Verificaci´on correcto funcionamiento de los nuevos servicios de la API 30m 25m Completado Crear regla para evitar lookups incrustados 10h 19h Completado Crear regla para evitar declaraciones de s´ımbolos en el fragmento de control de forma err´onea 8h 11h 20m Completado Documentaci´on. 2h 0h Aplazado Total 20h 30m 30h 45m 75 % Completado Tabla 7.7: Tareas del Sprint 6 Durante el evento de Sprint Planning de este Sprint se comunica por parte de la tutora que ya est´an implementados los nuevos servicios en el diccionario de datos, por lo que es necesario hacer una bater´ıa de pruebas para verificar su correcto funcionamiento, tanto desde el plugin como tambi´en de manera aislada. Para ello, dentro del plugin se crea un nueva bater´ıa de pruebas contra estos end points. Para hacer las pruebas en aislamiento se utiliza el programa PostMan el cual es un programa que sirve para poder realizar peticiones customizadas mediante HTTP. Al hacer las pruebas se reportan los fallos encontrados a los responsables del diccionario de datos y estos son arreglados durante el desarrollo de este Sprint. Despu´es de realizar las pruebas a los nuevos servicios de la API se pasa a crear la nueva regla de calidad que comprueba que no haya lookups incrustados en el c´odigo. Al empezar a realizar esta nueva regla, se llega a la conclusi´on de que actualmente no existe ning´un mecanismo que permita contar la cantidad de datos incrustados en cada s´ımbolo de tipo lookup. Adem´as, se analiza que el poder contar con estos datos supone una gran cantidad diferencias con cualquiera de los visitors existentes actualmente. Por estas dos razones se decide crear un nuevo visitor con la responsabilidad de contar estos datos incrustados en los lookups. El nombre de este nuevo visitor es EmbeddedLookupVisitor. Tambi´en se necesita crear una nueva clase que almacene la l´ogica de la nueva regla de control que recibe el nombre de EmbeddedLookupCheck. Una explicaci´on detallada de la implementaci´on puede ser encontrada en la secci´on de la historia de usuario 4.2. 111
7.10. SPRINT 7 04/02/2021-17/02/2021 Inicialmente esta regla generaba una issue en cada dato incrustado, durante la weekly se lleg´o a la conclusi´on de que esto puede provocar una gran cantidad de issues de manera innecesaria, por lo que se actualiza que se solo se genera una issue en la l´ınea donde se declara el s´ımbolo de tipo lookup que tiene sus datos incrustados. Despu´es de realizar este cambio en la regla se da por terminada su implementaci´on. Se continua el Sprint realizando la implementaci´on de la otra regla que se tiene como objetivo. Esta regla usa el concepto de grupo en el contexto de los archivos de extensi´on .mdl. Actualmente estos grupos no son contemplados en el plugin por lo que ser´a necesario modificar la gram´atica y los visitors para que se pueda detectar. La implementaci´on de estos cambios se encuentra en la secci´on de la historia de usuario 2. Una vez se tiene una forma de detectar los grupos en los visitors es necesario trasladar esa informaci´on a los s´ımbolos. Para ello es necesario extender las propiedades de los s´ımbolos para que almacenen el grupo al que pertenecen. Adem´as, se necesita saber que s´ımbolos pueden aparecer en este grupo de control, estos vienen definidos por Vensim y son los siguiente: TIME TIME STEP INITIAL TIME FINAL TIME SAVEPER Estos cinco s´ımbolos son utilizados por Vensim para gestionar los avances de la simulaci´on. Una vez que los s´ımbolos tienen ya su grupo y se tienen definidos qu´e s´ımbolos deben pertenecer en exclusiva al grupo de control, el resto es crear una nueva regla, en este caso la clase se llama SymbolGroupCheck. La implementaci´on de esta explicaci´on puede ser encontrada en la secci´on de la historia de usuario 4.3. Por ´ultimo, este Sprint tambi´en ten´ıa como objetivo la continuaci´on de la memoria, por un mal calculo de tiempo no se ha podido completar satisfactoriamente. 7.10. Sprint 7 04/02/2021-17/02/2021 La Tabla 7.8 tiene un resumen de las tareas realizadas durante este Sprint. 112
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO Tarea Tiempo estimado Tiempo invertido Estado Crear regla para comprobar que el nombre de las vistas sigue el convenio 6h 30m 6h 20m Completado Bug: El diccionario no acepta dos subcategor´ıas con el mismo nombre 10h 11h Completado Despliegue versi´on 1.2 1h 40m Completado Documentaci´on. 4h 3h 45m Completado Total 21h 30m 21h 45m 100 % Completado Tabla 7.8: Tareas del Sprint 7 Este Sprint comienza con la escritura de una nueva regla. En este caso la regla de calidad responsable de que la vistas tengan un nombre correcto. Esta es la primera regla que es independiente de los s´ımbolos. Esto hace que haya que modificar la forma en la que se comprobaba si una issue es guardada o no. La clase abstracta VensimCheck inicialmente tenia como atributo un s´ımbolo. Esto es sustituido para que sea un booleano y as´ı pueda funcionar tambi´en con vistas. La clase de la nueva regla se llama ViewNameCheck y la explicaci´on de su implementaci´on se encuentra en la secci´on de la historia de usuario 4.4. Una vez implementada la regla se pasa a la siguiente tarea del Sprint que tiene que ver con un fallo que se ha encontrado a la hora de inyectar categor´ıas en el diccionario de datos del proyecto. El problema est´a dado por como funciona la estructura interna del diccionario de datos. Es imposible almacenar dos subcategor´ıas con el mismo nombre aunque estas pertenezcan a categor´ıas distintas. Este problema es elevado al equipo responsable de LOCOMOTION. Al final en la weekly de este Sprint se recibe el veredicto de como afrontar este problema. Se decide que esa restricci´on se mantendr´a en pie debido a los problemas que dar´ıa tener que modificarlo en la implementaci´on del diccionario de datos. Por ello es necesario que el plugin sea complaciente con este nuevo requisito. Para llevar esto a cabo se genera una nueva regla de control, llamada CategoryDuplicatedCheck, que detecte cuando existen dos subcategor´ıas con el mismo nombre, invalidando siempre una de las dos. Si existiese una de las subcategor´ıas duplicadas ya en el diccionario de datos, se le dar´ıa prioridad a la almacenada ya en el diccionario de datos y se generar´ıa la issue en la otra duplicada. Si ninguna de las dos existe en el diccionario, la issue se generar´a en la primera en aparecer en el modelo. La implementaci´on de esta regla puede ser encontrada en la secci´on de la historia de usuario 6.3. Una vez realizada toda la implementaci´on de este Sprint se realiza un merge a la rama master con el c´odigo preparado para el despliegue de la versi´on del plugin 1.2 113
7.11. SPRINT 8 18/02/2021-03/03/2021 Por ´ultimo, en este Sprint se recupera el tiempo de documentaci´on perdido en el Sprint anterior. 7.11. Sprint 8 18/02/2021-03/03/2021 La Tabla 7.9 tiene un resumen de las tareas realizadas durante este Sprint. Tarea Tiempo estimado Tiempo invertido Estado Crear regla para comprobar que las unidades de los s´ımbolos son las estipuladas en el convenio 9h 30m 8h 50m Completado Bug: Inyecci´on de s´ımbolos no pertenecientes a ning´un m´odulo 3h 4h 15m Completado Actualizaci´on del archivo con los elementos encontrados en el an´alisis 3h 1h Completado Generaci´on de un archivo con las diferencias entre los elementos en local y los elementos en el diccionario de datos 4h 3h 20m Completado Despliegue versi´on 1.3 20m 20m Completado Documentaci´on. 2h 2h 10m Completado Total 21h 50m 19h 55m 100 % Completado Tabla 7.9: Tareas del Sprint 8 El Sprint se inicia con la creaci´on de una nueva regla, DictionaryUnitSymbolCheck, la cual se encargar´a de comprobar que los s´ımbolos del modelo analizado tengan como unidad, una de las oficiales elegidas en el marco com´un de modelado definido en el proyecto. Como estas unidades pueden ser modificadas en un futuro no pueden ser escritas en el c´odigo. En el diccionario de datos existe la lista con estas unidades v´alidas, por lo que es necesario generar un nuevo punto de conexi´on de la API para que pueda dar servicio de obtener las unidades. Se decide que el nuevo servicio se llamar´a qaGetUnitSystem. No se crea un servicio de inyecci´on por el motivo de que esta lista, o sistema de unidades, es fruto de un an´alisis y un acuerdo para el desarrollo del modelo y no tendr´ıa sentido que se pudiese modificar. La estructura de este nuevo servicio puede ser encontrada en el Anexo C. 114
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO Con esta nueva lista de unidades v´alidas se puede pasar a crear la nueva regla de control. La explicaci´on detallada de la implementaci´on se puede ver en la secci´on de la historia de usuario 4.5. Una vez se tiene la regla implementada se pasa a arreglar un fallo importante, pero que no hab´ıa sido detectado por la situaci´on temprana en la que se encuentra el modelo. Se trata de que actualmente los s´ımbolos que no pertenecen a ning´un m´odulo no son inyectados, esto se debe a las comprobaciones que se hacen sobre el filtrado de m´odulos que se realizan, este fallo afecta en especial a los ´ındices, los cuales por la forma en la que se declaran, no pertenecen de forma principal a ning´un m´odulo. Al trabajar en arreglar el error, se decide que ser´a m´as conveniente si se divide el servicio de la API qa[Get-Add]SymbolDefinition para que por un lado se suban los s´ımbolos est´andar que por lo general tienen su declaraci´on en un m´odulo en concreto y por otro lado los ´ındices que act´uan a trav´es de todos los m´odulos sin pertenecer a ninguno en concreto. As´ı se consigue que todos los servicios de la API solo utilicen una lista y no una lista de listas como era el caso de qa[Get-Add]SymbolDefinition. Por lo tanto se decide crear dos nuevos servicios de la API: qaGetIndexesDefinition y qaAddIndexesDefinition. La estructura de las peticiones y de las respuestas puede ser encontrada en el Anexo C y la implementaci´on en la secci´on historia de usuario 6.2. Una vez arreglado el fallo, se puede continuar con el desarrollo del Sprint, la siguiente tarea es un tema nuevo respecto a todo lo que se lleva hecho de TFG. Se trata de actualizar el archivo que se genera al realizar un an´alisis de un modelo. En este archivo aparece informaci´on sobre todos los s´ımbolos detectados. Actualmente la informaci´on que presenta es escasa y, si tenemos en cuenta todos los nuevos datos que se obtienen del modelo, faltan muchos datos por volcar, ya no solo de cada s´ımbolo, si no secciones enteras como puede ser la informaci´on sobre las vistas o las categor´ıas. Por lo tanto, se actualiza la clase responsable de generar este documento (JsonSymbolTableBuilder)para que incorpore mucha m´as informaci´on. La explicaci´on detallada de la implementaci´on puede ser encontrada en la secci´on de la historia de usuario 7. Adem´as, a partir de ahora, toda adici´on que se realice ya sea en los s´ımbolos o en cualquier otro elemento ser´a expuesta en este archivo. Tambi´en se requiere crear un nuevo archivo que, en vez de tener toda la informaci´on de los elementos detectados en el modelo analizado, contendr´a todas las diferencias encontradas entre el diccionario de datos y el an´alisis local del modelo programado en el .mdl. Contendr´a informaci´on relativa a diferencias encontradas en el mismo elemento como tambi´en elementos que solo est´en en el diccionario de datos o solo en el an´alisis en local. La clase responsable tiene el nombre JsonDictoinaryDiffBuilder. Como este archivo no es importante en todas las situaciones, se crea una nueva propiedad en el documento sonar-project.properties llamada vensim.dictionary.getDiff. Con 115
7.15. SPRINTS FINALES 22/04/2021 - 02/06/2021 7.15. Sprints finales 22/04/2021 - 02/06/2021 A partir de aqu´ı nos encontramos ya fuera de Sprints empleados para incrementar la funcionalidad del plugin. No obstante, se continuar´a manteniendo y corrigiendo posibles fallos que sean reportados por parte del equipo de LOCOMOTION. Los Sprints seguir´an siendo de dos semanas, con la tarea principal de continuar escribiendo la memoria. Se estima un tiempo de dedicaci´on de 20 horas por Sprints En total se realizaron tres Sprints m´as en esta etapa del TFG, . Durante este periodo con el plugin en producci´on se detectan problemas con la recuperaci´on del m´odulo y la categor´ıa de una vista. Esto se debe a que pueden existir nombres de vistas err´oneos sem´anticamente, pero que la estructura sint´actica sea compatible con el convenio de nombrado. Esto es un problema por el motivo de que se podr´ıa llegar el diccionario de s´ımbolos de m´odulos y categor´ıas err´oneos. Para mitigar este problema, sobretodo en las fases iniciales de desarrollo del modelo, se habilita la posibilidad de poder elegir qu´e elementos se inyectan. Para conseguir esto, se generan tres nuevas propiedades en el archivo de configuraci´on sonar-project.properties: vensim.dictionary.inject.modules vensim.dictionary.inject.categories vensim.dictionary.inject.symbols As´ı se puede prevenir la subida si de antemano se prev´e que habr´a nombres de vistas err´oneos. A parte se pide al equipo de LOCOMOTION que establezcan los nombres de sus vistas lo antes posible para evitar el problema. Aparte de este fallo, el resto del tiempo se dedic´o a continuar con la escritura de la memoria. En total durante estos tres Sprints se ha dedicado un total de 63 horas de trabajo contando el arreglar el fallo encontrado y en continuar con la documentaci´on. 7.16. Resumen de la ejecuci´on del proyecto 7.16.1. Resumen final de tareas y tiempos Al final el tiempo estimado en Sprints fue sobrepasado en gran cantidad, de los 10 Sprints estimados a desarrollar al principio, han acabado siendo 12. Este incremento se debe a, entre otros, a la mutabilidad que se ha encontrado en algunos de los requisitos y en su creaci´on y a la carga externa que ha tenido el alumno en algunos momentos durante el proyecto que lo han limitado a continuar con el desarrollo en algunos momentos. 122
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO Figura 7.1: Planificaci´on con las reuniones los jueves. Por lo tanto la planificaci´on inicial de Sprints ha cambiado considerablemente respecto al diagrama de Gantt inicial de la Figura 2.1. El primer cambio surgi´o al iniciar el curso el d´ıa 28 de Septiembre de 2020, por causa de las horas de clase, no pudo ser posible seguir reuni´endose los lunes, todas las reuniones fueron trasladadas a los jueves. Para mantener la consistencia de empezar el Sprint a la vez que se hace la reuni´on de Sprint Planning, se decidi´o modificar el inicio de todos los Sprints a los jueves, esto provoc´o entre el Sprint 0 y 1 hubiese un espacio de 3 d´ıas sin Sprint. En la Figura 7.1 puede encontrarse la actualizaci´on de la planificaci´on teniendo en cuenta el cambio de d´ıa de las reuniones. Por ´ultimo, el segundo cambio fue al final del Sprint 9 del proyecto se requirieron una gran cantidad de modificaciones extras al plugin las cuales se estim´o que no dar´ıa tiempo a realizarlas en el tiempo planificado restante. Por ello, se decidi´o ampliar la beca un mes extra hasta el d´ıa 14 de Abril de 2021 y as´ı poder contar con dos Sprint extra para realizar las implementaciones necesarias. En este periodo ya se empez´o con la escritura de la memoria. Tambi´en se tuvieron que a˜nadir los tres Sprints finales de documentaci´on y supervisi´on del plugin en producci´on para reaccionar ante cualquier incidencia. En la Figura 7.2 puede encontrarse la actualizaci´on de la planificaci´on una vez se ampli´o el plazo de beca y de documentaci´on. Una vez se han definido todos los Sprints en la Tabla 7.13 se puede encontrar un resumen por Sprint del tiempo estimado e invertido. 123
7.16. RESUMEN DE LA EJECUCI ´ ON DEL PROYECTO Figura 7.2: Planificaci´on final del TFG. Sprint Tiempo estimado Tiempo invertido Sprint 0 23h 30m 28h 30m Sprint 1 23h 30m 31h 5m Sprint 2 22h 30m 18h 15m Sprint 3 17h 14h 30m Sprint 4 15h 45m 19h 10m Sprint 5 27h 23h 5m Sprint 6 20h 30m 30h 45m Sprint 7 21h 30m 21h 45m Sprint 8 21h 50m 19h 55m Sprint 9 29h 34h 50m Sprint 10 13h 11h 55m Sprint 11 23h 20m 21h 45m Sprint 12-14 60h 63h Total 318h 25m 338h 30m Tabla 7.13: Resumen tiempo estimado e invertido por Sprint 124
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO 7.16.2. An´alisis de los riesgos A continuaci´on se har´a menci´on a todos los riesgos que se han detectado a los largo del desarrollo del TFG. La gran mayor´ıa de ellos hab´ıan sido recogidos en la lista de posibles riesgos generada al inicio del proyecto. Los riesgos que hubiesen sido detectados inicialmente estar´an acompa˜nados de su n´umero de riesgo que tienen en la secci´on 2.5. Los riesgos que no hubiesen sido detectados se marcar´an debidamente como nuevos. Riesgo 2: Flexibilidad horaria del equipo de trabajo Este riesgo es uno de los poco detectados inicialmente que era beneficioso para el proyecto, se consigui´o reconocer la asignatura del segundo cuatrimestre por lo que esto permiti´o poder trabajar en el TFG a la mejor hora posible y adem´as poder modificar ese horario si fuese necesario. Riesgo 3: Dificultad entendimiento c´odigo de partida Este riesgo se materializ´o a la hora de tener que modificar la gram´atica de ANTLR. La uni´on de una gram´atica compleja y la falta de experiencia del usuario en el uso de ANTLR hizo que las primeras semanas de desarrollo fuesen m´as lentas de los previsto. Al final se consigui´o obtener el conocimiento sobre el c´odigo y ANTLR como para poder realizar modificaciones sin utilizar demasiado tiempo. Riesgo 7: Mutabilidad de las historias de usuario Al tratarse de un proyecto ´agil, la mayor´ıa de los requisitos que se tienen al final del proyecto han ido siendo decididos durante el desarrollo del mismo. Esto hace que no se pueda prever en gran medida cu´ales ser´an los cambios en el proyecto en el futuro. Aun as´ı, el uso de un marco de trabajo ´agil ha facilitado en gran medida esta variabilidad en la modificaci´on de requisitos. Ninguno de los requisitos ya implementados en un Sprint recibi´o un cambio dr´astico en Sprints posteriores. Riesgo 8: Falta de organizaci´on en el equipo de trabajo Una carencia en la organizaci´on en alguno de los Sprints (principalmente el Sprint 9) agrav´o la previsi´on de tiempos. Esto se debe a que en situaciones en las que se hizo una mala estimaci´on de tiempos para las tareas, no se llev´o a cabo un cambio en la forma de trabajar en el Sprint para intentar mitigar lo m´aximo posible la estimaci´on err´onea. Esto llev´o a algunos Sprints a tener, como el 9, hasta el 50 % de la tareas aplazadas, o como el 1 y el 6, con el 60 % o el 75 %. Riesgo 10: Incompatibilidad horaria en el equipo de trabajo En el Sprint 4 fue necesario realizar un cambio en el horario de todas las reuniones por una incompatibilidad horaria. Este problema fue resuelto r´apido, modificando el d´ıa de las reuniones de los lunes a los jueves. Por esto hubo un periodo de 3 d´ıas exento de un Sprint oficialmente. 125
7.16. RESUMEN DE LA EJECUCI ´ ON DEL PROYECTO Riesgo 13: Falta de conocimientos del stack de desarrollo Este riesgo est´a relacionado con lo descrito en el riesgo 3, una carencia de conocimientos mayor a la esperada en ANTLR hizo que el desarrollo y actualizaci´on de la gram´atica llevase m´as tiempo del estimado. Riesgo no detectado: Necesidad de una comprensi´on sem´antica para la validaci´on de alguna regla. Este es un riesgo no detectado al inicio del proyecto. Este riesgo se refiere a la posible situaci´on de que alguna de las nuevas reglas previstas para el plugin no pueda ser analizada sint´acticamente solo y se necesita un contexto y una comprensi´on sem´antica. Este tipo de reglas pueden catalogarse como muy complejas de implementar debido a que el plugin solo tiene capacidades sint´acticas de an´alisis. Este riesgo se materializ´o a la hora de invalidar o no los nombres de las vistas. Los nombres de las vistas deben seguir la estructura dada por una expresi´on regular, el problema es que existen nombre que puedan seguir la estructura de la expresi´on regular, pero est´en mal. Por ejemplo, si tenemos la expresi´on regular: ([a-zA-Z0-9_]+)*[a-zA-Z0-9]+(-[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)?)? la cual podr´ıa ser una forma v´alida del nombre de una vista que tiene “-” como separador entre m´odulo y categor´ıa y “.” como separador entre categor´ıa y subcategor´ıa. El nombre energy-consumption.land ser´ıa un nombre correcto tanto sint´acticamente como sem´anticamente el cual tendr´ıa energy como m´odulo, consumption como categor´ıa yland como subcategor´ıa. Pero time-saving aplications in development ser´ıa un nombre v´alido sint´acticamente, pero inv´alido sem´anticamente ya que esto detectar´ıa como m´odulo a time y como categor´ıa a saving aplications in development. En el proyecto no se define un m´odulo time. Para combatir este problema se realizaron dos procedimientos, el primero fue implementar un nuevo par´ametro el cual permitiese poder deshabilitar la inyecci´on de elementos al diccionario de datos para as´ı poder prevenir la inyecci´on de estos elementos err´oneos sobretodo en versiones tempranas del modelo. Segundo, se avis´o al equipo que implementa el modelo que intenten tener como prioridad m´axima los nombres de las vistas correctos sem´anticamente. 7.16.3. Gesti´on de tareas con Gitlab issue tracker Al haber utilizado las herramientas de gesti´on de incidencias de GitLab y adem´as con el uso de etiquetas y milestones se puede realizar un resumen de cu´antas tareas se han ejecutado por tipo de incidencia y cu´antas tareas ha habido en cada release. En la Tabla 7.14 se puede ver el resumen de las incidencias agrupadas por tipo, y en la Tabla 7.15 se pueden ver agrupadas por release. 126
CAP´ ITULO 7. SEGUIMIENTO DEL PROYECTO Etiqueta Node incidencias Data dictionary 14 Documentation 4 File generation 3 Grammar 5 Refactor 2 Release 4 Rule added 7 Rule modification 7 Sin etiqueta 4 Total 50 Tabla 7.14: Agrupaci´on de las incidencias por etiqueta Existe un grupo de incidencias que no tienen etiqueta, esto se debe a que pertenec´ıan a conceptos espec´ıficos de los cuales no se ha generado etiqueta en s´ı. Como por ejemplo incidencias del CI/CD que en este caso solo hay una. Versi´on Node incidencias Fecha de despliegue v1.1 7 29/10/2020 v1.2 17 16/02/2021 v1.3 6 03/03/2021 v1.4 20 21/04/2021 Total 50 Tabla 7.15: Agrupaci´on de las incidencias por release Toda las modificaciones realizadas a partir del despliegue de la versi´on 1.4 fueron a˜nadidas a esta propia versi´on. 127
7.16. RESUMEN DE LA EJECUCI ´ ON DEL PROYECTO 7.16.4. Coste simulado Todos los valores incluidos en este coste se toman del presupuesto estimado en la Secci´on 2.7.1 en el cual se hizo una previsi´on de costes del proyecto con una supuesta duraci´on de 300 horas. El proyecto final ha supuesto una duraci´on de 338h 30m. Teniendo en cuenta que el salario del desarrollador es de 11,53 ea la hora implica un coste en salario de 3.902,9 e. Los costes de hardware y de software no han sufrido variaciones a lo estimado inicialmente. Por lo tanto el coste final del proyecto puede ser visto en la Tabla 7.16. Sueldo 3.902,9 e Hardware 106,25 e Software 89,40 e Total 4.098,55 e Tabla 7.16: Coste simulado. Teniendo en cuenta que en el presupuesto original se hizo una estimaci´on de 3.654,65 e con un margen de contingencias del 12 % el cual ampliaba el presupuesto total a 4.093,21 e. Se puede ver que la relaci´on entre el presupuesto y el coste es pr´acticamente id´entica. Esto verifica la importancia de establecer un buen margen de contingencias. 7.16.5. Coste real Para llevar a cabo el coste real se utilizan los valores obtenidos en el presupuesto real el cual se encuentra en la Secci´on 2.7.2. Teniendo en cuenta que el coste mensual de la beca para la Funge es de 348,41 ey, adem´as, que la beca fue ampliada un mes para un total de siete meses. Se tiene un coste en salario de 348,41x7 = 2438,87 e. La amortizaci´on del ordenador se mantiene igual en 106,25 e. Por lo tanto el coste total del proyecto ha sido de 2545.12 e. 128
CAP´ ITULO 8. CONCLUSIONES Cap´ıtulo 8 Conclusiones Una vez terminado el proyecto, se puede decir que se han cumplido satisfactoriamente todos los objetivos del proyecto dando como resultado un plugin utilizado actualmente en producci´on, con un feedback muy positivo del equipo de LOCOMOTION. Adem´as, se ha publicado el software obtenido en Gitlab, pasando a ser c´odigo libre. La flexibilidad de configuraci´on del plugin permite poder adaptarlo a diferentes contextos de otros proyectos de una manera sencilla, adem´as, esta publicaci´on permitir´a que el plugin pueda ser ampliado y mejorado por la comunidad. Por otra parte, el uso de nuevas tecnolog´ıas como ANTLR o el framework de SonarQube requiri´o de una adaptaci´on inicial por parte del alumno la cual en algunos momentos fue tediosa como puede ser a la hora de desarrollar la gram´atica y los problemas de incompatibilidades encontrados respecto a la gram´atica original. A´un as´ı, la gram´atica resultante funciona en todas las situaciones en las que se ha probado. Respecto al uso del framework, se han necesitado muchas horas para su comprensi´on y entendimiento del funcionamiento del flujo, comparando como se cre´o la primera nueva regla de control de calidad a la ´ultima se nota una gran mejora en la comprensi´on de este framework. Respecto a la gesti´on del proyecto, la reuniones con la tutora, ya fuesen weeklys osprint planning, review o retrospective, fueron de gran ayuda para la organizaci´on y poder abstraerse a un punto de vista de m´as alto nivel sobre la situaci´on actual del plugin. El desarrollo del proyecto ha sido ´optimo, se han necesitado aun as´ı m´as semanas debido a un incremento continuado del alcance del proyecto. En cuanto a la memoria, esta ha sido desarrollada en paralelo al desarrollo, no obstante se han realizado mejoras sustanciales a posteriori conociendo el alcance total del proyecto y el resultado del mismo. Debido a ser el primer proyecto de esta envergadura de desarrollo por el alumno, las estimaciones de tiempo variaron ligeramente respecto a la planificaci´on inicial. Sobre la limpieza del c´odigo se ha intentando mantener en lo posible un bajo acoplamiento 129
8.1. APLICACIONES REALES DEL PLUGIN EN LOCOMOTION y utilizar t´ecnicas de dise˜no que faciliten la comprensi´on y mantenibilidad del c´odigo en el futuro. La gran mayor´ıa de las clases y paquetes est´an organizados de una manera coherente y no se suele encontrar nada fuera de lugar. Como experiencia personal, este ha sido sin duda el proyecto m´as grande al que me he enfrentado, con el cual he podido ver mejor cu´ales son mis fortalezas y mis debilidades. Con ello puedo aprender de mis debilidades y que en el futuro debo tener m´as en cuenta el realizar una estimaci´on de tiempos m´as realista y no intentar doblar horas cuando no es posible, gestionar mejor mi organizaci´on, estabilizar el trabajo diario a un n´umero est´andar de horas y priorizar la escritura de la documentaci´on para evitar tener que hacer gran parte de ella al final. Por otra parte, he aprendido que puedo afrontar la gesti´on de una base de c´odigo con una complejidad significativa y que puedo adaptarme a nuevas tecnolog´ıas en un plazo de tiempo relativamente peque˜no aunque intenso. 8.1. Aplicaciones reales del plugin en LOCOMOTION Desde la versi´on 1.1 del plugin, este ha sido usado en el desarrollo de LOCOMOTION para mantener el control de calidad del modelo. Actualmente, en el servidor SonarQube del proyecto se encuentran almacenados los an´alisis de 21 proyectos de SonarQube distintos.Cada uno de ellos con sus propios par´ametros de an´alisis concretos como puede ser el filtrado por m´odulo, otros para analizar modelos que son subproyectos o proyectos colaterales, o bien para realizar pruebas. En ellos se puede ver como se han realizado m´ultiples an´alisis y como ha ido reduciendo el n´umero de issues detectadas a lo largo de estos an´alisis. Como ejemplo se pondr´a el proyecto demography el cual se utiliza para filtrar, analizando solamente los s´ımbolos del m´odulo demography. Como se puede ver en la Figura 8.1, en el primer an´alisis el plugin detecto casi 5000 issues y al final estas han bajado a 411. Cabe decir que el primer an´alisis se realiz´o en la versi´on 1.0 del plugin en la cual todav´ıa no exist´ıa una forma de filtrar por m´odulo, de ah´ı el n´umero tan grande en comparaci´on. El primer an´alisis realizado ya con el filtrado por m´odulo fue en noviembre con un total de 528 issues. Se puede ver tambi´en el uso activo que se est´a realizando del plugin y como la cantidad issues va fluctuando en funci´on de las ampliaciones del modelo que se van llevando a cabo. Por ´ultimos, la mitad de las issues reportadas avisan de que los s´ımbolos no existen en el diccionario de datos, esto se debe a que el diccionario actualmente tiene los s´ımbolos almacenados, pero no los tiene como validos por los que la API no los muestra, cuando se empiecen a validar, el n´umero de issues bajar´a dr´asticamente. 130
CAP´ ITULO 8. CONCLUSIONES Figura 8.1: Transcurso del uso del plugin en el desarrollo de LOCOMOTION. Tambi´en durante los an´alisis de LOCOMOTION, el plugin ha estado comunic´andose con el diccionario de datos del proyecto. Desde el inicio, se han inyectado un total de: 464 s´ımbolos de todos los tipos. 158 categor´ıas y subcategor´ıas. 9 m´odulos v´alidos. 8.2. Publicaci´on en GitHub La publicaci´on p´ublica del plugin en Github est´a realizada bajo el nombre VensimPlugin4SonarQube, en este traspaso del repositorio central interno de la escuela en Gitlab a este nuevo se ha mantenido todo los commits realizados con los responsables pertinentes, de este modo, Daniel Bazaco, el alumno que empez´o este plugin en su TFG aparecer´a como contribuidor de todos sus commits. La URL de este proyecto puede ser encontrada en el anexo B. 8.3. L´ıneas de trabajo futuras Como l´ıneas de trabajo futuras primero se expondr´an las detectadas por Daniel Bazaco en su TFG las cuales no han sido contempladas en este proyecto. La descripci´on detallada de estas l´ıneas puede ser encontrada en la Secci´on 10.1 de su memoria [4]. 131