Ingeniería inversa de una app Android open-source y migración de XML a Jetpack Compose de una de sus vistas
Abstract
Departamento de Informática (Arquitectura y Tecnología de Computadores, Ciencias de la Computación e Inteligencia Artificial, Lenguajes y Sistemas Informáticos)
Full text
Universidad de Valladolid ESCUELA DE INGENIERÍA INFORMÁTICA GRADO EN INGENIERÍA INFORMÁTICA Mención en Ingeniería del Software Ingeniería inversa de una app Android open-source y migración de XML a Jetpack Compose de una de sus vistas Alumno: Jorge Aguado Recio Tutores: Yania Crespo González-Carvajal Juan Carlos Garrote Gascón
A mi familia, que me ha ayudado y apoyado en todo momento. I
II
AGRADECIMIENTOS Agradecimientos A mi familia, que siempre ha estado ahí y me ha animado para conseguir lo que me propusiese. A mis amigos, que también me han apoyado y se han preocupado por mi a lo largo de todos estos años. A mis compañeros de carrera que se han convertido en mis amigos, y con su ayuda todos estos años han sido más llevaderos. A mi tutora y profesora Yania, la cual me ha orientado y ayudado en la gestión de este proyecto y en varias asignaturas a lo largo del grado. A mi tutor Juan Carlos por estar día tras día ayudándome en cualquier aspecto y facilitándome muchas tareas en todos los ámbitos. Gracias a todos. III
AGRADECIMIENTOS IV
RESUMEN Resumen El objetivo de este trabajo es conseguir ejecutar una modernización parcial, de tipo migración (tipo de modernización cuyo objetivo es moverse por completo a una nueva tecnología), en un proyecto open-source. Se trata de una app Android con la interfaz de usuario desarrollada en XML que se desea ir migrando a Jetpack Compose, el framework moderno de creación de IU utilizado de manera oficial en Android. Para conseguir este objetivo, se realizará un trabajo de ingeniería inversa sobre el estado actual de la aplicación, con el objetivo de obtener documentación de diseño. A partir de ese punto se abordará la modernización parcial de la app mediante migración. La contribución al proyecto open-source será doble, aportando documentación de diseño, que está desactualizada en este momento, y la propia modernización en sí. V
RESUMEN VI
ABSTRACT Abstract The objective of this work is to achieve a partial modernization, of the migration type (a modernization approach aimed at fully transitioning to new technology), of an open-source project. It involves an Android app with its user interface developed in XML that is intended to be gradually migrated to Jetpack Compose, the officially endorsed modern UI creation framework for Android. To accomplish this goal, a reverse engineering work will be undertaken on the current state of the application, with the aim of obtaining design documentation. From that point, the partial modernization of the app will be addressed through migration. The contribution to the open-source project will be twofold, providing design documentation, which is outdated at the moment, and the actual modernization itself. VII
ÍNDICE GENERAL XIV
LISTA DE FIGURAS Lista de Figuras 2.1. TablerodeGitHub................................. 10 2.2. Funcionamiento principal de las ramas de Git [11] . . . . . . . . . . . . . . . 11 2.3. Funcionamiento de git add ygit commit en el área de preparación, árbol de trabajoyrepositorio[29].............................. 12 3.1. Estructura general de una arquitectura limpia . . . . . . . . . . . . . . . . . . 21 3.2. Estructura de la capa de presentación de una arquitectura limpia . . . . . . . 22 3.3. Estructura de la capa de datos de una arquitectura limpia . . . . . . . . . . . 23 3.4. Estructura de la capa de dominio de una arquitectura limpia . . . . . . . . . 23 3.5. Principios SOLID [30] ............................... 25 4.1. Arquitectura principal de ownCloud ....................... 28 4.2. Ejemplo de caso de uso genérico . . . . . . . . . . . . . . . . . . . . . . . . . 30 4.3. Modules&UsesStyle del módulo owncloudApp perteneciente al caso de uso de subidadeunfichero ................................ 31 4.4. Modules&UsesStyle del módulo owncloudData perteneciente al caso de uso de subidadeunfichero ................................ 32 4.5. Modules&UsesStyle del módulo owncloudComLibrary perteneciente al caso de usodesubidadeunfichero ............................ 33 4.6. Modules&UsesStyle del módulo owncloudDomain perteneciente al caso de uso desubidadeunfichero............................... 34 4.7. Modules&UsesStyle del caso de uso de subida de un fichero . . . . . . . . . . 35 XV
LISTA DE FIGURAS 4.8. Modules&UsesStyle del módulo owncloudApp para el caso de uso de consulta delestadodelassubidas.............................. 36 4.9. Modules&UsesStyle del móduloowncloudData para el caso de uso de consulta delestadodelassubidas.............................. 37 4.10. Modules&UsesStyle del módulo owncloudDomain para el caso de uso de consulta del estado de las subidas . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 4.11. Modules&UsesStyle del caso de uso de consulta del estado de las subidas . . . 39 5.1. Diagrama de secuencia principal correspondiente al caso de uso de subida de unfichero....................................... 42 5.2. Diagrama de secuencia correspondiente a la función openBottomSheetToUploadFiles delaFigura5.1................................... 42 5.3. Diagrama de secuencia correspondiente a la función uploadFromFileSystem delaFigura5.1................................... 43 5.4. Diagrama de secuencia correspondiente a la función onActivityResult de la Figura5.1...................................... 44 5.5. Diagrama de secuencia correspondiente a la función byPassUnlockOnce de la Figura5.4...................................... 45 5.6. Diagrama de secuencia correspondiente a la función requestUploadOfContentFromApps delaFigura5.4. .................................. 46 5.7. Diagrama de secuencia correspondiente al ref getPermission de la Figura 5.6 47 5.8. Diagrama de secuencia correspondiente a la función uploadFilesFromContentUri delaFigura5.6................................... 47 5.9. Diagrama de secuencia correspondiente a la función storeInUploadsDatabase delaFigura5.8................................... 48 5.10. Diagrama de secuencia correspondiente a la implementación de la interfaz TransferRepository delaFigura5.9 ...................... 48 5.11. Diagrama de secuencia correspondiente a la función saveTransfer de la Figura5.10 ...................................... 49 5.12. Diagrama de secuencia correspondiente a la función enqueueSingleUpload de laFigura5.8 .................................... 50 5.13. Diagrama de secuencia correspondiente al ref Creation of variable of the worker delaFigura5.12.............................. 50 5.14. Diagrama de secuencia correspondiente a la función doWork de la Figura 5.1 . 51 XVI
LISTA DE FIGURAS 5.15. Diagrama de secuencia correspondiente al ref Upload File Operations de laFigura5.14.................................... 52 5.16. Diagrama de secuencia correspondiente a la función uploadDocument de la Figura5.15 ..................................... 53 5.17. Diagrama de secuencia correspondiente a la función uploadPlainFile de la Figura5.16 ..................................... 54 5.18. Diagrama de secuencia correspondiente a la implementación de transferRepository delaFigura5.17 .................................. 54 5.19. Diagrama de secuencia correspondiente a la implementación de la interfaz remoteDataTransfer delaFigura5.18 ..................... 55 5.20. Diagrama de secuencia correspondiente a la implementación de interfaz fileService delaFigura5.19 .................................. 55 5.21. Diagrama de secuencia correspondiente a la implementación la función run de laFigura5.20.................................... 56 5.22. Diagrama de secuencia correspondiente a la captura de excepción de la Figura5.21........................................ 57 5.23. Diagrama de secuencia correspondiente a la función uploadFile de la Figura 5.22 57 5.24. Continuación del diagrama de secuencia correspondiente a la Figura 5.23 . . . 58 5.25. Diagrama de secuencia principal correspondiente al caso de uso de consulta deestadodelassubidas .............................. 59 5.26. Diagrama de secuencia correspondiente a la creación del TransferListFragment 60 5.27. Diagrama de secuencia correspondiente a la creación del TransfersViewModel 60 5.28. Diagrama de secuencia correspondiente a la implementación de la interfaz transferRepository delaFigura5.27 ..................... 61 5.29. Diagrama de secuencia correspondiente a la implementación de la interfaz localTransferDataSource de la Figura 5.28 . . . . . . . . . . . . . . . . . . 62 5.30. Diagrama de secuencia correspondiente a la implementación de la función setData delaFigura5.26............................. 62 5.31. Diagrama de secuencia correspondiente a la implementación de la función setData delaFigura5.30............................. 63 6.1. Modules&UsesStyle del módulo owncloudApp para el caso de uso de consulta del estado de las subidas después del rediseño . . . . . . . . . . . . . . . . . . 68 XVII
LISTA DE FIGURAS 6.2. Diagrama de secuencia principal correspondiente al caso de uso: Consulta del estadodelassubidas................................ 69 6.3. Diagrama de secuencia correspondiente a la creación del TransferListComposeFragment delaFigura6.2................................... 70 6.4. Diagrama de secuencia correspondiente a la función composable Transfers . 71 6.5. Diagrama de secuencia correspondiente a la función composable EmptyList . 72 6.6. Diagrama de secuencia correspondiente a la función composable TransferList 72 6.7. Diagrama de secuencia correspondiente a la función composable UploadGroup 74 6.8. Diagrama de secuencia correspondiente a la función composable TransferItem 75 6.9. Diagrama de secuencia correspondiente a la función composable SpacePathLine 76 7.1. Elemento de IU asociado a la función composable SpacePathLine ....... 80 7.2. Resultado de la función composable TransferItem en el estado Succeded . . . 83 7.3. Resultado de la función composable TransferItem en el estado Failed . . . . 83 7.4. Resultado de la función composable TransferItem en el estado Enqueued . . 83 7.5. Resultado de la función composable TransferItem en el estado In Progress . 84 7.6. Resultado de la función composable UploadGroup en el estado Succeded . . . 85 7.7. Resultado la función composable UploadGroup en el estado Failed ....... 85 7.8. Resultado la función composable UploadGroup en el estado Enqueued ..... 86 7.9. Resultado la función composable UploadGroup en el estado In Progress . . . . 86 7.10. Resultado de la función composable TransferList con los estados Enqueued yFailed ....................................... 87 7.11. Resultado de la función composable TransferList con los estados In progress ySucceeded ..................................... 87 7.12. Resultado de la función composable EmptyList ................. 90 7.13. Pantalla de las subidas definida en XML . . . . . . . . . . . . . . . . . . . . . 91 7.14. Pantalla de las subidas definida en Jetpack Compose . . . . . . . . . . . . . . 91 A.1. Artefactos, Roles y Eventos de Scrum [50] . . . . . . . . . . . . . . . . . . . . 114 XVIII
LISTA DE TABLAS Lista de Tablas 7.1. Plan de pruebas referente a la lista vacía . . . . . . . . . . . . . . . . . . . . . 92 7.2. Plan de pruebas referente al estado de subida: Succeeded ............ 93 7.3. Plan de pruebas referente al estado de subida: Enqueued ............ 95 7.4. Plan de pruebas referente al estado de subida: In progress ........... 97 7.5. Plan de pruebas referente al estado de subida: Failed .............. 99 7.6. Plan de pruebas referente al flujo de subida de un sólo archivo en todos los estadosposibles................................... 100 7.7. Plan de pruebas con todos los estados posibles simultáneamente . . . . . . . . 100 A.1. Planificación del calendario . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 A.2. Riesgo R01. Trabajo individual. . . . . . . . . . . . . . . . . . . . . . . . . . . 118 A.3. Riesgo R02. Dominio de la tecnología. . . . . . . . . . . . . . . . . . . . . . . 118 A.4. Riesgo R03. Ausencia temporal del estudiante por enfermedad. . . . . . . . . 119 A.5. Riesgo R04. Asignaturas pendientes. . . . . . . . . . . . . . . . . . . . . . . . 119 A.6. Riesgo R05. Confinamiento debido al COVID-19. . . . . . . . . . . . . . . . . 119 A.7. Riesgo R06. Indisponibilidad del equipo de trabajo. . . . . . . . . . . . . . . . 120 A.8. Riesgo R07. Pérdida de información. . . . . . . . . . . . . . . . . . . . . . . . 120 A.9. Riesgo R08. No entender el código de la aplicación open-source. . . . . . . . . 120 A.10.Presupuestosimulado. ............................... 122 A.11.Presupuestoreal................................... 123 XIX
LISTA DE TABLAS A.12.Product Backlog inicial............................... 123 A.13.Historias de usuario asociadas a la épica 2 (EP02: Ingeniería inversa) . . . . . 124 A.14.Historias de usuario asociadas a la épica 1 (EP01: Migración de XML a Jetpack Compose)...................................... 124 B.1.TareasdelSprint0................................. 126 B.2.TareasdelSprint1................................. 127 B.3.TareasdelSprint2................................. 128 B.4.TareasdelSprint3................................. 129 B.5.TareasdelSprint4................................. 130 B.6.TareasdelSprint5................................. 131 B.7.TareasdelSprint6................................. 131 B.8.TareasdelSprint7................................. 132 B.9.TareasdelSprintextra............................... 133 B.10.Costerealfinal ................................... 134 XX
CAPÍTULO 1. INTRODUCCIÓN Capítulo 1 Introducción 1.1. Contexto Este trabajo de fin de grado se va a llevar a cabo junto con Izertis [21], una empresa multinacional especializada en el sector tecnológico. Su sede principal se encuentra en Gijón, aunque posee varias sedes y oficinas en otras partes de la península como Valencia o Valladolid. Además presenta alguna sede en otros países de diferente continente como, por ejemplo, México. El equipo que trabaja en Valladolid es puramente nativo de Android. En concreto, se encuentran desarrollando la aplicación Android de ownCloud [36], aplicación open-source sobre la que se va a trabajar en el TFG. ownCloud es un servicio de almacenamiento y sincronización de archivos multiplataforma que se puede alojar en un servidor propio. La principal ventaja que tiene esta aplicación respecto a sus principales competidoras como Google Drive,OneDrive oDropbox, es que al estar instalado en nuestro propio hosting permite diseñar la estructura de todo el sistema de almacenamiento, además de tener el control total sobre la privacidad de todos los archivos existentes [54]. 1.2. Motivación La principal motivación para la realización de este trabajo es la aplicación de todos los conocimientos aprendidos durante las horas de prácticas curriculares en la mejora de la aplicación open-source sobre la que se va a trabajar. Durante los últimos años ownCloud ha sufrido bastantes modificaciones en cuanto a su estructura se refiere, por lo que la documentación no se encuentra totalmente actualizada. A partir de un proceso de ingeniería inversa se actualizará y se documentará parte de la aplicación actual. Además, actualmente la incorporación de nuevo personal al equipo del 1
1.3. PROYECTOS OPEN-SOURCE proyecto requiere un proceso de formación intenso utilizando horas de trabajo de un ingeniero senior, en el que se explique la arquitectura y estructura de la aplicación, la forma de trabajo del equipo o incluso las decisiones que se han tomado para el desarrollo. Contar con una documentación actualizada permitiría la autoformación de los nuevos integrantes, siendo sólo necesario algunas sesiones para aclarar dudas con los ingenieros senior que se encuentren dentro del equipo. Por otro lado, el actual framework de interfaz de usuario con el que se trabaja en la mayoría de las actuales aplicaciones en Android es Jetpack Compose [2], dejando de lado el desarrollo de interfaces basado en XML como se venía haciendo anteriormente. En la aplicación Android para ownCloud se desarrollaron las interfaces de usuario en el formato XML, por lo que durante el desarrollo de este trabajo de fin de grado se migrará una de sus pantallas al framework anteriormente mencionado. 1.3. Proyectos open-source Un proyecto open-source en un entorno informático [33] es aquel proyecto cuyo código está diseñado para que sea accesible a todo el mundo. Todos pueden ver, modificar y distribuir el código de la forma en la que vean conveniente. Estos proyectos se desarrollan de forma diferente a otros proyectos convencionales. Todo depende de la revisión de las múltiples personas que trabajen en el proyecto, además del apoyo de la propia comunidad. Otra de las características que tienen los proyectos open-source respecto a cualquier otro tipo de proyecto es que suelen ser más económicos, flexibles y duraderos [43, 18]. En un proyecto open-source se encuentran varios roles especializados: Autor: Persona(s) que creó(crearon) el proyecto. Dueño: Personas que poseen la propiedad administrativa sobre la organización o el repositorio en el que se está desarrollando todo el proyecto. Encargados: Personas encargadas de dirigir y administrar la organización del proyecto. Colaboradores: Cualquier persona que haya aportado con alguna contribución durante el desarrollo del proyecto. En inglés se conoce con el término contributor. Comunidad: Personas que utilizan el producto creado. Pueden expresar su opinión acerca de la dirección que está tomando el proyecto. Aparte de los diferentes roles, también se utilizan distintas herramientas. Estos medios facilitan el trabajo a todos los implicados en el proyecto. Las herramientas que se utilizan son las siguientes [34]: Issue Tracker: Medio a través del cual las personas que conforman el proyecto discuten los problemas relacionados con el mismo. 2
CAPÍTULO 1. INTRODUCCIÓN Pull request: Lugar donde las personas discuten y revisan los cambios que han tenido lugar durante el desarrollo. Foros de discusión: Algunos proyectos utilizan estas herramientas para iniciar hilos de conversación de diversos tópicos/temas. Canal de chat síncrono: Medio a través del cual todos los participantes del proyecto pueden comunicarse diariamente para la organización interna y colectiva. 1.4. Ingeniería inversa La ingeniería inversa es un proceso de desarrollo en el sector de la tecnología que consiste en obtener información de cómo está construido o cómo funciona un programa, objeto o sistema ya creado. Para ser más exactos el origen de la ingeniería inversa se encuentra en la ingeniería mecánica. Si en la ingeniería se diseñan los componentes de un producto para su montaje posterior, la ingeniería inversa consiste en el proceso inverso [19, 52]. 1.4.1. Ingeniería inversa de software El primer paso para llevar a cabo ingeniería inversa sobre un producto software es entender el código. Sin la comprensión del mismo resulta imposible obtener conclusiones. Durante este proceso, el código no se modifica como tal, sino que se sacan una serie de conclusiones para la reestructuración o rediseño del producto. Al aplicar ingeniería inversa sobre un producto software se puede llegar a varias conclusiones como la reducción de la complejidad del sistema, recuperación de información/documentación perdida o desactualizada o incluso la reutilización de sistemas completos [20]. Con un proceso de ingeniería inversa en el caso del software, se parte de código y los resultados del proceso serán artefactos de niveles de abstracción superior, hasta el nivel que se plantee llegar, como diseño, análisis, requisitos. 1.5. Objetivos Los objetivos principales que se quieren conseguir con la realización de este TFG son los siguientes: Comprensión y documentación de la aplicación open-source. Como se va a trabajar sobre una aplicación open-source, será necesario entender el código así como la estructura de la propia aplicación. Una vez comprendidos los aspectos fundamentales, se llevará a cabo la actualización de la documentación a través de diagramas tanto del marco estático como dinámico. Comprensión y aprendizaje de Jetpack Compose. No se había utilizado este framework de Android anteriormente durante el transcurso del grado, por lo que la 3
2.2. TECNOLOGÍAS PARA LA GESTIÓN DEL PROYECTO Figura 2.1: Tablero de GitHub Una vez que ya se ha creado el fork, tenemos la posibilidad de crear una issue. Una issue consiste en un registro de una tarea, problema o sugerencia relacionada con el proyecto de software que se esté gestionando en GitHub. En este trabajo se abre una issue por cada tarea que se tenga que hacer para la migración de XML a Jetpack Compose. Para cada una de esas tareas se abre un pull request en el repositorio. Su principal función es permitir a los colaboradores proponer cambios en el código, por tanto cada vez que se vaya a realizar algún cambio sobre una rama se creará un pull request. Cada uno de los pull request incluye los cambios propuestos además de una descripción en los que se explican los motivos de esos cambios y cualquier información para los revisores. Los colaboradores pueden consultar un pull request, realizar comentarios, sugerir modificaciones o incluso aprobarlo para que los cambios se fusionen con la rama principal. Estos elementos se pueden asociar mutuamente pudiendo llevar a cabo un seguimiento de cada uno de los cambios que se han realizado respecto a una tarea en concreto. 2.2.2. Git Git [12] es un sistema de control de versiones distribuido, diseñado para manejar todo tipo de proyectos, desde los más pequeños hasta los más grandes, con velocidad y eficiencia. Fue creado por Linus Torvalds en 2005 para el desarrollo del kernel de Linux, pero desde entonces se ha convertido en uno de los sistemas de control de versiones más populares y ampliamente utilizado en todos los tipos de proyectos de software. Se basa en un sistema de repositorios y ramas. Si lo que queremos es añadir por ejemplo una nueva funcionalidad a nuestra aplicación, lo que tenemos que hacer es crear una nueva rama a partir de la rama 10
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS de desarrollo normalmente nombrada como develop. En el caso de ownCloud cada rama de funcionalidad surge a partir de la rama principal, denominada master. Su funcionamiento se puede ver de forma gráfica en la Figura 2.2. Figura 2.2: Funcionamiento principal de las ramas de Git [11] Una vez que se ha trabajado en ese cambio y después de haber pasado satisfactoriamente por varias fases de aceptación, revisión e integración se puede fusionar esa rama en la rama master. Con esto se consigue añadir esa funcionalidad que se ha desarrollado en la aplicación principal y por tanto que ese cambio que se ha hecho, lo pueda ver el usuario que utiliza dicha aplicación en este caso. Para poder llevar a cabo todo este proceso, se han de seguir unos pasos (forma de trabajo establecida en ownCloud) para poder tener la rama actualizada respecto a la rama principal además de evitar cualquier tipo de conflicto en el código. A continuación se muestran algunos comandos [6] útiles para dicho proceso: git fetch: Se utiliza para recuperar los últimos cambios de un repositorio remoto sin fusionarlos automáticamente con la rama local actual. Esto significa que el comando obtiene la última versión de todas las ramas del repositorio remoto que no se tienen localmente y actualiza la información de seguimiento de las ramas remotas, pero no modifica el trabajo local en absoluto. git rebase: Se utiliza para reorganizar y modificar la historia de commits en una rama. En lugar de fusionar como lo hace git merge, reescribe la historia de la rama actual para que parezca que se basa en el punto más reciente de la rama especificada. El uso común de este comando es integrar cambios de una rama secundaria en una rama principal de manera más limpia y ordenada, evitando así líneas de tiempo confusas y commits redundantes. Adicionalmente existe una forma de utilizar este comando de forma interactiva. Esto se hace con git rebase -i <commit>. Esta funcionalidad te permite revisar y modificar la historia de commits antes de fusionarlos con otra rama. Al ejecutar este comando aparecerá una lista de todos los commits a partir del cual se ha ejecutado y una serie de instrucciones para poder manipular esa historia. También se puede dar el caso de que salte un conflicto de la rama en la que se esté trabajando con la rama principal. En el momento en el que salta ese conflicto será necesario resolverlo. 11
2.2. TECNOLOGÍAS PARA LA GESTIÓN DEL PROYECTO Una vez que se ha resuelto se comprueba con el comando git status, el cual muestra si existen más conflictos en los archivos respectivos. Si todo está correcto se comprueba el siguiente commit utilizando el comando git rebase --continue. Estos pasos se repiten hasta que se hayan solucionado todos los conflictos. git add: Se utiliza para agregar cambios realizados en archivos específicos al área de preparación (staging area). Este área de preparación es un paso intermedio antes de confirmar los cambios mediante git commit. git commit: Se utiliza para confirmar los cambios realizados en los archivos de un repositorio local. Al ejecutarlo, se abre un editor de texto donde puedes escribir un mensaje que describe los cambios que se han realizado durante esta confirmación. Este mensaje es sumamente importante ya que proporciona contexto sobre todos los cambios realizados. La principal ventaja que tiene Android Studio (herramienta que se explicará más adelante) es que presenta un botón que fusiona tanto el comando git add como el comando git commit, facilitando la tarea en gran medida. El funcionamiento de este comando junto con el comando git add se puede apreciar en la Figura 2.3. Figura 2.3: Funcionamiento de git add ygit commit en el área de preparación, árbol de trabajo y repositorio [29] git log: Se utiliza para mostrar el historial de commits en una rama específica. Al ejecutarlo se despliega una lista de los commits realizados en esa rama, mostrando información como el autor, la fecha y hora y el mensaje asociado a ese commit. git reset: Se utiliza para deshacer cambios en el área de preparación y/o en el árbol de trabajo. Se puede utilizar de varias formas dependiendo del contexto. git reset <nombre del archivo> para quitar un archivo específico del área de preparación, manteniendo los cambios en el árbol de trabajo. git reset --hard para deshacer todos los cambios en el árbol de trabajo y en el área de preparación. git checkout: Se utiliza para cambiar entre ramas, restaurar archivos y deshacer cambios en el directorio de trabajo. La funcionalidad varía dependiendo de los argumentos que se le pase. git checkout <nombre de la rama> para cambiar a otra rama en el repositorio. Esto permite trabajar en diferentes ramas de desarrollo de forma independiente. git checkout --<nombre del archivo> para restaurar ese archivo a su estado tal como estaba en el último commit. git checkout -b <nombre de la nueva rama> <hash del commit> para crear una nueva rama basada en un commit específico. 12
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS git push: Se utiliza para enviar los cambios locales a un repositorio remoto. Esto permite sincronizar el trabajo, compartiendo los commits con otros colaboradores o actualizando el estado del repositorio remoto con los cambios locales. Este comando no permite subir el contenido cuando existen diferencias entre lo hay que en remoto y lo que hay en local. Por este motivo, existe una opción git push -f que se utiliza para forzar la subida de los archivos. Esta opción es peligrosa, pero en muchas ocasiones resulta necesaria, ya que sin ella el propio Git no te permite subir los archivos al repositorio remoto. 2.3. Tecnologías para el análisis, diseño y documentación 2.3.1. Overleaf Overleaf [35] es una plataforma en línea que permite a los usuarios escribir, editar y colaborar en documentos LaTeX en tiempo real. LaTeX es un sistema de composición de textos ampliamente utilizado para la creación de documentos científicos y técnicos ya que ofrece un alto control sobre el diseño y la estructura del documento. Esta aplicación simplifica el proceso de escritura además de tener una compilación automática, control de versiones, plantillas predefinidas y la capacidad de compartir documentos con otros usuario en tiempo real, además de trabajar de forma colaborativa. Es una aplicación gratuita a manos de todo el público y que ha servido en este trabajo para desarrollar toda la memoria. 2.3.2. Astah Professional Astah Professional [5] es una herramienta de modelado visual y diseño de software utilizada por desarrolladores y profesiones de la ingeniería del software para crear diagramas UML, diagramas de flujo de datos, diagramas de clases, diagramas de secuencia y otro tipo de diagramas que ayudan en el proceso de diseño y documentación de software. Esta herramienta no es gratuita y es necesario pagar una licencia para uso, pero en este caso la Escuela de Ingeniería Informática proporciona una licencia para estudiantes. En este proyecto la utilidad de esta herramienta ha sido para crear todos los diagramas relacionadas con la estructura de ownCloud. 2.4. Tecnologías para el desarrollo del proyecto 2.4.1. Android Studio Android Studio [10] es un entorno de desarrollo integrado (IDE) creado por Google para desarrollar aplicaciones móviles Android. Proporciona herramientas y recursos para escribir código, depurar, compilar y probar aplicaciones Android de manera eficiente. Además integra 13
2.4. TECNOLOGÍAS PARA EL DESARROLLO DEL PROYECTO funcionalidades como el diseño de interfaces de usuario, gestión de versiones y compatibilidad con diferentes dispositivos Android. Este entorno de desarrollo es gratuito y está a disposición de todo el mundo. Se ha utilizado la versión Android Studio Hedgehog | 2023.1.1 Patch 2para el desarrollo del TFG. 2.4.2. Android Android [1] es un sistema operativo pensado para dispositivos móviles al igual que otros sistemas operativos como pueden ser iOS, Symbian o incluso Blackberry OS. La diferencia de Android respecto a estos sistemas operativos es que está basado directamente en Linux. En un principio fue desarrollado por Android Inc, sin embargo más tarde fue adquirido por Google LLC en el año 2005. Dos años después fue presentado junto con la fundación de Open Handset Alliance para avanzar los estándar abiertos de los dispositivos móviles. Respecto algunos temas del TFG, en Android existen dos formas de para desarrollar interfaces de usuario. La primera y más antigua es a través de XML, en el que se van definiendo etiquetas junto con sus atributos. La otra forma de hacerlo es la que actualmente se aplica en muchas aplicaciones Android y lo que la documentación de Android Developers considera como oficial: Jetpack Compose. Ambas tecnologías se explicarán en el Apartado 2.4.4 y Apartado 2.4.5 respectivamente. 2.4.3. Kotlin Kotlin [26] es un lenguaje de programación moderno y estáticamente tipado que se ejecuta en la máquina virtual de Java (JVM) y también puede ser compilado a JavaScript o código nativo. Fue desarrollado por JetBrains y se anunció por primera vez en 2011. Kotlin es completamente interoperable con Java, lo que significa que puede llamar y ser llamada desde código Java sin ningún tipo de problema. Esta característica es uno de sus mayores puntos fuertes. Además está diseñado para reducir la cantidad de código necesario para escribir programas en comparación con Java. Esto incluye menos verbosidad en las declaraciones y la eliminación de patrones de diseño redundantes. Por otro lado, Kotlin introduce el manejo de nulabilidad a nivel de lenguaje y funciones de orden superior (lambdas). Es el lenguaje recomendado para desarrollar Android nativo y que, hoy en día, ha sustituido a Java. En este proyecto es el lenguaje que se ha utilizado para llevar a cabo la migración de la interfaz de usuario. 2.4.4. XML XML [55] es un lenguaje de marcado similar a HTML. Sus siglas significan Extensible Markup Language. En Android su principal uso es para definir la disposición y los elementos que conforman la interfaz de usuario de una aplicación. Esto incluye la disposición de elementos visuales como pueden ser botones, campos de texto, imágenes, etc.. Android proporciona por defecto un conjunto de etiquetas para definir cada uno de esos elementos como 14
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS pueden ser: LinearLayout,RelativeLayout,TextView,Button, entre otras muchas. Además de aplicarse a la interfaz de usuario también se utiliza para definir otro tipo de recursos estáticos como cadenas de texto, estilos, colores, dimensiones, menús, animaciones, etc... Este tipo de recursos se definen en archivos separados y se utilizan en la aplicación para mantener una separación clara entre la lógica de la aplicación y los elementos visuales y estéticos. En XML el enfoque es imperativo, es decir: se describe la estructura directamente y se aplican los cambios manualmente cuando es necesario. Además para poder ver los cambios que se realizan es necesario compilar y ejecutar la aplicación, lo que puede resultar un proceso bastante lento para la iteración y desarrollo de la IU. 2.4.5. Jetpack Compose Jetpack Compose [2] es un conjunto de bibliotecas modernas de Android que simplifica y acelera el desarrollo de la interfaces de usuario nativas. Está diseño para reemplazar el tradicional enfoque basado en XML y ofrecer una forma más intuitiva y declarativa de construir interfaces de usuario en Android. Algunas de las características que presenta Jetpack Compose son: Declarativo y funcional: En lugar de definir directamente las interfaces y manipularlas a través de un código procedural permite describir directamente como debería ser la interfaz de usuario y de forma automática se encarga de renderizarla eficientemente. Funciones Composables: Todas las interfaces de usuarios se construyen a partir de funciones composables las cuales reciben la etiqueta @Composable. Estos composables pueden tener a su vez otros composables, lo que permite construir interfaces complejas y modulares de manera muy intuitiva. Preview en tiempo real: Permite visualizar cómo se verá y se comportará la interfaz de usuario en tiempo real mientras se está desarrollando. Esto agiliza el proceso de diseño y desarrollo al proporcionar la retroalimentación instantánea al realizar los cambios respectivos. Interoperabilidad: Es totalmente compatible con cualquier código y bibliotecas existentes de Android, lo que significa que se puede integrar fácilmente en proyectos existentes. Al mismo tiempo en un proyecto se permite que convivan simultáneamente tanto XML como Jetpack Compose sin ningún problema, resultando muy útil en la migración de aplicaciones de gran tamaño como es en el caso de este trabajo. Soporte para el ciclo de vida Android: Se integra perfectamente con el ciclo de vida de cualquier aplicación Android, gestionando automáticamente la actualización y destrucción de las vistas de la interfaz de usuario. De forma resumida, se podría decir que Jetpack Compose ofrece una forma moderna y potente, con una experiencia de desarrollo más fluida, productiva y mantenible en comparación con aquellas interfaces de usuario desarrolladas a partir de XML y código procedural. 15
2.4. TECNOLOGÍAS PARA EL DESARROLLO DEL PROYECTO Para el desarrollo de parte de este trabajo de fin de grado se ha tomado como referencia el Trabajo de Fin de Máster (TFM) de Juan Carlos Garrote Gascón [23], el cual consistía en una guía para migrar interfaces de usuario de XML a Jetpack Compose. 2.4.6. Gradle Gradle [17] es una herramienta de automatización de construcción de proyectos de código con soporte para diferentes acciones del ciclo de vida del código, y muy importante para la gestión de dependencias. Es especialmente popular en el ecosistema de desarrollo de aplicaciones Android, donde se utiliza para construir, probar y desplegar aplicaciones. El proceso de construcción se basa directamente en la compilación, enlazado y empaquetado del código. Es muy popular por el hecho de que es capaz de soportar varios lenguajes como por ejemplo Java, Scala, C/C++ y Groovy, pero como se ha mencionado anteriormente, su fuerte se encuentra en aplicaciones Android. [49] 16
Parte I Ingeniería inversa 17
CAPÍTULO 3. ESTUDIO DE OWNCLOUD Y CLEAN ARCHITECTURE Capítulo 3 Estudio de ownCloud y Clean Architecture 3.1. ownCloud La aplicación open-source ownCloud [36] es sobre la que gira todo el proyecto. A pesar de que ya se ha explicado ligeramente su funcionamiento principal en el Apartado 1.1, en esta sección se llevará a cabo una descripción con más detalle. ownCloud es un servicio de almacenamiento en la nube y sincronización de archivos multiplataforma que se puede alojar en un servidor propio. La principal ventaja, como se mencionó en el Capítulo 1, que tiene esta aplicación sobre el resto de aplicaciones con una funcionalidad parecida es que, al estar instalado en nuestro propio hosting, permite diseñar la estructura de todo el sistema de almacenamiento además de tener el control total sobre la privacidad de todos los archivos existentes. Actualmente ownCloud cuenta con varios clientes dependiendo de la plataforma que se utilice. Tiene una versión web, una versión de escritorio, una versión de Android y una versión de iOS. Todo lo que se va a desarrollar en este trabajo está relacionado con la aplicación en su versión de Android. A diferencia del resto de equipos de desarrollo, los cuales se encuentran en Alemania, el equipo de Android tiene su sede en las oficinas de Izertis en Valladolid. Además Izertis también cuenta con un desarrollador back-end, pero se encuentra en un equipo totalmente distinto. Continuando con el back-end, existen dos tipos de servidores: oC10 (ownCloud 10) y oCIS (ownCloud Infinite Scale) [38]. En primer lugar, oC10 es la versión de ownCloud que presenta una funcionalidad similar a otras aplicaciones del estilo. Permite el almacenamiento de cualquier tipo de archivo en una estructura de ficheros que haya definido el usuario. Por otro lado, está oCIS (ownCloud Infinite Scale). La principal diferencia de esta versión respecto a la mencionada anteriormente es que su arquitectura está basada en microservicios en la nube. No depende directamente 19
3.2. CLEAN ARCHITECTURE 26
CAPÍTULO 4. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA ESTÁTICA Capítulo 4 Ingeniería inversa de la arquitectura de ownCloud: vista estática 4.1. Clean Architecture en ownCloud: vista estática Una vez que ya se ha hecho una introducción de lo que es ownCloud (en el Apartado 3.1) y cómo es una arquitectura limpia (en el Apartado 3.2), se mostrará cómo están ambas partes relacionadas entre sí. Para empezar, el proyecto se encuentra dividido en cuatro módulos totalmente diferentes. Está el módulo owncloudApp el cual corresponde con la capa de interfaz de usuario, los módulos owncloudData yowncloudComLibrary, los cuales entrarían dentro de la capa de datos y por último el módulo owncloudDomain, el cual corresponde corresponde con la capa de dominio o lógica de negocio. Entrando más a detalle en la estructura de la aplicación, se mostrarán varios diagramas en los que se observa de forma clara todo lo mencionado anteriormente. Debido a la gran amplitud de la propia aplicación se han elegido dos casos de uso para mostrar la arquitectura, sus clases y todas las relaciones que existen entre las diferentes capas. Esos dos casos de uso son: consulta de estado de las subidas (pantalla en la que se trabajará en la migración) ysubida de un fichero. El hecho de que haya dos casos de uso, es porque el primero no utiliza el módulo owncloudComLibrary, pues no presenta ninguna llamada de red hacia un servidor externo, mientras que en el segundo caso de uso sí que se utiliza la arquitectura en su totalidad. 27
4.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA ESTÁTICA Figura 4.1: Arquitectura principal de ownCloud 28
CAPÍTULO 4. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA ESTÁTICA 4.1.1. Caso de uso genérico Como se puede ver en la Figura 4.1, la arquitectura de la app Android de ownCloud sigue esa Clean Architecture de la que se ha hablado en el Apartado 3.2. La capa de dominio (owncloudDomain) corresponde al centro de la arquitectura, considerándose la capa “sumidero” pues ninguna relación puede salir de ese módulo hacia módulo superiores. Se han establecido una serie de colores para asignar a cada módulo de la aplicación, dependiendo de la capa a la que correspondan, en los diagramas que documentan la arquitectura. Esto también se verá reflejado en las clases que se encuentran en cada uno de los módulos. El color verde corresponde a todo aquello relacionado con la capa de presentación, en este caso al módulo owncloudApp (el único en dicha capa). El color azul se corresponde a todo aquello que pertenezca a la capa de datos, ya sea parte del módulo owncloudData uowncloudComLibrary. Finalmente, el color rojo está asociado a todo lo que se encuentre dentro de la capa de dominio. En este caso particular todo aquello que esté dentro del módulo owncloudDomain. La estructura de un caso de uso genérico se puede observar en la Figura 4.2. La explicación del mismo seguirá la disposición de las capas de la clean architecture. Dentro del módulo de presentación, se identifican dos clases principales: un Fragment/Activity (dependiendo del caso de uso) y un ViewModel. El Fragment/Activity constituye la parte visual de la aplicación, todo aquello que el usuario ve a través de la pantalla. Cuando se produce alguna interacción del usuario con la interfaz, se llama directamente al ViewModel. En todos los casos de uso, se establece una asociación entre un Fragment oActivity con uno o varios ViewModels, de ahí esa relación 1...*. También existe la posibilidad de que haya varias Activities oFragments asociados entre sí. Ocurre lo mismo en la otra dirección, un ViewModel puede estar relacionado con una o más clases de IU de forma simultánea. Dependiendo de cada caso de uso se pueden tener más o menos clases con diferentes funciones, pero todas ellas cumplen al menos con esta estructura mencionada. La siguiente capa a tratar es la capa de datos, más concretamente se iniciará con el módulo owncloudData. Aquí hay algo en particular en el diagrama, y es que existen clases que presentan un color más claro que la clase Repository. Esto es debido a que todas esas clases no siempre se utilizan en todos los casos de usos. Dependiendo de la funcionalidad, se prescindirá de algunas y por ese motivo se ha querido reflejar en el diagrama. Dentro de este primer módulo, siempre nos encontraremos con el Repository. Esta clase es la implementación del repositorio presente en la capa de dominio, la cual se definirá en último lugar. Esta implementación puede tener una relación directa con un LocalDataSource y un RemoteDataSource (no siempre se dan los dos casos de forma simultánea). La primera se utiliza siempre y cuando se hagan llamadas a la base de datos local mientras que la segunda se utiliza cuando es necesario realizar una llamada de red para llevar a cabo cualquier tipo de operación remota. Tomando el camino de la base de datos local, se encuentra el DAO. Esta clase es el nexo entre la base de datos y la aplicación. Se encarga de realizar las operaciones necesarias para transformar las clases que pertenecen a la propia aplicación en entidades que se pueden almacenar en base de datos. Explicando la relación 1...* a1...*, no quiere decir que un LocalDataSource esté relacionado con varios DAOs de un mismo tipo, sino que puede haber varios de diferente tipo. Al mismo tiempo, un DAO puede estar presente en varios LocalDataSource. Finalmente, si se sigue el flujo, se encuentra la LocalEntity. Como ya se 29
4.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA ESTÁTICA Figura 4.2: Ejemplo de caso de uso genérico ha mencionado anteriormente, esta es la entidad que se almacenará en base de datos. Dicha clase únicamente presenta los tipos de datos básicos de Kotlin, teniendo que haber convertido anteriormente cualquier tipo definido en la aplicación en uno de estos. Si se sigue el otro flujo, se encuentra el RemoteDataSource. A diferencia del otro data source, este presenta una relación directa con una clase de otro módulo. Aquí es donde entra en juego el módulo owncloudComLibrary, encargado de realizar todas las llamadas de red. En primer lugar está el Service. Es una clase que reúne todas la operaciones que se necesitan realizar sobre el servidor externo. Dentro de esta clase, justo como se acaba de mencionar, están todas las operaciones de tipo RemoteOperation. Éstas pueden ser tanto de lectura como de escritura. Finalmente se puede apreciar como existe una asociación con la clase RemoteEntity. Esta clase es la encargada de mapear todos los datos que provienen del servidor remoto y que son necesarios para realizar ciertas operaciones en la aplicación. Por último, se encuentra el módulo owncloudDomain, el cual siempre tiene tres partes 30
CAPÍTULO 4. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA ESTÁTICA principales y bien definidas. En primer lugar está el UseCase. Esta clase es llamada directamente por el ViewModel localizado en la capa de presentación. Existen tantos casos de uso como funcionalidades haya en la aplicación. Esta clase tiene una dependencia directa con otras dos clases. Estas dos son el modelo o Model y el Repository. El modelo en este diagrama aparece como una única clase, pero en un ejemplo real corresponde con varias clases relacionadas entre sí, incluidas aquellas que se encuentran en módulos diferentes. 4.1.2. Caso de uso: Subida de un fichero Tras haber hablado de la arquitectura general de la aplicación, se detallará toda la información relacionada con el caso de uso de subida de un fichero. Siguiendo el mismo orden que antes, se mostrará en un primer lugar el módulo owncloudApp. Tras ello se mostrará toda la información asociada a owncloudData. Seguido a esto se explicará todo lo relacionado con el módulo owncloudComLibrary. Finalmente se entrará en detalle en el módulo owncloudDomain, siendo este el centro de toda la estructura de la aplicación. Por otro lado se seguirá con la relación de colores que se había definido en el Apartado 4.1.1. Las clases pertenecientes al módulo owncloudApp llevan el color verde. Las clases de los módulos owncloudData y owncloudComLibrary el azul y las clases de owncloudDomain el color rojo. El resto de clases que tienen un color más claro corresponden a aquellas que no se encuentran reflejadas en la Figura 4.2 y por tanto no son las clases más importantes a pesar de tener una relación directa con el caso de uso y formar parte del mismo. Figura 4.3: Modules&UsesStyle del módulo owncloudApp perteneciente al caso de uso de subida de un fichero En la Figura 4.3 se tienen todas las clases participantes en este caso de uso que pertenecen al módulo owncloudApp. En primer lugar se tiene FileDisplayActivity, la cual será la clase en la que se implemente toda la lógica relacionada con las acciones del usuario en caso de que quiera subir cualquier tipo de archivo. Esa clase tiene como atributo un Fragment, el cual recibe el nombre de MainFileListFragment. Esta clase mostrará por pantalla toda la interfaz relacionada con la lista principal en la cual se ven todos los archivos del Personal space. Otra de las dependencia que se tiene con la Activity es el ViewModel. En este caso la dependencia es con TransfersViewModel. En el momento en el que el usuario haya seleccionado el archivo que quiere subir desde el sistema de ficheros, se ejecutará el UseCase correspondiente. En este ejemplo concreto 31
4.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA ESTÁTICA se tienen dos casos de uso diferentes: UploadFilesFromContentUriUseCase yUploadFile- FromContentUriUseCase. El hecho de que estas dos clases se encuentren en la capa de presentación y no en la capa dominio, es porque se necesita un contexto de la aplicación para realizar ciertas acciones. En Android esto sólo es posible conseguirlo en esta capa, por lo que se ha hecho una excepción respecto a la estructura que aparece reflejada en la Figura 4.2 (esto resulta algo fuera de lo normal, y que se podría tener en cuenta a la hora de rediseñar un caso de uso o incluso la aplicación). En primer lugar, se tiene un caso de uso para todos los archivos seleccionados, los cuales se guardarán en base de datos y luego se tiene el otro caso de uso por fichero individual. Este será el encargado de subir el archivo al servidor correspondiente para que más tarde se haga la sincronización y el resto de operaciones oportunas. Esas operaciones se harán a través de un Worker, que en este caso recibe el nombre de UploadFileFromContentUriWorker. Esto es simplemente para hacer todo el trabajo en segundo plano y no interferir en la secuencia principal. Figura 4.4: Modules&UsesStyle del módulo owncloudData perteneciente al caso de uso de subida de un fichero Respecto al módulo owncloudData, todas las clases y sus relaciones se encuentran reflejadas en la Figura 4.4. En primer lugar se encuentra la implementación de la interfaz del repositorio. Esta clase recibe el nombre OCTransferRepository. Ésta tiene dos atributos o propiedades bien definidas. Por un lado está el LocalTransferDataSource, clase encargada de realizar cualquier tipo de operación de forma local. Por el otro lado está la interfaz que sirve como conexión para cualquier operación que se haga de forma remota, recibiendo el nombre 32
CAPÍTULO 4. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA ESTÁTICA de RemoteTransferDataSource. Respecto a la parte de datos local, la implementación de LocalTransferDataSource se encuentra en la clase OCLocalTransferDataSource presente en el paquete implementation. Esta clase tiene una asociación con la clase TransferDAO, siendo una propiedad de la primera. El DAO servirá para poder almacenar en base de datos todos aquellos ficheros que se quieran subir, los cuales están convertidos en objetos de tipo OCTransferEntity. Siguiendo el camino de las operaciones en remoto, se tiene que la implementación de RemoteTransferDataSource se encuentran en el mismo paquete que la implementación local. En este caso, la clase que lo implementa recibe el nombre de OCRemoteTransferDataSource, siguiendo el patrón del prefijo OC. Para acabar con este módulo, existe una clase denominada ClientManager la cual se encarga de gestionar todas las sesiones para conectarse a la red y que se encuentran directamente asociada con la implementación del data source remoto, siendo un atributo de la misma. De forma aislada se pueden ver las clases LocalStorageProvider yOCSharedPreferencesProvider. Ambas clases se utilizan en el caso de uso de forma complementaria para conseguir información que será utilizada en la lógica del caso de uso. Figura 4.5: Modules&UsesStyle del módulo owncloudComLibrary perteneciente al caso de uso de subida de un fichero 33
4.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA ESTÁTICA Siguiendo el orden que se había establecido previamente, todas las clases y relaciones pertenecientes al módulo owncloudComLibrary aparecen en la Figura 4.5. En primer lugar se tiene tres clases bien diferenciadas que participan en este caso de uso, todas ellas dentro del paquete files. La primera de ellas es FileService. Esta clase es simplemente una interfaz, la cual está implementada por OCFileService. Ésta última es la encargada de llevar a cabo todas las operaciones remotas dependiendo del caso de uso. Dentro de estas operaciones, se tiene la clase UploadFileFromFileSystemOperation cuya lógica consiste en subir los respectivos ficheros al servidor. En la parte inferior se pueden ver varias clases dentro del paquete common. Todas ellas participan en el caso de uso pues están relacionadas con la operación, pero no forman parte de la estructura general que se había mostrado en la Figura 4.2 Figura 4.6: Modules&UsesStyle del módulo owncloudDomain perteneciente al caso de uso de subida de un fichero Para el módulo owncloudDomain se tiene una gran diferencia respecto al otro caso de uso. Como se puede apreciar en la Figura 4.6 no se tienen los casos de uso en este módulo. Destacando entre todas las clases, está TransferRepository la cual es la interfaz a partir de la cual se harán todas las operaciones respectivas. A su vez se tiene las clases de OCTransfer, TransferResult,UploadEnqueuedBy,TransferStatus yUploadBehaviour. La relación que existe entre todas ellas es que la clase OCTransfer tiene un atributo de cada una de las otras clases además de otros atributos de tipos primitivos, de ahí la multiplicidad de 1 solamente en una dirección. Por otro lado también existe dependencia entre el repositorio y otras clases que no sean la de la propia subida, debido a que existen ciertos métodos que dependen de esas clases para que se ejecuten de forma correcta. 34
CAPÍTULO 4. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA ESTÁTICA Figura 4.7: Modules&UsesStyle del caso de uso de subida de un fichero En la Figura 4.7 se pueden apreciar todos los módulos junto con las clases del caso de uso completo. Se ha decidido mostrar únicamente las clases que están relacionadas entre sí pero pertenecen a diferentes módulos, ya que se quiere reflejar la alta cohesión y el bajo acoplamiento que existe. Como para este caso de uso los UseCase estaban el módulo de presentación no existe un ViewModel relacionado directamente con la capa de dominio. Es por ello que se tiene una relación con el repositorio desde el Worker. Por otro lado también se puede apreciar como existe una dependencia entre el módulo owncloudData y el módulo owncloudComLibrary. Esta dependencia viene dada por la relación que hay desde la clase 35
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.1: Diagrama de secuencia principal correspondiente al caso de uso de subida de un fichero. La función openBottomSheetToUploadFiles, la cual se encuentra desarrollada en la Figura 5.2 tiene un funcionamiento bastante sencillo. En primer lugar lo que se hace es un inflate sobre el LayoutInflater. Una vez que se ha hecho esto, se creará el diálogo que se va a mostrar por pantalla. Cuando ya se ha creado, se mostrarán las dos vistas posibles que tiene el diálogo: subida de ficheros desde el almacenamiento del sistema o subida de ficheros a través de la cámara. Tras haber construido el diálogo con las dos posibles opciones, junto con el texto correspondiente, se mostrará por pantalla. Figura 5.2: Diagrama de secuencia correspondiente a la función openBottomSheetToUploadFiles de la Figura 5.1 42
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA A partir de este momento, el usuario seleccionará la opción de subida de ficheros desde el sistema de archivos. Tal y como se muestra en la Figura 5.1, cuando el usuario lleva a cabo la acción correspondiente se ejecutará un nuevo método llamado uploadFromFileSystem además de ocultar el diálogo que había aparecido anteriormente. Esta llamada forma parte de una interfaz alojada en la clase MainFileListFragment cuya implementación se encuentra en la clase FileDisplayActivity. Por este motivo se ha mostrado toda la información asociada a este método en la Figura 5.3. Figura 5.3: Diagrama de secuencia correspondiente a la función uploadFromFileSystem de la Figura 5.1 Una vez que se realiza la llamada al método correspondiente, se crea un Intent implícito, pues no se determina a que componente se va a llamar. Tras haber creado el Intent, se establecen una serie de parámetros sobre ese componente y a partir de ahí se lanzará su ejecución haciendo que se abra el sistema gestor de ficheros del dispositivo. En este caso la función asociada a esa acción es startActivityForResult. El funcionamiento interno es que una función callback recibirá un aviso una vez que ya se haya terminado de elegir los ficheros que se quieren subir. A partir de este momento, se procesará toda la información que venga en el propio callback. Esta llamada se puede apreciar en el diagrama de la Figura 5.1, en el cual existe una llamada asíncrona sobre onActivityResult perteneciente a la clase FileDisplayActivity. 43
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.4: Diagrama de secuencia correspondiente a la función onActivityResult de la Figura 5.1 Tal y como se puede apreciar en la Figura 5.4, la llamada callback a esa función llega con tres parámetros diferentes. El primero de ellos es el requestCode, el cual indica el tipo de llamada que se está haciendo. Por otra lado se tiene el resultCode, el cual indica si las operaciones que se han hecho previamente son correctas y no ha habido ningún fallo. Por último está la variable data, en la cual viene toda la información asociada a los ficheros que se han seleccionado en el sistema gestor de archivos. Una vez que se recibe esa llamada, se llama a la función byPassUnlockOnce, cuyo funcionamiento se encuentra reflejado en la Figura 5.5. Un usuario tiene la posibilidad de establecer una contraseña cada vez que accede a own- Cloud, teniendo una mayor seguridad respecto a sus datos. El método de byPassUnlockOnce, lo que hace es desactivar ese paso si el tiempo en el que ha estado buscando los archivos que quiere subir ha excedido el tiempo límite para que vuelva a saltar la pantalla de introducir la contraseña. Después de haber ejecutado este método, se tiene una estructura condicional bastante larga y que para este caso de uso sólo aplica la primera condición1. 1El resto de los casos de esa estructura condicional no se van a desarrollar por motivos de extensión, además de no estar directamente relacionados con el caso de uso expuesto. 44
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA Figura 5.5: Diagrama de secuencia correspondiente a la función byPassUnlockOnce de la Figura 5.4 En caso de que el requestCode tenga un valor relacionado con la selección de contenido de cualquier otra aplicación, y el resultCode sea correcto, se ejecutará la función requestUploadOfContentFromApps, cuya implementación se ve reflejada en la Figura 5.6. En primer lugar, se crear un ArrayList de URIs totalmente vacío. Tras ello se recorrerá toda la lista de elementos que vienen en el data del Intent y se irán añadiendo a ese ArrayList que se ha creado anteriormente. Una vez que se ha formado correctamente toda la lista con las URIs de los elementos que se van a subir a la aplicación, se obtiene el directorio sobre el que se va a realizar dicha subida. Cuando el usuario no esté en una determinada ruta dentro de su sistema de ficheros en ownCloud, se subirá a la dirección root que está por defecto (/). Para cada uno de esos ficheros se necesitará obtener todos los permisos correspondientes. Esta funcionalidad se abstrae en el ref denominado getPermission, cuyo desarrollo se documenta en la Figura 5.7. Para cada uno de los elementos que pertenecen a la lista de URIs antes mencionada, se comprueba que se tenga permiso de escritura de todos los ficheros que se van a tratar. En caso de que esto no sea así, saltará una excepción de tipo RemoteException. La zona del código en la que se captura esta excepción está marcada en el fragmento combinado alt, el cual simplemente llamará a la clase Timber para generar un mensaje de error en forma de log. Una vez que se han conseguido todos los permisos de los archivos que se van a subir, se llama a la función uploadFilesFromContentUri, la cual se encuentra alojada en el TransfersViewModel. El desarrollo de esta función se documenta en la Figura 5.8. 45
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.6: Diagrama de secuencia correspondiente a la función requestUploadOfContentFromApps de la Figura 5.4. Después de recibir la llamada por parte del FileDisplayActivity, el ViewModel realizará una llamada a la clase de Android CoroutineScope de modo que ejecutará el caso de uso en otro hilo totalmente distinto al principal de forma asíncrona. Una particularidad que tiene Kotlin y que se ha utilizado en este proyecto son los operator. Un operator permite agregar funcionalidades nuevas a clases existentes sin tener que heredar de ellas o modificar su código fuente. Para este caso concreto se ha creado un operator relacionada con el método invoke de un caso de uso. Únicamente será necesario escribir el nombre del caso de uso con los parámetros necesarios sin la notación punto para poder ejecutarlo. Después de que se haya ejecutado de forma asíncrona, se recorrerá nuevamente la lista de todas las URIs creando un objeto de tipo DocumentFile para cada uno de los elementos. Cada elemento se guardará en base de datos local además de subirse al servidor remoto. En caso de que la creación del archivo sea fallida saltará un error en consola. Para llevar un orden de todo el caso de uso, primero se verá la funcionalidad del guardado del fichero en base de datos local la cual recibe el nombre de storeInUploadsDatabase. Luego se detallará toda la implementación de la función enqueueSingleUpload, la cual corresponde a la subida de un único fichero hacia el servidor. 46
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA Figura 5.7: Diagrama de secuencia correspondiente al ref getPermission de la Figura 5.6 Figura 5.8: Diagrama de secuencia correspondiente a la función uploadFilesFromContentUri de la Figura 5.6 En la Figura 5.9 se puede apreciar la relación que teníamos entre la capa de presentación y la capa de dominio. El caso de uso UploadFilesFromContentUriUseCase, a partir de los parámetros que se le pasan, crea un objeto de tipo OCTransfer. Una vez que se ha creado ese objeto, llamará al repositorio TransferRepository, cuya implementación se encuentra en otra capa totalmente distinta. Al igual que antes, se utiliza un diagrama diferente para mostrar la implementación de esa interfaz, junto con el resto de llamadas que se hagan en 47
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.9: Diagrama de secuencia correspondiente a la función storeInUploadsDatabase de la Figura 5.8 el flujo de actividad. Además de llamar al repositorio, se muestra un log con la información correspondiente a la creación del objeto y la llamada a la interfaz. Figura 5.10: Diagrama de secuencia correspondiente a la implementación de la interfaz TransferRepository de la Figura 5.9 La implementación del repositorio simplemente consisten en realizar una llamada a la clase LocalTransferDataSource, la cual tiene una relación directa con el DAO. En la Figura 5.10 se puede ver esa llamada. Al igual que antes, al tener una interfaz existe otro diagrama en el que ya se muestra todo su implementación. Todo ello se encuentra reflejado en la Figura 5.11. 48
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA Figura 5.11: Diagrama de secuencia correspondiente a la función saveTransfer de la Figura 5.10 Desde la implementación del LocalTransferDataSource, se recibe el objeto OCTransfer que se había creado en pasos anteriores, exactamente en la Figura 5.9. Para guardar este objeto en base de datos local será necesario transformar todas sus propiedades en tipos primitivos, pues son los únicos tipos admitidos. Esa transformación corresponde a la función toEntity. Una vez que se ha creado el objeto de tipo OCTransferEntity se llamará a la clase TransferDAO, la cual se encarga de realizar un insert con ese objeto y guardarlo directamente en la base de datos local a través de un insert, operación que añade una nueva entrada, pues es una base de datos relacional. En caso de que ya exista la entrada, reemplazará la que había previamente sobrescribiéndola, de ahí que la función sea insertOrReplace. Para conseguir todo esto se ha utilizado Room, una biblioteca nativa de Android que se utiliza en ownCloud para la construcción de la base de datos local. A partir de este momento ya se tiene guardado en base de datos la información asociada al archivo que se va a subir. Tras ello, y siguiendo el flujo que se muestra en la Figura 5.8, ahora hay que guardarlo en el servidor remoto a través de una llamada de red. Sin embargo, antes de esta llamada hay una serie de pasos intermedios como, por ejemplo, la implementación de la función enqueueSingleUpload. Desde el caso de uso uploadFilesFromContentUriUseCase se llama, con el operator que se había creado, al otro caso de uso que está relacionado directamente, el cual recibe el nombre de uploadFileFromContentUriUseCase. Desde este caso de uso se construirá un Worker (clase encargada de realizar operaciones en segundo plano), el cual será el encargado de realizar todas las acciones relacionadas con la llamada de red cuando el sistema operativo lo indique. Antes de crear el Worker se definen una serie de variables que son útiles para su construcción. Todo ello se ha abstraído en un ref con el nombre de Creation of variables of the worker. Esto se hace con el fin de evitar alargar demasiado el diagrama y, como consecuencia de esto, tener dificultad para apreciar todo lo importante referente al diagrama. 49
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.12: Diagrama de secuencia correspondiente a la función enqueueSingleUpload de la Figura 5.8 Figura 5.13: Diagrama de secuencia correspondiente al ref Creation of variable of the worker de la Figura 5.12 En la Figura 5.13 se aprecia la creación de todas esas variables, que se mencionaban anteriormente respecto a la construcción del Worker. En primer lugar, se creará un objeto de 50
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA tipo Data, el cual tiene seis pares de atributos de la forma <clave:valor>. En el diagrama no están reflejados todos ellos pero esto es debido a que el diagrama se hacía demasiado extenso y, por tanto, ilegible debido a su tamaño. El siguiente paso es comprobar si está habilitada la opción del Wi-Fi. Dependiendo del caso se elegirá un valor u otro. Una vez hecho esto, se inicializarán todos los valores del Builder para que más tarde pueda construir el Worker correctamente. Siguiendo la secuencia de la Figura 5.12, se inicializan todas esas variables que se habían creado en el ref y, finalmente, se hace un build construyendo el Worker con la información correspondiente y encolándolo en el WorkManager para que el sistema operativo lo ejecute siguiendo sus propios criterios internos. Volviendo nuevamente al diagrama de secuencia principal, reflejado en la Figura 5.1, se puede apreciar como existe una llamada asíncrona a la función doWork correspondiente a la clase UploadFilesFromContentUriWorker. El desarrollo de dicho método se encuentra en la Figura 5.14. Figura 5.14: Diagrama de secuencia correspondiente a la función doWork de la Figura 5.1 En primer lugar, se comprueba que todos los parámetros que recibe el Worker son correctos. Una vez que se haya comprobado, en caso de no ser correcto se devolverá un fallo y, por tanto, el caso de uso será cancelado ya que no se puede realizar correctamente la subida de los ficheros. Una vez que se tienen todos los parámetros, se cambiará el estado de la subida a In Progress a través de una llamada al repositorio. En este caso no se ha desarrollado todo lo correspondiente a este método pues sigue la misma secuencia que se ha descrito para guardar cada uno de los ficheros en base de datos local. Una vez que se ha modificado ese estado, se ejecutará otro caso de uso, el cual recibe el nombre de GetWebDavUrlForSpacesUseCase. Para no extender demasiado todos los diagramas, se ha referenciado ese caso de uso sin entrar a detalle. Este caso de uso se ha representado con otro color más claro, ya que a pesar de no ser el centro del caso de uso también es importante e interviene en el mismo, siendo parte de un include hacia el UseCase principal. Tras llamar a ese caso de uso se consigue el temporalPath, que tampoco se ha desarrollado pues incluía muchas autollamadas, las cuales no son demasiado importantes, pues el objetivo principal de estos diagramas es representar la comunicación entre objetos. Tras haber realizado todas estas operaciones se llevará a cabo un proceso de subida de fichero el cual se encuentra referenciado en el cuadro con nombre 51
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.24: Continuación del diagrama de secuencia correspondiente a la Figura 5.23 58
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA 5.1.2. Caso de uso: Consulta del estado de las subidas El caso de uso se inicia cuando el usuario pulsa sobre la opción de las subidas, la cual está situada en la barra inferior de la aplicación. Esta primera interacción se puede ver en la Figura 5.25. Figura 5.25: Diagrama de secuencia principal correspondiente al caso de uso de consulta de estado de las subidas Una vez que el usuario ha pulsado sobre esa acción, se crea la actividad UploadList- Activity. Nada más crearse se ejecutan una serie de métodos, los cuales sirven para inicializar todos los elementos visuales que van a aparecer por pantalla. Una vez que se han creado todos estos elementos se crea un fragment, más concreto un fragment de tipo TransferListFragment, el cual recibe el nombre uploadList. Después de haberse creado el fragment, se llama al FragmentManager y se muestra ese fragment por pantalla. La creación del uploadList se puede ver en la Figura 5.26. Lo primero que se hace dentro de ese fragment, es crear el ViewModel. En este caso es de tipo TransfersViewModel y recibe el nombre de transfersViewModel. La creación de esa clase está reflejada en la Figura 5.27. Siguiendo con el flujo, el siguiente paso que se realiza es crear el transfersAdapter. Esta clase será la encargada de distribuir todas las subidas, que se recuperen más adelante, en la lista que aparecerá por pantalla. Tras ello, se inicializan varios elementos de la vista. Por último, lo que se tiene son dos funciones diferentes. En primer lugar está la función denominada collectLatestLifecycleFlow. Su funcionalidad es estar escuchando constantemente, comprobando si se ha producido algún cambio en la lista de las subidas que se van a recuperar de base de datos local. En caso de que se produzca alguna modificación, el adapter se encargará de pintar toda esa la lista en la pantalla correspondiente. La última función que aparece ahí comprueba si alguna descarga está en progreso y notifica al adapter sobre algún cambio que haya, modificando de esta manera el estado de cada subida en pantalla. 59
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA Figura 5.26: Diagrama de secuencia correspondiente a la creación del TransferListFragment Figura 5.27: Diagrama de secuencia correspondiente a la creación del TransfersViewModel En la Figura 5.27 se muestra todo aquella relacionado con la creación de la clase denominada transfersViewModel. Dentro del init, la cual es la función que se inicia nada más crear la clase se inicializan dos atributos, que como ya se había mencionado anteriormente, se va estar observando para pintar lo correspondiente por pantalla. El primer de 60
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA ellos (workInfosLiveData) indica el progreso de todas las subidas que estén teniendo lugar en el sistema. El segundo de los atributos que se recuperan nada más crear la clase son todas las subidas que haya en base de datos local y si ha habido algún cambio sobre ellas (transfersWithSpaceStateFlow). Este atributo es un combine de varios elementos. En primer lugar se obtiene todos los subidas que haya en base de datos local a través del caso de uso GetAllTransfersAsStreamUseCase. La implementación de la interfaz (transferRepository) se encuentra reflejada en la Figura 5.28. Después de haber ejecutado ese caso de uso, se ejecutará otro caso de uso diferente el cual recibe el nombre de GetSpaces- FromEveryAccountUseCaseAsStream. La funcionalidad de esta caso de uso es conseguir todos los spaces que estén asociados a la cuenta del usuario. Una vez que se tiene la lista tanto de las subidas como de los spaces, se va a crear un objeto Pair por cada par de elementos. Se va comprobando a que space está asociado cada subida y se van asociando entre sí, para luego añadirlo a la lista correspondiente. Esta lista será la que el transfersAdapter utilice para poder mostrar todos los elementos por pantalla y con la información correspondiente. Figura 5.28: Diagrama de secuencia correspondiente a la implementación de la interfaz transferRepository de la Figura 5.27 Siguiendo el flujo de los diagramas anteriores, en la Figura 5.28, se muestra la implementación de la interfaz para este caso de uso. Siguiendo el mismo patrón que el caso de uso de subida de un fichero, dicha clase presenta el prefijo OC. La llamada que se realiza es sobre el LocalTransferDataSource, el cual es un atributo de esa clase. A esa llamada no se pasará ningún parámetro, pues simplemente consiste en obtener todos los elementos de base de datos local. Nuevamente al ser una interfaz, se tiene otro diagrama en el que se muestre dicha implementación. En este caso corresponde con la Figura 5.29. En primer lugar se llama a la clase transferDao para realizar una consulta a la base de datos local y obtener todas las tranfers que haya almacenadas en dicho sistema. Tras ello se crea una nueva lista en la que se irá guardando cada uno de esos elementos para ya transformados en el modelo del sistema (OCTransfer). Tras haber transformado todas las transfersEntities al correspondiente modelo, se procederá a ordenarlas según su tipo. Sobre esa lista que se había creado se ejecuta la función groupBy con el atributo status como argumento de dicha función. Los dos siguientes pasos son crear dos listas en los que se irán guardando todas las subidas ya ordenadas. La primera de esa lista es un ArrayList mientras que la segunda es de tipo MutableList. Una vez que se han creado, se procederá a ordenarlas. En la primera posición del ArrayList se almacenarán aquellas subidas que están en progreso. En la siguiente posición de la lista se guardan aquellas que estén en cola. Seguidas a esas, se encuentran todas las subidas que hayan fallado durante todo el proceso 61
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA de subida. Por último, están almacenadas todas aquellas subidas que han sido satisfactorias y que ya han terminado todo el proceso de subida. Cuando ya se tiene ordenadas sobre esa lista se guardarán una a una en la MutableList que se había creado anteriormente. Figura 5.29: Diagrama de secuencia correspondiente a la implementación de la interfaz localTransferDataSource de la Figura 5.28 Figura 5.30: Diagrama de secuencia correspondiente a la implementación de la función setData de la Figura 5.26 62
CAPÍTULO 5. INGENIERÍA INVERSA DE LA ARQUITECTURA DE OWNCLOUD: VISTA DINÁMICA Ahora viene toda la secuencia relacionada con mostrar toda la información que se ha sacado de la base a datos. En la Figura 5.30 se puede ver como todo esto inicia con la función setData. Tras ello, a través del binding, se setean todos los elementos iniciales que corresponde a la lista vacía. Finalmente se llama al transfersAdapter con todas las subidas asociadas a cada space para que lo pinte por pantalla. Toda esta lógica se encuentra desarrollada en la Figura 5.31. Figura 5.31: Diagrama de secuencia correspondiente a la implementación de la función setData de la Figura 5.30 63
5.1. CLEAN ARCHITECTURE EN OWNCLOUD: VISTA DINÁMICA 64
Parte II Reingeniería: migración a Jetpack Compose 65
CAPÍTULO 6. REDISEÑO DE UN CASO DE USO Capítulo 6 Rediseño de un caso de uso El caso de uso que se ha decidido migrar, y en consecuencia, rediseñar es: consulta del estado de las subidas. Dentro de todo este proceso no se ha contemplado cambiar el aspecto visual de la pantalla por lo que la apariencia de la pantalla es similar a la que ya se tenía antes de todo el proceso. Para ello se han realizado una serie de tareas hasta conseguir el resultado final. El primer paso que se ha llevado a cabo es la lectura de la Guía de migración de XML a Jetpack Compose de Juan Carlos Garrote Gascón [23], en la cual se exponían diferentes formas para llevar a cabo la migración, lo que implica tener que rediseñar el caso de uso en cuestión. Existen dos formas diferentes de poder llevar a cabo esa migración: Migración completa. Se realiza una migración completa de toda la aplicación a la nueva tecnología, manteniendo en todo momento la lógica. Migración por pantallas. Se realiza una migración progresiva por pantallas, manteniendo la lógica de cada una de ellas, teniendo una aplicación híbrida hasta que se complete todo el proceso. Para este caso concreto se ha decidido realizar la migración por pantallas, ya que el caso de uso que se desea rediseñar únicamente aplica a una pantalla en toda la aplicación. Dentro de esta técnica de migración existen otras dos posibles opciones: la pantalla a migrar sea una actividad de Android o sea un fragmento de Android alojado en una actividad. Dependiendo del caso que se tenga, se realizará de una u otra manera. En este caso se realizará la migración de un fragmento ya que la clase antes del rediseño (TransferListFragment) es un fragmento nativo de Android, como su propio nombre indica. 67
6.2. REDISEÑO DE LA VISTA DINÁMICA DEL CASO DE USO Figura 6.7: Diagrama de secuencia correspondiente a la función composable UploadGroup 74
CAPÍTULO 6. REDISEÑO DE UN CASO DE USO Figura 6.8: Diagrama de secuencia correspondiente a la función composable TransferItem 75
6.2. REDISEÑO DE LA VISTA DINÁMICA DEL CASO DE USO Figura 6.9: Diagrama de secuencia correspondiente a la función composable SpacePathLine 76
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO Capítulo 7 Implementación y pruebas del caso de uso rediseñado 7.1. Implementación 7.1.1. Proceso seguido El proceso que se ha seguido para completar la migración ha sido la migración por pantallas, en contraposición a la construcción de la aplicación por completo en Jetpack Compose, tal y como se había mencionado en el Capítulo 6.2. El motivo por el que se ha decidido seguir este método es porque la migración únicamente se va a realizar sobre una pantalla, en este caso la pantalla relacionada con el caso de uso: consulta del estado de las subidas. Además, como se indica en la Guía de migración de XML a Jetpack Compose de Juan Carlos Garrote Gascón [23] existen dos posibles opciones en la migración por pantallas: la pantalla a migrar es una actividad o es un fragmento de Android. Para este caso concreto, se tiene un fragmento de Android y ésta será la única clase en la que se van a realizar los cambios. El primer paso es crear un nuevo fragmento de Android, el cual recibe el nombre de TransferListComposeFragment. Cuando se tenga creado en su respectivo paquete, se deberá crear una instancia de ese fragmento en el lugar que corresponde y eliminar la anterior instancia que estaba definida con vistas XML. La clase encargada de crear ese fragmento es UploadListActivity y el lugar concreto donde se realiza dicha operación es dentro de la función createUploadListFragment. En el Fragmento de código 7.1 se puede ver esta lógica. Además, se puede apreciar cómo la anterior creación del fragmento se encuentra comentada, debido a que se busca realizar una comparación entre lo que se tiene actualmente y lo que se tenía antes de la migración. Por brevedad, los fragmentos de código que se muestran omiten partes no relativas a lo que se va a explicar. 77
7.1. IMPLEMENTACIÓN 1public class UploadListActivity extends FileActivity { 2 3... 4 5private void createUploadListFragment () { 6TransferListComposeFragment uploadList = new TransferListComposeFragment(); 7//TransferListFragment uploadList = new TransferListFragment (); 8... 9} Fragmento de código 7.1: Creación del fragmento de Android en la clase UploadListActivity Tras haber creado la instancia del fragmento, se deberá construir la propia clase a partir de las funciones del ciclo de vida de un fragmento de Android. En este caso sólo será necesario crear la función onCreateView, en la cual se va a definir la interfaz de usuario y su respectivo comportamiento a través de funciones composables. En el Fragmento de código 7.2 se puede ver cómo se realiza una llamada a la función Transfers, la cual es de tipo composable y presenta su propia lógica interna. 1class TransferListComposeFragment : Fragment () { 2 3private val transfersViewModel by viewModel < TransfersViewModel >() 4 5override fun onCreateView ( 6inflater : LayoutInflater , 7container : ViewGroup ?, 8savedInstanceState : Bundle ? 9): View { 10 return ComposeView ( requireContext ()). apply { 11 setContent { 12 ... 13 Transfers () 14 } 15 } 16 } 17 ... 18 } Fragmento de código 7.2: Función onCreateView de la clase TransferListComposeFragment 78
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO Llegado este punto existen dos estrategias posibles para llevar a cabo la migración a través de funciones composables: De abajo hacia arriba (bottom-up): Se comienza migrando los elementos de IU más pequeños, y de forma progresiva se va construyendo la pantalla completa. De arriba hacia abajo (top-down): Se comienza migrando los elementos de IU que contienen a todos los demás, y de forma progresiva se van migrando todos los elementos contenidos. Para este caso se ha escogido la estrategia denominada bottom-up, comenzando con los elementos más pequeños para más tarde juntarlos y con ello tener definida la interfaz en su totalidad. Es por ello que en primer lugar se definirá la función composable SpacePathLine, la cual es la más pequeña de todas las existentes en el fragmento. 1@Composable 2fun SpacePathLine ( space : OCSpace , parentPath : String ) { 3val spaceName : String 4val spaceImage : Int 5 6if ( space . isPersonal ) { 7spaceName = stringResource ( id = R. string . bottom_nav_personal) 8spaceImage = R. drawable . ic_folder 9} else { 10 spaceName = space . name 11 spaceImage = R. drawable . ic_spaces 12 } 13 14 15 Row (...) 16 { 17 Icon( 18 ... 19 painter = painterResource ( id = spaceImage ), 20 ... 21 ) 22 Text( 23 ... 24 text = spaceName 25 ) 26 Text( 27 ... 28 text = parentPath 29 ) 30 } 31 } Fragmento de código 7.3: Función composable SpacePathLine 79
7.1. IMPLEMENTACIÓN En el Fragmento de código 7.3 se encuentra reflejada la estructura y el comportamiento de la función composable SpacePathLine. Esta función recibe dos parámetros diferentes con los que se trabajará a lo largo de toda la lógica implementada. En primer lugar se recibe el space al que se encuentra asociada una subida en concreto (la que se está pintando en la lista en ese momento) junto con la variable parentPath, la cual indica la ruta en la que se guardará cuando el archivo se suba exitosamente. Antes de comenzar con el resto de las funciones composables se realiza una comprobación del space. En caso de que sea el personal space, el nombre que se va a mostrar por pantalla viene determinado por una cadena de texto que está definida en el fichero strings.xml, además de establecer la imagen de una carpeta como icono principal. El hecho de que esa variable se encuentre en el fichero strings.xml es debido a que es una cadena de texto traducible. Por otro lado, si ese space no es el personal entonces el nombre que se mostrará por pantalla será aquel que está asociado a la variable que ha llegado como parámetro (nombre no traducible) de la función composable TransferItem, además de establecer el icono predeterminado de los spaces. Una vez que se han hecho estas comprobaciones se comenzará con la estructuración de toda la interfaz. En primer lugar se introduce una función composable Row, la cual servirá para agrupar todos los elementos en forma de fila. Esta función tiene varios parámetros relacionados con la posición de los elementos en el interior, haciendo que se complete el ancho de la pantalla y se centren verticalmente. Dentro de esa función se tiene una función composable Icon. Esta función tiene una serie de parámetros que determinarán el aspecto del icono como, por ejemplo, el color, la descripción o incluso la imagen que se ha escogido previamente. Tras esa función se tiene dos composables de tipo Text con una estructura bastante similar entre sí. Se determina el color del texto, overflow (omitir partes de texto en caso de que sea demasiado grande y no se pueda ver correctamente en el espacio disponible), número de líneas, tamaño de la fuente y el texto. Este último parámetro viene determinado por las dos variables spaceName yparentPath. El resultado de esta función se encuentra reflejado en la Figura 7.1, donde se puede ver claramente el icono, el nombre del space y la ruta en la que se encuentra un determinado archivo. Figura 7.1: Elemento de IU asociado a la función composable SpacePathLine El siguiente paso que hay que realizar es crear cada uno de los elementos que conformarán la lista de todas las subidas. La función composable encargada de mostrar por pantalla este elemento de IU recibe el nombre de TransferItem. La explicación de esta función composable seguirá el orden que se encuentra reflejado en el Fragmento de código 7.4. 1@Composable 2fun TransferItem ( transfer : OCTransfer , space : OCSpace ?, workInfo : List < WorkInfo >) { 3val remoteFile = File( transfer . remotePath ) 4var fileName = remoteFile . name 5if ( fileName . isEmpty () ) { 6fileName = File . separator 7} 8 80
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO 9var path = "" 10 remoteFile . parent ?. let { 11 path = if ( it . endsWith ("${ OCFile . PATH_SEPARATOR }") ) { 12 it 13 } else { 14 " $it$ { OCFile . PATH_SEPARATOR }" 15 } 16 } 17 18 Row (...) 19 { 20 Box (...) 21 { 22 Image (...) 23 } 24 Column (...) 25 { 26 Text( 27 ... 28 text = fileName 29 ) 30 Row { 31 Text (...) 32 if ( transfer . status != TransferStatus . TRANSFER_FAILED ) { 33 ... 34 Text (...) 35 } 36 } 37 if ( transfer . status != TransferStatus . TRANSFER_SUCCEEDED ) { 38 Text (...) 39 } 40 } 41 42 if ( transfer . status == TransferStatus . TRANSFER_IN_PROGRESS) { 43 LinearProgressIndicator( 44 ... 45 progress = checkProgress (transfer , workInfo) / 100 f 46 ) 47 } 48 49 Text( 50 ... 51 text = checkAccount ( transfer ) 52 ) 53 if ( space != null ) { 54 SpacePathLine (space = space , parentPath = path) 55 } 81
7.1. IMPLEMENTACIÓN 56 } 57 Box (...) 58 { 59 if ( transfer . status != TransferStatus . TRANSFER_SUCCEEDED ) { 60 ... 61 IconButton ( onClick = { transfersViewModel . cancelUpload ( transfer ) }) { 62 Icon (...) 63 } 64 } 65 } 66 } 67 Divider (...) 68 } Fragmento de código 7.4: Función composable TransferItem A esta función TransferItem llegan, como parámetros, el objeto OCTransfer, que será necesario para obtener toda la información y pintarla por pantalla, el objeto de tipo OCSpace, que muestra el space en el que se encuentra ubicado el archivo, y, por último, la variable workInfo, en la cual viene toda la información asociada al progreso de subida de todos los archivos. Comenzando con la implementación de la función, en primer lugar se crea un objeto de tipo File a partir del atributo remotePath de la variable transfer. Tras ello, se obtiene el nombre del archivo que se ha subido, guardándolo en una variable con el nombre fileName. Si ese nombre está vacío, se pondrá la ruta del directorio raíz (/). El siguiente paso es determinar la ruta en la que se encuentra ese archivo para más tarde enviárselo a la función composable SpacePathLine. El valor de la variable path viene determinado por el atributo parent del objeto remoteFile. Dependiendo de su valor, se construirá la cadena, de una u otra forma, con el fin de mostrarlo correctamente en todo momento. Una vez que se ha determinado el valor de esas dos variables, fileName ypath, se procederá a la creación de la interfaz de usuario con el resto de funciones composables. En primer lugar, se tiene una función Row encargada de distribuir al resto de elementos en forma de fila. Una de las características que tiene esta función, respecto al resto que aparecen en todo el fragment, es que en caso de que el estado de la subida sea failed, se activa la opción clickable. Esto permite al usuario interactuar con todo el elemento, independientemente de donde toque, pudiendo reanudar la subida del archivo. De forma anidada, se encuentra otra función de tipo Box, la cual será la encargada de centrar la miniatura del archivo. Esta miniatura se consigue reproducir por pantalla a través de la función composable Image, la cual tiene una serie de atributos que definirán su apariencia. Saliendo del alcance de la función Box, se encuentra una función Column organizando los elementos de interfaz de usuario que tenga anidados en forma de columna. Como se puede apreciar, todos los elementos del composable se distribuyen tanto en columna como en fila según se vaya requiriendo. Lo siguiente que hay que mostrar en la pantalla es el nombre del archivo, almacenado en la variable fileName ya comentada anteriormente. El resto de información que hay que mostrar está relacionada con el tamaño del archivo, el tiempo que ha transcurrido desde que se ha subido hasta la actualidad, la cuenta a la que se 82
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO encuentra asociada y el space al que se encuentra asociado. Esto último se corresponde con la función composable SpacePathLine, además de depender de la versión que esté utilizando el usuario (oCIS /oC10). Además, en caso de que la subida del fichero se encuentre en progreso se mostrará una línea de progreso, permitiendo al usuario conocer el estado actual de la misma y cuánto falta aproximadamente para que el fichero se termine de transferir. Este progreso viene determinado por la información almacenada dentro de la variable workInfo. Para conseguir este proceso se ha creado una función auxiliar denominada checkProgress. Junto a ese indicador se muestra un icono de cancelación, permitiendo al usuario interrumpir el proceso en cualquier momento. Esta funcionalidad sólo está disponible para aquellas subidas que no se hayan guardado de forma satisfactoria en el servidor. Por otro lado, para conseguir la información de la cuenta a la que se encuentra asociada esa subida, se ha creado una función auxiliar denominada checkAccount. Para concluir con la función TransferItem, se tiene una función composable Divider encargada de mostrar por pantalla un separador entre los diferentes elementos. La apariencia de este divisor viene determinado por todos los parámetros de la función, como por ejemplo el color, el grosor o la longitud del mismo. El resultado de la función composable TransferItem en su totalidad y en los diferentes estados que existen, se puede ver reflejado en la Figura 7.2, Figura 7.3, Figura 7.4, y Figura 7.5. Figura 7.2: Resultado de la función composable TransferItem en el estado Succeded Figura 7.3: Resultado de la función composable TransferItem en el estado Failed Figura 7.4: Resultado de la función composable TransferItem en el estado Enqueued 83
7.1. IMPLEMENTACIÓN Figura 7.12: Resultado de la función composable EmptyList 90
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO 7.1.2. Resultado El resultado que se ha obtenido es la pantalla “Transfers” de la aplicación Android de ownCloud, la cual ha sido migrada de un paradigma imperativo con la interfaz de usuario definida en XML y código Kotlin a un paradigma declarativo utilizando exclusivamente código Kotlin y el kit de herramientas de IU de Jetpack Compose. En la Figura 7.13 y Figura 7.14 se puede ver una comparativa entre la pantalla original y la pantalla resultante para un mismo estado. En esa comparación se puede apreciar como ambas pantallas son relativamente idénticas, diferenciándose por alguna característica de tamaño, espacio o distribución de algún elemento. Con ello se puede concluir que se puede realizar una migración a Jetpack Compose sobre una pantalla sin influir en su aspecto. Figura 7.13: Pantalla de las subidas definida en XML Figura 7.14: Pantalla de las subidas definida en Jetpack Compose 91
7.2. PRUEBAS 7.2. Pruebas Tras terminar con la implementación, el código de la pantalla asociada al caso de uso en cuestión ha sido sometido a dos rondas de revisión a manos de un ingeniero experto en Android y en la aplicación de ownCloud, sugiriendo algún cambio. Tras terminar con esa revisión, se han llevado a cabo una serie de pruebas para comprobar que todo funcionaba a la perfección. Toda esta serie de pruebas recibe el nombre de plan de pruebas, el cual ha sido creado por un ingeniero QA (Quality Assurance) perteneciente al equipo Android de ownCloud de Izertis. Algo a destacar, es que a pesar de que el trabajo principal se ha centrado en la migración de la interfaz de usuario, se ha separado todo el plan de pruebas en varias partes. En primer lugar se ha probado cómo se veía la interfaz por cada estado disponible (In progress, failed, succeeded y enqueued). Tras ello se ha comprobado si el flujo era correcto para un sólo archivo. Finalmente se han hecho pruebas con varios ficheros de forma simultánea con estados diferentes. En todas las pruebas que se han hecho relativas al estado failed solamente se ha considera el error Connection error. A pesar de que hay más errores que pueden reproducirse, e influir en el estado de la subida, el cambio en la interfaz de usuario es el mismo y, por tanto, no surgirían nuevos problemas respecto a las pruebas. En las Tablas 7.1, 7.2, 7.3, 7.4, 7.5, 7.6 y 7.7 se pueden apreciar todas las pruebas que se han llevado a cabo separados por estados y flujos. Título Pasos a seguir Resultado esperado Resultado Comentarios Lista vacía 1. Instalar la aplicación y añadir una cuenta 2. Abrir la sección de Uploads dando click en el icono de la flecha vertical situada en la barra inferior No uploads available Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Tabla 7.1: Plan de pruebas referente a la lista vacía 92
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 1 archivo en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Uploaded y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha sido subido -Personal como space - / como carpeta El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Uploaded y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido -Personal como space - / como carpeta El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica del Personal Space 1. Abrir el botón flotante dentro de una carpeta del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Uploaded y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha subido -Personal como space - Carpeta destino de la subida El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en una ruta específica del Personal Space 1. Abrir el botón flotante dentro de una carpeta del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Uploaded y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido -Personal como space - Carpeta destino de la subida El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Uploaded y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha subido - Nombre del space compartido - / como carpeta El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Uploaded y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido - Nombre del space compartido - / como carpeta El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Uploaded y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha subido - Nombre del space compartido - Carpeta destino de la subida El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Uploaded y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido - Nombre del space compartido - Carpeta destino de la subida El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Borrar lista 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el botón Clear 3. Sección con el nombre Uploaded y5 Files 4. Lista y sección Uploaded eliminadas Correcto Tabla 7.2: Plan de pruebas referente al estado de subida: Succeeded 93
7.2. PRUEBAS Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 1 archivo en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Enqueued y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha sido subido -Personal como space - / como carpeta - Botón Xvisible El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Enqueued y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido -Personal como space - / como carpeta - Botón Xvisible para cada archivo El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica del Personal Space 1. Abrir el botón flotante dentro de una carpeta del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Enqueued y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha subido -Personal como space - Carpeta destino de la subida - Botón Xvisible El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en una ruta específica del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Enqueued y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido -Personal como space - Carpeta destino de la subida - Botón Xvisible para cada archivo El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Enqueued y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha subido - Nombre del space compartido - / como carpeta - Botón Xvisible El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Enqueued y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido - Nombre del space compartido - / como carpeta - Botón Xvisible para cada archivo El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Enqueued y1 File El archivo que se ha subido debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se ha subido - Nombre del space compartido - Carpeta destino de la subida - Botón Xvisible El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) (Continúa en la siguiente página) 94
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO (Empieza en la página anterior) Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 10 archivos en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Enqueued y10 Files Todos los archivos que se han subido deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y fecha de la subida - Cuenta en la que se han subido - Nombre del space compartido - Carpeta destino de la subida - Botón Xpara cada archivo El botón Clear debe estar visible Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Eliminar algunos archivos que están en cola 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el botón Xde dos archivos 5. Recuperar la conexión del dispositivo 3. Sección con el nombre Enqueued y5 Files 4. 3 archivos restantes en la sección Enqueued 5. Los archivos restante pasan a la sección Current y tras ello a la sección Uploaded Correcto Eliminar todos los archivos que están en cola 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el botón Xde todos los archivos 3. Sección con el nombre Enqueued y5 Files 4. La sección Enqueued desaparece por completo Correcto Tabla 7.3: Plan de pruebas referente al estado de subida: Enqueued 95
7.2. PRUEBAS Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 1 archivo grande en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Current y1 File mientras el archivo se está subiendo. El archivo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo -Personal como space - / como carpeta - Botón Xvisible - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Current y10 Files. El número va decrementando a medida que los archivos se van subiendo correctamente. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo -Personal como space - / como carpeta - Botón Xvisible para cada archivo - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica del Personal Space 1. Abrir el botón flotante dentro de una carpeta del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Current y1 File mientras el archivo se está subiendo. El archivo que se está subiendo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo -Personal como space - Carpeta destino de la subida - Botón Xvisible - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en una ruta específica del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Current y10 Files. El número va decrementado a medida que los archivos se van subiendo correctamente. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo -Personal como space - Carpeta destino de la subida - Botón Xvisible para cada archivo - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Current y1 File mientras el archivo se está subiendo. El archivo que se está subiendo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo - Nombre del space compartido - / como carpeta - Botón Xvisible - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) (Continúa en la siguiente página) 96
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO (Empieza en la página anterior) Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 10 archivos en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Current y10 Files. El número va decrementando a medida que los archivos se van subiendo correctamente Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo - Nombre del space compartido - / como carpeta - Botón Xvisible para cada archivo - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Current y1 File mientras el archivo se está subiendo. El archivo que se está subiendo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se está subiendo - Nombre del space compartido - Carpeta destino de la subida - Botón Xvisible - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 ficheros en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Current y10 Files. El número va decrementando a medida que los archivos se van subiendo correctamente. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Uploading... - Cuenta en la que se han subido - Nombre del space compartido - Carpeta destino de la subida - Botón Xpara cada archivo - Barra de progreso Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Eliminar algunos archivos en progreso 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el botón Xde dos archivos antes de que finalicen 3. Sección con el nombre Current y5 Files 4. 3 archivos restantes en la sección Current. Cuando terminan pasan a la sección Uploaded y la sección Current desaparece. Correcto Eliminar todos los archivos que están en progreso 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el botón Xde todos los archivos 3. Sección con el nombre Current y5 Files 4. La sección Current desaparece por completo Correcto Tabla 7.4: Plan de pruebas referente al estado de subida: In progress 97
7.2. PRUEBAS Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 1 archivo en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Failed y1 File. El archivo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo -Personal como space - / como carpeta - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Failed y10 Files. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo -Personal como space - / como carpeta - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica del Personal Space 1. Abrir el botón flotante dentro de una carpeta del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Failed y1 File. El archivo que se está subiendo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo -Personal como space - Carpeta destino de la subida - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) (Continúa en la siguiente página) 98
CAPÍTULO 7. IMPLEMENTACIÓN Y PRUEBAS DEL CASO DE USO REDISEÑADO (Empieza en la página anterior) Título Pasos a seguir Resultado esperado Resultado Comentarios Subir 10 archivos en una ruta específica del Personal Space 1. Abrir el botón flotante dentro del root del Personal Space 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Failed y10 Files. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo -Personal como space - Carpeta destino de la subida - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Failed y1 File El archivo que se está subiendo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo - Nombre del space compartido - / como carpeta - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 archivos en el root de un space compartido 1. Abrir el botón flotante dentro del root del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Failed y10 Files. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo - Nombre del space compartido - / como carpeta - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 1 archivo en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar cualquier fichero del sistema Sección con el nombre Failed y1 File. El archivo que se está subiendo debe cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se está subiendo - Nombre del space compartido - Carpeta destino de la subida - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Subir 10 ficheros en una ruta específica de un space compartido 1. Abrir el botón flotante dentro de una carpeta del space compartido 2. Hacer click en Upload y seleccionar Files 3. Seleccionar 10 ficheros del sistema Sección con el nombre Failed y10 Files. Todos los archivos que se están subiendo deben cumplir las siguientes características: -Thumbnail o icono del tipo de fichero - Nombre del fichero - Tamaño y Connection error - Cuenta en la que se han subido - Nombre del space compartido - Carpeta destino de la subida - Icono de la papelera visible Los botones Clear yRetry deben estar visibles Correcto Comprobado en las dos orientaciones posibles (vertical y horizontal) Eliminar algunos archivos fallido. Recuperar el proceso con el botón Retry 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el icono de la papelera en 2 archivos fallidos 5. Levantar el servidor 6. Hacer click en el botón Retry 3. Sección con el nombre Failed y5 Files 4. 3 archivos restantes en la sección Failed. 6. 3 archivos en la sección Current. La sección Failed desaparece Correcto Eliminar algunos archivos fallido. Recuperar el proceso dando click al elemento. 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el icono de la papelera en 2 archivos fallidos 5. Levantar el servidor 6. Hacer click sobre cada uno de los elementos fallidos 3. Sección con el nombre Failed y5 Files 4. 3 archivos restantes en la sección Failed. 6. 3 archivos en la sección Current. La sección Failed desaparece Correcto Eliminar todos los archivos fallidos. 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el icono de la papelera en todos los archivos fallidos 3. Sección con el nombre Failed y5 Files 4. La sección Failed desparece Correcto Limpiar la lista 1. En cualquier carpeta, abrir el botón flotante 2. Dar click en Upload y seleccionar Files 3. Seleccionar 5 archivos del sistema 4. Hacer click en el botón Clear 3. Sección con el nombre Failed y5 Files 4. Se vacía la lista de los elementos y la sección Failed desaparece Tabla 7.5: Plan de pruebas referente al estado de subida: Failed 99
8.1. LÍNEAS DE TRABAJO FUTURAS 106
BIBLIOGRAFÍA Bibliografía [1] Android. Android. https://www.android.com/intl/es_es/. Accessed: 2024-05-01. [2] Android Developers. Jetpack Compose UI App Development Toolkit - Android Developers. https://developer.android.com/jetpack/compose. Accessed: 2024-03-06. [3] Apple. MacBook Pro 2023 (M3). https://www.apple.com/es/shop/buy-mac/macbo ok-pro/14-pulgadas-gris-espacial-chip-m3-de-apple-con-cpu-de-8-n%C3%BA cleos-y-gpu-de-10-n%C3%BAcleos-8gb-de-memoria-1tb. Accessed: 2024-03-09. [4] Astah. Pricing Individual. https://astah.net/pricing/individual/. Accessed: 2024-03-09. [5] Astah. Sofware Design Tool. Astah Professional. https://astah.net/products/ast ah-professional/. Accessed: 2024-04-13. [6] Atlassian. Desarrollo de software. Comandos Git. https://www.atlassian.com/es/g it/glossary#commands. Accessed: 2024-04-14. [7] Campus Training. Alba Naveira. Sueldo de un desarrollador Android: todo lo que necesitas saber. https://www.campustraining.es/cursos-de-informatica/programac ion-android/sueldo/. Accessed: 2024-03-09. [8] Deloitte. Artefactos scrum: las 3 herramientas claves de gestión. https://www2.deloi tte.com/es/es/pages/technology/articles/artefactos-scrum.html. Accessed: 2024-03-02. [9] Deloitte. Scrum: roles y responsabilidades. https://www2.deloitte.com/es/es/pa ges/technology/articles/roles-y-responsabilidades-scrum.html. Accessed: 2024-03-03. [10] Developers. Android Studio. https://developer.android.com/studio. Accessed: 2024-04-104. [11] Espai. Como trabajar con Ramas en Git y Github. https://www.espai.es/blog/20 21/05/como-trabajar-con-ramas-en-git-y-github/. Accessed: 2024-04-13. [12] Git. Fast version control. https://git-scm.com/. Accessed: 2024-04-14. [13] GitHub. Let’s build from here. https://github.com/. Accessed: 2024-04-13. 107
BIBLIOGRAFÍA [14] Glassdoor. Sueldos para el puesto de Desarrollador Android en España. https://www. glassdoor.es/Sueldos/desarrollador-android-sueldos-SRCH_KO0,21.htm#:~: text=En%20Espa%C3%B1a%2C%20el%20sueldo%20medio,que%20trabajan%20de%20Des arrollador%20android. Accessed: 2024-03-09. [15] Google. Google Meet. https://meet.google.com/. Accessed: 2024-04-12. [16] Google. Material Design. https://m3.material.io/. Accessed: 2024-07-02. [17] Gradle. Gradle Build Tool. https://gradle.org/. Accessed: 2024-04-104. [18] IBM. ¿Qué es el software de código abierto? https://www.ibm.com/es-es/topics/o pen-source. Accessed: 2024-02-28. [19] Ingenieros Asesores. Ingeniería Inversa. Conceptos y aplicaciones. https://ingeni erosasesores.com/actualidad/ingenieria-inversa-concepto-aplicaciones/. Accessed: 2024-03-02. [20] Ionos. La ingeniería inversa del software. https://www.ionos.es/digitalguide/ paginas-web/desarrollo-web/ingenieria-inversa-de-software/. Accessed: 2024-03-02. [21] Izertis. Facilitamos la transformación digital. https://www.izertis.com/es/. Accessed: 2024-03-06. [22] Juan Carlos Garrote Gascón. AppGenda: app Android como agenda virtual de las PYMEs de servicios de un ayuntamiento. https://uvadoc.uva.es/handle/10324/5 0084. Accessed: 2024-02-21. [23] Juan Carlos Garrote Gascón. Elaboración de una guía de migración de XML a Jetpack Compose en aplicaciones Android: un caso de estudio de modernización de software. https://uvadoc.uva.es/handle/10324/57389. Accessed: 2024-05-01. [24] Ken Schwaber y Jeff Sutherland. La guía definitiva de Scrum: Las reglas del juego. http s://scrumguides.org/docs/scrumguide/v2016/2016-Scrum-Guide-Spanish.pdf. Accessed: 2024-03-06. [25] Kent Beck, Mike Beedle, Arie van Bennekum y otros 14 autores más. Manifiesto por el desarrollo ágil de Software. https://agilemanifesto.org/iso/es/manifesto.html. Accessed: 2024-03-02. [26] Kotlin. Kotlin Programming. https://kotlinlang.org/. Accessed: 2024-07-01. [27] Leburo. Precio de coworking en Valladolid. https://leburocowork.es/precio-cow orking-valladolid. Accessed: 2024-03-09. [28] María Robles del Blanco. Evolución y mejora en la traducción de código Vensim a código Python: ingeniería inversa y mantenimiento de PySD. https://uvadoc.uva.e s/handle/10324/50438. Accessed: 2024-02-21. [29] Medium | Lucas Maurer. Git Gud: The Working Tree, Staging Area, and Local Repo. https://medium.com/@lucasmaurer/git-gud-the-working-tree-staging-area-a nd-local-repo-a1f0f4822018. Accessed: 2024-04-14. 108
BIBLIOGRAFÍA [30] Medium (Juvinaojesus). Los principios SOLID. https://medium.com/@juvinaojesus d/los-principios-solid-256f106b311a. Accessed: 2024-03-11. [31] Microsoft Teams. Microsoft Teams. https://www.microsoft.com/es-es/microsof t-teams/group-chat-software. Accessed: 2024-06-25. [32] OnePlus. OnePlus Nord 3 (5G). https://www.oneplus.com/es/oneplus-nord-3-5g. Accessed: 2024-03-09. [33] Open Source. Open Source Initative. https://opensource.org/. Accessed: 2024-02-26. [34] Open Source Guides. Cómo contribuir con el código abierto. https://opensource.g uide/es/how-to-contribute/. Accessed: 2024-02-26. [35] Overleaf. Overleaf, a LaTeX editor. https://www.overleaf.com/. Accessed: 2024-04- 12. [36] ownCloud. A Kiteworks Company. https://owncloud.com/. Accessed: 2024-03-02. [37] ownCloud. Feature. Spaces. https://owncloud.com/features/spaces/. Accessed: 2024-03-18. [38] ownCloud. Introduction to Infinity Scale. https://doc.owncloud.com/ocis/next/. Accessed: 2024-03-18. [39] Paradigma Digital. Estados y recomposición en Jetpack Compose. https://www.pa radigmadigital.com/dev/estados-recomposicion-jetpack-compose/. Accessed: 2024-06-28. [40] PC Componentes. MSI Alpha 15 A3DDK-001XES. https://www.pccomponentes.co m/msi-alpha-15-a3ddk-001xes-amd-ryzen-7-3750h-16gb-512gb-ssd-rx-5500m-1 56. Accessed: 2024-03-09. [41] Per-Erik Bergman. Medium. Repository Pattern. https://medium.com/@pererikber gman/repository-design-pattern-e28c0f3e4a30. Accessed: 2024-07-01. [42] Profile. SOLID: Los 5 principios que te ayudarán a desarrollar software de calidad. https://profile.es/blog/principios-solid-desarrollo-software-calidad/. Accessed: 2024-03-09. [43] Redhat. ¿Qué es open-source? https://www.redhat.com/es/topics/open-sourc e/what-is-open-source#:~:text=Originalmente%2C%20la%20expresi%C3%B3n% 20open%20source,la%20forma%20que%20consideren%20conveniente. Accessed: 2024-02-26. [44] Repsol. Tipos de ordenadores y su gasto mensual. https://www.repsol.es/partic ulares/asesoramiento-consumo/cuanto-consume-ordenador/#:~:text=Por%20lo% 20general%2C%20un%20ordenador,cuenta%20el%20tiempo%20de%20uso. Accessed: 2024-03-09. [45] Richard Albán Fernández. Tutorías InfUVa: una web y bot de Telegram para facilitar la gestión de tutorías para alumnos y profesores de la Escuela de Ingeniería Informática. https://uvadoc.uva.es/handle/10324/57206. Accessed: 2024-02-21. 109
BIBLIOGRAFÍA [46] Robert Martin. Clean Architecture Craftsmans Software Structure. https://www.am azon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164. Accessed: 2024-07-01. [47] Rocket.chat. Rocket Chat. https://es.rocket.chat/. Accessed: 2024-04-12. [48] Scrum.org. What is Scrum? https://www.scrum.org/learning-series/what-is-s crum/the-scrum-events. Accessed: 2024-03-03. [49] Simpl¡learn. What is Gradle? Why do we use gradle? Explained. https://www.simpli learn.com/tutorials/gradle-tutorial/what-is-gradle#:~:text=Gradle%20is%2 0a%20build%20automation,help%20of%20build%20automation%20tools. Accessed: 2024-04-104. [50] UEMC (Ángela de Toro). ¿Qué es scrum? Conoce el framework que aguluza el trabajo en equipo. https://www.escueladenegociosydireccion.com/revista/business/s crum-framework-agiliza-trabajo-equipo/. Accessed: 2024-03-11. [51] Universidad de Valladolid. Guía docente. Trabajo de Fin de Grado. https://apps.sti c.uva.es/guias_docentes/uploads/2023/545/46976/1/Documento.pdf. Accessed: 2024-03-08. [52] Universitat Oberta de Catalunya. Ingeniería Inversa. Qué es, herramientas y técnicas. https://blogs.uoc.edu/informatica/ingenieria-inversa-que-es-herramienta s-y-tecnicas/#:~:text=La%20ingenier%C3%ADa%20inversa%20es%20el,fue%20el %20proceso%20de%20fabricaci%C3%B3n. Accessed: 2024-03-02. [53] Vysor. Vysor, a window to your Phone. https://www.vysor.io/. Accessed: 2024-04-12. [54] webEmpresa. ¿Qué es ownCloud y para qué sirve? https://www.webempresa.com/b log/que-es-owncloud-y-para-que-sirve.html. Accessed: 2024-03-02. [55] Wikipedia. Extensible Markup Language (XML). https://es.wikipedia.org/wiki/ Extensible_Markup_Language. Accessed: 2024-07-01. 110
BIBLIOGRAFÍA Anexos 111
APÉNDICE A. PLANIFICACIÓN DEL PROYECTO Apéndice A Planificación del proyecto A.1. Scrum El desarrollo del proyecto se llevará a cabo mediante el marco de trabajo Scrum [24]. Es un marco de trabajo a partir del cual las personas pueden abordar problemas complejos creando de forma simultánea productos de calidad. Este marco de trabajo se lleva utilizando desde la década de los 90 aproximadamente. De forma resumida, Scrum consiste en una serie de iteraciones en la que cada uno de los integrantes del equipo, los cuales algunos presentan roles diferentes, se coordinan y cooperan entre sí para generar un incremento de producto en el periodo de tiempo que se ha establecido. Hay que mencionar también que el marco de trabajo Scrum se encuentra dentro de la metodología ágil, la cual se caracteriza por los siguientes cuatro valores según el Manifiesto Ágil [25]: Individuos e interacciones sobre procesos y herramientas Software funcionando sobre documentación extensiva Colaboración con el cliente sobre negociación contractual Respuesta ante el cambio sobre seguir un plan Dentro de Scrum se definen artefactos, eventos y roles tal y como se puede ver en la Figura A.1. 113
A.1. SCRUM Figura A.1: Artefactos, Roles y Eventos de Scrum [50] A.1.1. Artefactos En el marco de trabajo Scrum se define como artefacto a aquellos resultados que surgen a partir del trabajo realizado durante un cierto período de tiempo previamente establecido. Al mismo tiempo estos artefactos proporcionan transparencia y registro de la aplicación Scrum. Existen tres artefactos principales [8] dentro de este marco de trabajo, los cuales son: Product Backlog: Consiste en una lista ordenada que contiene cualquier tipo de trabajo que haya que realizar en el producto. Es la principal fuente de información del mismo. El responsable de este artefacto es exclusivamente el Product Owner. Sprint Backlog: Consiste en una lista de elementos pertenecientes al Product Backlog que se deben de llevar a cabo durante un sprint. Incremento del producto: Se trata del resultado de un sprint. Consiste en la suma de todas las tareas, casos de uso, historias de usuario u otro tipo de trabajo que se haya realizado durante el sprint. A.1.2. Roles Un equipo de trabajo Scrum está conformado por diferentes roles. Cada uno de ellos posee unas responsabilidades y debe de trabajar de una forma en particular. Los tres roles existentes [9] dentro de este marco de trabajo son los siguientes: 114
APÉNDICE A. PLANIFICACIÓN DEL PROYECTO Product Owner: Encargado de optimizar y maximizar el producto. Es el rol encargado de gestionar el valor del producto a través del Product Backlog. De forma tradicional este rol se ha asemejado al de un cliente, siendo la persona que establece qué se debe hacer hacer o cuál es la funcionalidad que se requiere conseguir. Scrum Master: Tiene dos funciones dentro del marco de trabajo. La primera de ellas es gestionar el proceso Scrum. Es el rol encargado de asegurar que se están llevando a cabo todas las etapas de manera correcta. Otra de las funciones que posee el Scrum Master es de eliminar cualquier tipo de impedimento que surja durante el desarrollo del proyecto. Equipo de desarrollo: Este equipo suele estar formando entre 3 y 9 profesionales. Son los encargados de, como su propio nombre indica, desarrollar el proyecto en el que están involucrados. El equipo de desarrollo se coordinará de forma que puedan conseguir el incremento del producto en el tiempo establecido. A.1.3. Eventos Dentro del marco de trabajo Scrum existen diversos eventos en los cuales el producto se va desarrollando de forma progresiva. Algunos de estos eventos son simplemente un análisis de cómo va todo mientras que otros eventos se centran solamente en el desarrollo de la aplicación. Los eventos [48] con más detalle son los siguientes: Sprint: Es el evento representativo de este marco de trabajo. Un sprint tiene una duración fija entre 1 semana y 4 semanas, en el cual el equipo de desarrollo realiza su trabajo a partir de unos objetivos que se han fijado previamente. Durante el sprint los requisitos no se pueden cambiar, sin embargo es posible hacer retrospectiva del mismo y tratar puntos que no se habían cubierto en los sprints siguientes. Sprint Planning: Reunión de todo el equipo Scrum en el que se debate acerca de qué ítems del Product Backlog se tienen que desarrollar durante el sprint que dará comienzo tras este evento. La duración de este evento no debería durar más de 2 horas por cada semana de sprint. Daily Scrum: Evento diario en el cual se reúne el equipo de desarrollo durante aproximadamente 15 minutos. Cada integrante del equipo expone al resto en lo que ha trabajo el día anterior y si ha tenido cualquier tipo de dificultad que le haya impedido terminar con el trabajo asignado. Sprint Review: Evento que tiene lugar al final de cada sprint en el que se reúne todo el equipo Scrum junto con el cliente para determinar qué objetivos se han completado durante el sprint. Sprint Retrospective: Con este evento se finaliza el sprint. El equipo de desarrollo se reúne y debate acerca de qué aspectos se pueden mejorar para el siguiente sprint o si ha habido algún problema entre el equipo que haya influido a la hora de conseguir el trabajo establecido previamente. 115
A.5. PRESUPUESTO Concepto Precio Cantidad Total Coste del empleado 14,2e/hora 300 horas 4.260e Equipo de trabajo (MacBook Pro 2023) 47,06e/mes 5 meses 235,3e Dispositivo móvil (One Plus Nord 3) 9,35e/mes 5 meses 46,75e Licencia Astah Professional 9,99e/mes 5 meses 49,95e Espacio de trabajo (Co-Working) 85e/mes 5 meses 425e TOTAL 5017e Tabla A.10: Presupuesto simulado. A.5.2. Presupuesto real A diferencia del presupuesto estimado, ciertos elementos no se aplican al presupuesto real como por ejemplo el coste del empleado. Como el equipo de desarrollo en este caso es el propio estudiante, el coste del mismo es de 0e. Sucede lo mismo con el co-working. El estudiante llevará a cabo el desarrollo del proyecto desde su casa por lo que no existirá ningún gasto de alquiler respecto a la zona de trabajo. Sin embargo, referente a este concepto, hay que aplicar un gasto que no se había mencionado anteriormente. Es el caso de la luz. Con el presupuesto real se tenía incluido el gasto de luz dentro de la tarifa de la oficina de co-working pero en este caso habrá que tener en cuenta la tarifa de luz y el consumo de los dispositivos para calcular la cifra total. Aproximadamente el consumo de un ordenador portátil es de 16kWh mensuales [44], lo cual sería un consumo por hora de 0,022kWh (aplicando que un mes tiene 30 días). Si se tiene en cuenta que se emplearán 300 horas de trabajo aproximadamente, el consumo total del dispositivo es de 6,6kWh. Con una tarifa de 0,130435 e/kWh el gasto total es de 0,86e. Por otra parte, el equipo utilizado por el estudiando es un MSI Alpha 15 [40]. Su precio es de 1099,84e. Teniendo en cuenta que la vida útil del dispositivo es de 4 años (48 meses), el precio del mismo saldría a 22,91e/mes. Para cubrir los 5 meses de desarrollo del TFG se tiene que el coste total del equipo de trabajo es de 114,55e. Respecto al smartphone que se va a utilizar para realizar las pruebas correspondientes, se cuenta con un Motorola Moto G14. Su precio es de 124eactualmente por lo que, contando con los 4 años de vida útil que tiene el dispositivo su precio saldría a 2,58e/mes. Al igual que en los anteriores casos hay que multiplicar esa cantidad por el número total de meses de desarrollo (5 meses). El precio total ascendería a 12,92e. Finalmente, no se aplicará ningún coste relacionado a las licencias de todos los programas que se utilizaran para el desarrollo ya que la universidad las proporciona de forma gratuita. 122
APÉNDICE A. PLANIFICACIÓN DEL PROYECTO Concepto Precio Cantidad Total Equipo de trabajo (MSI Alpha 15) 22,91e/mes 5 meses 114,55e Dispositivo móvil (Motorola Moto G14) 2,58e/mes 5 meses 12,92e Coste de la luz 0,1304e/kWh 6,6kWh 0,86e TOTAL 128,33e Tabla A.11: Presupuesto real. A.6. Product Backlog Inicial Tal y como se ha mencionado en el Apartado A.1.2, el rol del Product Owner será desempeñado por Juan Carlos. Este tendrá la responsabilidad de definir el product backlog inicial. Como se está utilizando un marco de trabajo Scrum, cada una de las épicas se definen como historias de usuario. La estructura de una historia de usuario es la siguiente: "Como <stateholder> quiero <objetivo> para <razón para conseguir ese objetivo>". Siguiendo este modelo a continuación se muestra el product backlog inicial. Número Épica EP01 Como equipo de desarrollo quiero ser capaz de migrar una interfaz de la aplicación la cual está definida en XML al framework que se utiliza hoy en día en Android: Jetpack Compose. EP02 Como equipo de desarrollo quiero poder documentar y actualizar la arquitectura de la aplicación a través de un proceso de ingeniería inversa. Tabla A.12: Product Backlog inicial A.7. Product Backlog Final Desde el inicio del proyecto hasta su finalización, el Product Backlog ha sufrido diferentes cambios, pues se han ido modificando algunas historias de usuario, se han añadido otras y también se han eliminado aquellas que no resultaban interesantes o por ciertos motivos debían agruparse con otras. En la Tabla A.13 se muestran todas aquellas historias de usuario relacionadas con la épica EP02: Ingeniería Inversa mientras que en la Tabla A.14 se muestran todas las historias de usuario relacionadas con la EP01: Migración de XML a Jetpack Compose. 123
A.7. PRODUCT BACKLOG FINAL Código Historia de usuario Puntos HU01 Como desarrollador quiero documentarme sobre la arquitectura, funcionalidad, metodología y otros aspectos importantes de ownCloud 2 HU02 Como desarrollador quiero elaborar un diagrama inicial en el que se muestre la arquitectura principal de ownCloud 1 HU03 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para un caso de uso generalizado 2 HU04 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo owncloudApp relacionado con el caso de uso de consulta del estado de las subidas 1 HU05 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudDomain relacionado con el caso de uso de consulta del estado de las subidas 1 HU06 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudData relacionado con el caso de uso de consultado del estado de las subidas 1 HU07 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo owncloudApp relacionado con el caso de uso de subida de un fichero 1 HU08 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudDomain relacionado con el caso de uso de subida de un fichero 1 HU09 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo owncloudData relacionado con el caso de uso de subida de un fichero 1 HU10 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo owncloudComLibrary relacionado con el caso de uso de subida de un fichero 2 HU11 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos del caso de uso de subida de un fichero 5 HU12 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos del caso de uso de consulta del estado de las subidas 3 Tabla A.13: Historias de usuario asociadas a la épica 2 (EP02: Ingeniería inversa) Código Historia de usuario Puntos HU13 Como desarrollador quiero documentarme y aprender sobre la tecnología de Jetpack Compose 2 HU14 Como desarrollador quiero migrar la pantalla de subidas de la aplicación ownCloud de XML a Jetpack Compose 5 HU15 Como desarrollador quiero poder hacer una comparativa después de haber migrado la pantalla de las subidas 2 Tabla A.14: Historias de usuario asociadas a la épica 1 (EP01: Migración de XML a Jetpack Compose) 124
APÉNDICE B. SEGUIMIENTO DEL PROYECTO Apéndice B Seguimiento del proyecto B.1. Introducción En este capítulo se ha detallado el seguimiento real de todo el proyecto sprint a sprint. Se ha establecido un apartado por cada sprint, en el cual se entra más a detalle con el progreso de cada uno. A excepción del Sprint 0, todos los demás sprint tendrán una estructura similar. El proyecto comenzó el día 19 de febrero de 2024, y según la planificación inicial que se ha realizado terminará el 20 de junio de 2024 como muy pronto (primeras fechas) o el 7 de julio de 2024 como muy tarde (segundas fechas). B.2. Sprints B.2.1. Sprint 0 (19/02/2024 - 04/03/2024) La duración de este sprint es de 2 semanas al igual que el resto, sin embargo, como ya se ha mencionado en el capítulo A.7 este sprint es bastante diferente al resto. La estimación inicial que se le ha dado a este sprint es de 20 horas, que a diferencia del resto es la mitad. Durante este sprint se ha llevado a cabo la planificación y organización del TFG. Además, durante este período de tiempo se ha comenzado con la lectura de varios TFG con el mismo método de trabajo, los cuáles pertenecían a Juan Carlos Garrote Gascón [22], María Robles del Blanco [28] y Richard Albán Fernández [45]. En especial, se ha puesto bastante atención en el TFG de María Robles pues trataba temas de ingeniería inversa de un proyecto open-source. Estas son las principales tareas que se han llevado a cabo durante este sprint, las cuales se encuentran detalladas según las horas de trabajo y estado de cada una en la Tabla B.1. 125
B.2. SPRINTS Nombre de la tarea Tiempo estimado Tiempo dedicado Estado Lectura del TFG de Juan Carlos Garrote 4h 4h 45min Completada Lectura del TFG de María Robles 4h 7h Completada Lectura del TFG de Richard Albán 4h 4h Completada Planificación del TFG 4h 3h Completada Organización de los capítulos del TFG 4h 3h15min Completada Total 20h 22h 4/4 Tabla B.1: Tareas del Sprint 0 B.2.2. Sprint 1 (04/03/2024 - 18/03/2024) Durante este sprint ya se ha comenzando con las tareas de desarrollo del proyecto. En primer lugar, se llevó a cabo una serie de presentaciones para la formación. La primera de todas ha sido la descripción general del proyecto y la puesta en marcha. Durante esta sesión de formación, se ha explicado en líneas generales cuales son los diferentes productos que tiene la marca al igual que su estructura a grandes rasgos (back-end,front-end,mobile). Tras su finalización se ha hecho la instalación del proyecto en el dispositivo personal para poder trabajar en él. Tras ello se ha llevado a cabo una segunda sesión de formación, esta vez sobre el método de trabajo del equipo de ownCloud. En esta presentación se ha explicado cuál es la principal herramienta que se utiliza para la organización del proyecto (GitHub) al igual que otros detalles más a fondo como pueden ser los distintos estados en los que se encuentra cada tarea. Tras esa segunda sesión, se ha llevado a cabo una tercera. En esta sesión se ha explicado a fondo cual era la arquitectura de toda la aplicación. Para acabar, mencionar que durante este sprint se han dedicado 30h en total en las cuales se incluyen, no sólo las historias de usuario que se habían metido para este sprint sino también tareas de documentación. Durante este sprint se ha tenido el problema de la asignatura pendiente, contemplado en el riesgo A.5 y siendo imposible dedicarle las horas necesarias para completar todas las tareas. A pesar de ello se ha conseguido sacar adelante bastante trabajo. Todas aquellas tareas que no se han terminado, se desarrollarán durante sprints futuros, teniendo la necesidad de dedicarle más horas, siempre y cuando se den las condiciones necesarias. Además, existe una semana de vacaciones que en principio no se iba a hacer nada, pero se cuenta con la posibilidad de usar esos días para poder avanzar tareas atrasadas. 126
APÉNDICE B. SEGUIMIENTO DEL PROYECTO Historia de usuario Descripción de la tarea Tiempo empleado Estado HU01 Como desarrollador quiero documentarme sobre la arquitectura, funcionalidad, metodología y otros aspectos importantes de ownCloud 5h 30min Completada HU02 Como desarrollador quiero elaborar un diagrama inicial en el que se muestre la arquitectura principal de ownCloud 4h En progreso HU03 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle generalizado en el que se muestre la arquitectura en su totalidad 2h 30 min En progreso -Documentación de la introducción 5h 30min Completada -Documentación de requisitos y planificación 6h Completada -Documentación de la arquitectura de ownCloud 2h En progreso -Documentación del seguimiento del Sprint 0 2h Completada -Documentación del seguimiento del Sprint 1 2h 30min Completada Total 30h 5/8 Tabla B.2: Tareas del Sprint 1 B.2.3. Sprint 2 (18/03/2024 - 08/04/2024) Tal y como se mencionó anteriormente, la finalización de este sprint ha sido en una fecha más tardía que las 2 semanas estipuladas en la planificación por cada sprint por el simple motivo de que entre medias estaba la semana de vacaciones de Semana Santa. Durante este sprint, aparte de terminar aquellas historias de usuario que quedaron pendientes se han desarrollado todos los diagramas Modules&UsesStyle (HU04, HU05, HU06, HU07, HU08, HU09, HU10) de cada uno de los módulos que componen la aplicación de ownCloud, separados por casos de usos. Una vez que se han terminado los diagramas por módulos se ha creado otro diagrama Modules&UsesStyle para cada uno de los casos de usos en el que únicamente se muestra la relación entre todas las capas que conforma la aplicación. En este caso, se han especificado dos casos relacionados con la pantalla, la cual más tarde se migrará de XML a Jetpack Compose. El hecho de que haya dos casos de usos es que en uno de ellos no utilizaba uno de los módulos (owncloudComLibrary) mientras en el otro caso de uso sí se realizaban llamadas de red hacia servidores externos, y por tanto se podía apreciar la relación entre todos los módulos de la aplicación. A continuación se muestra un tabla detallada con todas las historias de usuario que se han desarrollado durante este sprint, así como su tiempo dedicado y el estado en el que se encuentran. En este caso no es necesario pasar al siguiente sprint ninguna tarea, ya que todas se encuentran en estado completado. Como mucho, realizar algunos retoques en los diagramas a partir del Sprint Review que da por finalizado este sprint y comienza el siguiente. Por otra parte, se puede apreciar cómo se ha necesitado menos tiempo del que se había estimado inicialmente, por lo que en sprints posteriores se tendrá la posibilidad de dedicar más tiempo a tareas que sean más difíciles o largas para hacer. A pesar de no haber cumplido con las horas que se habían estipulado en 127
B.2. SPRINTS la planificación (40 horas), se ha conseguido sacar adelante todo el trabajo, a excepción de la documentación que está pendiente de diagramas, que se había planificado teniendo un total de 31h dedicadas entre historias de usuario y otras tareas de documentación. Historia de usuario Descripción de la tarea Tiempo empleado Estado HU02 Como desarrollador quiero elaborar un diagrama inicial en el que se muestre la arquitectura principal de ownCloud 1h 30min Completada HU03 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle generalizado en el que se muestre la arquitectura en su totalidad 4h Completada HU04 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudApp relacionado con el caso de uso de consulta de estado de las subidas 4h Completada HU05 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudDomain relacionado con el caso de uso de consulta de estado de las subidas 3h 30min Completada HU06 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudData relacionado con el caso de uso de consulta de estado de las subidas 3h Completada HU07 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudApp relacionado con el caso de uso de subida de un fichero 3h Completada HU08 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudDomain relacionado con el caso de uso de subida de un fichero 2h 30min Completada HU09 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo ownCloudData relacionado con el caso de uso de subida de un fichero 2h 15min Completada HU10 Como desarrollador quiero elaborar un diagrama Modules&UsesStyle para el módulo owncloudComLibrary relacionado con el caso de uso de subida de un fichero 2h Completada - Documentación del seguimiento del Sprint 2 2h Completada - Documentación de la arquitectura de ownCloud 3h 15min En progreso Total 31h 10/11 Tabla B.3: Tareas del Sprint 2 B.2.4. Sprint 3 (08/04/2024 - 22/04/2024) Durante el transcurso de este sprint se ha tenido en cuenta el riesgo de la asignatura pendiente A.5, contemplado en el apartado de los riesgos posibles para este proyecto. Por este motivo no se ha podido dedicar el tiempo suficiente como para sacar adelante todas las tareas que se habían planificado para este sprint. A pesar de ello se ha comenzado con la historia de usuario HU11. Para ir desarrollando el diagrama de secuencia, se ha ido mirando lentamente todas las llamadas a los diferentes métodos de las clases implicadas además de los argumentos que iban dentro de cada llamada. También se han modificado 128
APÉNDICE B. SEGUIMIENTO DEL PROYECTO ligeramente los diagramas realizados en el anterior sprint, cosa que se tenía prevista y por tanto entraba dentro de la planificación de este sprint. De forma adicional, y con las historias de usuario pendientes para terminar en el siguiente sprint, se han llevado a cabo tareas de documentación. En primer lugar se ha documentado el apartado de las tecnologías utilizadas casi en su totalidad, faltando solamente realizar una comparación inicial entre XML y Jetpack Compose. Otra tarea de documentación que se ha llevado a cabo ha sido la explicación parcial de los diagramas de clases que se terminaron durante el sprint anterior. Debido a esa falta de tiempo para poder dedicarle a este sprint, ese apartado también ha quedado incompleto por lo que se irá terminando a lo largo de los siguientes sprints según se vayan acabando todos los diagramas pendientes. Teniendo en cuenta todos los inconvenientes que se han tenido durante sprint, se ha dedicado un total de 29h 50min. Todas las tareas que se tenían previstas en este sprint se terminarán en el siguiente sprint. Historia de usuario Descripción de la tarea Tiempo empleado Estado HU11 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos para el caso de uso de subida de un fichero 11h En progreso HU12 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos para el caso de uso de consulta del estado de las subidas - No iniciada - Documentación de la arquitectura de ownCloud 6h 15min En progreso - Documentación de las tecnologías utilizadas 6h 35min En progreso - Modificaciones en los diagramas Modules&UsesStyle 4h Completada - Documentación del seguimiento del Sprint 3 2h Completada Total 29h 50min 2/6 Tabla B.4: Tareas del Sprint 3 B.2.5. Sprint 4 (22/04/2024 - 06/05/2024) De las dos semanas que conforman el sprint, sólo ha sido posible trabajar durante la segunda semana del mismo debido al riesgo A.5, el cual ya estaba contemplado en el apartado respectivo. A pesar de no haber tenido una semana con disponibilidad para adelantar parte de las tareas que se habían movido para este sprint, se han conseguido terminar 3 de las cinco que se habían planificado. La primera de ellas ha sido la historia de usuario HU11. Se han desarrollado todos los diagramas de secuencia que correspondía al caso de uso de subida de un fichero, el cual incluía tanto parte de registro de datos local como registro de datos en remoto, a través de llamadas de red. La otra tarea que también se ha terminado durante este sprint ha sido la documentación del apartado de las tecnologías utilizadas en todo el TFG. También mencionar que la tarea de documentación de la arquitectura de ownCloud lleva varios sprints en progreso. Esto es debido a que según se van haciendo los diagramas se va plasmando toda la información que corresponda en el informe y por tanto no es posible terminar con esta tarea hasta que se hayan desarrollado todas las historias de usuario relacionadas con la épica EP01. Por otra parte se ha comenzado con el desarrollo del diagrama de secuencia para el caso de uso de consulta del estado de las subidas. Este trabajo va a ser bastante más fácil que para el otro caso de uso, pues muchas cosas se pueden referenciar con el otro diagrama además de no tener toda la parte de llamadas de red hacia un servidor externo a la aplicación. 129
B.2. SPRINTS Teniendo en cuenta que todavía se encuentra en desarrollo se pasará al siguiente sprint. Para acabar, mencionar que las horas que se han dedicado a este sprint han sido 27h, las cuales se detallan más a fondo en la Tabla B.5. Historia de usuario Descripción de la tarea Tiempo empleado Estado HU11 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos para el caso de uso de subida de un fichero 14h 45min Completada HU12 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos para el caso de uso de consulta del estado de las subidas 4 h En progreso - Documentación de las tecnologías utilizadas 2h 15min Completada - Documentación de la arquitectura de ownCloud 4h En progreso - Documentación del seguimiento del Sprint 4 2h Completada Total 27h 3/5 Tabla B.5: Tareas del Sprint 4 B.2.6. Sprint 5 (06/05/2024 - 20/05/2024) El principal trabajo que se ha desarrollado a lo largo del sprint ha sido la historia de usuario HU12 correspondiente a la elaboración los diagramas de secuencia mostrando la interacción de todos los objetos que participan en el caso de uso de consulta del estado de las subidas además de documentar todo lo relativo a los diagramas de secuencia correspondiente al caso de uso de subida de un fichero. Durante este sprint y, como se lleva apreciando a lo largo de otros sprints, se ha manifestado el riesgo A.5. Como consecuencia de esto, no se ha podido realizar suficiente trabajo y, por tanto, no se ha conseguido terminar las tareas que pertenecían al sprint anterior. Además, después de una reunión con los tutores y viendo el alcance de todas las tareas que quedaban por hacer, se ha decidido utilizar el Sprint extra que se había planificado en la Tabla A.1 como sprint de refuerzo en caso de contingencia. Además, se ha decidido dedicar el siguiente sprint entero a documentación de la arquitectura de ownCloud, dando por terminada la primera parte del trabajo. Por tanto durante los Sprint 7 y Sprint extra se llevará a cabo el trabajo de la migración de Jetpack Compose junto con su respectiva documentación. En resumen, en este sprint se han dedicado un total de 36h repartidas en tareas según indica la Tabla B.6. 130
APÉNDICE B. SEGUIMIENTO DEL PROYECTO Historia de usuario Descripción de la tarea Tiempo empleado Estado HU12 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos para el caso de uso de consulta del estado de las subidas 10h 40min En progreso - Documentación de la arquitectura de ownCloud 15h 10min En progreso - Documentación del seguimiento del Sprint 5 2h Completada -Modificaciones en los diagramas relacionados con la historia de usuario HU11 8h 10min Completada Total 36h 2/4 Tabla B.6: Tareas del Sprint 5 B.2.7. Sprint 6 (20/05/2024 - 03/06/2024) El principal trabajo que se ha desarrollado durante este sprint es la documentación de toda la arquitectura de ownCloud tanto de la vista estática como de la vista dinámica. Por otro lado también se ha terminado con la historia de usuario HU12 la cual era la última asociada a la épica EP01. Respecto al tiempo dedicado, ha sido el primer sprint en el que se han completado todas las horas que se habían estimado durante la planificación, habiendo dedicado un total de 44h. Todas las tareas y su respectivo tiempo se encuentran reflejadas en la Tabla B.7. Historia de usuario Descripción de la tarea Tiempo empleado Estado HU12 Como desarrollador quiero elaborar diagramas de secuencia que describan la interacción entre objetos para el caso de uso de consulta del estado de las subidas 4h Completada - Documentación de la arquitectura de ownCloud 38h Completada - Documentación del seguimiento del Sprint 6 2h Completada Total 44h 3/3 Tabla B.7: Tareas del Sprint 6 B.2.8. Sprint 7 (03/06/2024 - 17/06/2024) Este sprint se ha dedicado exclusivamente a la parte de la migración de XML a Jetpack Compose, la cual engloba las historias de usuario HU13,HU14 yHU15. Antes de comenzar con el proceso de migración de la pantalla del caso de uso, se ha tenido un período de formación en Jetpack Compose (HU13), sobre la cual no se tenía nada de conocimiento previo. La formación se ha basado en realizar los codelabs de Android, en los que se ha trabajado sobre varias de las funcionalidades o características de esta tecnología en cuestión, habiendo dedicado un total de aproximadamente 15 horas y 15 minutos de trabajo. Una vez que se ha terminado con todo el proceso de formación, el siguiente paso ha sido realizar la migración de la pantalla (HU14). Todo este proceso se ha conseguido completar en un tiempo menor que el estimado, teniendo un total de 21 horas de trabajo. Algo que hay que mencionar es que durante la segunda semana del sprint se ha tenido una ausencia durante aproximadamente cuatro días, por lo que el número de horas que se han podido dedicar a este 131