-
Notifications
You must be signed in to change notification settings - Fork 0
Información sobre la aplicación de patrones de arquitectura: diagrama de "componentes" y explicación de los mismos.
En este apartado se incluye el diagrama de componentes de nuestra aplicación, así como los patrones de arquitectura usados y su implementación.
En el diagrama podemos ver, separados en capas, los distintos componentes de nuestra aplicación. Cada componente es un paquete dentro de nuestra aplicación que contiene el resto de clases de la misma, de forma que, por ejemplo, el componente "fragments" contiene a todas las clases de tipo "Fragment", está en la capa de "View" y usa los adapters y los viewModels para su implementación. De esta forma, quedan definidos los componentes que usa nuestra aplicación (además de estar divididos en capas) y las relaciones entre ellos.
A continuación se explican los patrones aplicados en la aplicación.
El patrón Model-View-ViewModel (MVVM) es una arquitectura de diseño de software que se utiliza comúnmente en el desarrollo de aplicaciones de interfaz de usuario. Este patrón separa claramente las responsabilidades y roles de los componentes principales de una aplicación. Aquí te explico cada uno de los componentes del patrón MVVM:
Representa los datos y la lógica de negocio de la aplicación. El modelo no tiene conocimiento de la interfaz de usuario y se centra en la manipulación de datos y la implementación de reglas empresariales. Gestiona los datos y las operaciones relacionadas con la lógica de negocio. El modelo lo hemos incluido en el paquete model, en la raíz de nuestro paquete de aplicación. Contiene todas las clases de datos necesarias para la gestión de la aplicación y la base de datos con sus atributos necesarios, y se incluyen en la siguiente imagen.
En el subpaquete Api, se ven las clases necesarias para el modelo en relación con la API y los datos que se recuperan de la misma que, como se explica en el patrón Repository, se deben guardar también en la base de datos.
Representa la interfaz de usuario y su estructura visual. En el contexto de una aplicación para el usuario final, la vista es la pantalla que presenta la información y recibe las interacciones del usuario. Trata de mostrar la información al usuario y reaccionar a las acciones del usuario, pero no contiene lógica de negocio. La vista de nuestra aplicación la incluimos en el paquete view de la misma, y dentro de ella encontramos, ordenadas por sus correspondientes subpaquetes, las diferentes implementaciones que necesitamos, como son:
- activities
- adapters
- fragments
La vista general de la parte View de nuestro proyecto es la que se aprecia en la siguiente imagen.
Actúa como un intermediario entre la vista y el modelo. Es responsable de exponer datos desde el modelo a la vista y manejar las interacciones del usuario en la vista para actualizar el modelo. Sus principales responsabilidades son convertir datos del modelo en un formato que pueda ser mostrado por la vista, gestionar la interacción del usuario y actualizar el modelo en consecuencia.
La vista observa y se enlaza a propiedades y comandos proporcionados por el ViewModel. El ViewModel interactúa con el Modelo para obtener o modificar datos. Cuando el Modelo se actualiza, el ViewModel notifica a la vista a través de la notificación de cambios (por ejemplo, mediante el uso de observables). La vista actualiza su interfaz de usuario según los cambios notificados por el ViewModel.
El patrón DAO (Data Access Object) es un enfoque en el desarrollo de software que apunta a mantener la lógica de acceso a datos separada de la lógica de negocio. Este patrón se presenta con varios elementos clave.
Primero, está la Interfaz DAO, que establece los métodos para operaciones básicas como crear, leer, actualizar y eliminar (CRUD) en objetos de dominio. Luego, se tienen las Implementaciones concretas del DAO, que ofrecen la implementación real de esos métodos para una fuente de datos específica, como una base de datos relacional.
Los Objetos de Dominio representan las entidades de la aplicación que se almacenan en la base de datos. Normalmente, estos objetos se alinean directamente con las tablas de la base de datos. La Lógica de Negocio (Cliente) utiliza la interfaz del DAO para interactuar con la base de datos, manteniéndose ajena a los detalles específicos de implementación. Esto permite cambiar la fuente de datos sin tocar el código del cliente.
Opcionalmente, el patrón DAO puede incluir una Factoría que facilita la obtención de instancias concretas de DAO. Esto posibilita cambiar la fuente de datos subyacente sin alterar el código del cliente.
Entre las ventajas del patrón DAO, se destaca la clara separación de responsabilidades entre la lógica de acceso a datos y la lógica de negocio. Esto mejora la mantenibilidad, la reutilización de código y la flexibilidad al permitir cambios en la implementación de la base de datos sin afectar otras partes de la aplicación. Además, el patrón DAO facilita las pruebas unitarias al posibilitar la creación de implementaciones de DAO de prueba sin depender de una base de datos real.
Esta implementación la hemos realizado con Room en nuestro proyecto, estando las interfaces de acceso a la base de datos en el paquete uex.aseegps.ga03.tuonce.database, en el que se incluyen las clases ActividadDao, EquipoDao, etc. cada una con el código Room necesario para acceder a la base de datos mediante las consultas especificadas en las etiquetas. Desde el repositorio, como se explicará a continuación, accederemos a estas interfaces.
Asimismo, en este paquete encontramos TuOnceDatabase, que es una clase abstracta necesaria para acceder a la base de datos de la aplicación. En ella se detallan las funciones del DAO a las que se podrá llamar, así como las entidades que tendrá la base de datos, implementando un patrón Singleton
Los objetos del dominio se explicarán en el apartado de ModelViewViewModel, ya que son parte del modelo de datos.
El patrón Repository, o Repositorio, es una estrategia de diseño de software que se utiliza para facilitar la gestión de la persistencia de objetos. Su enfoque principal es ofrecer una interfaz simplificada para trabajar con objetos en una fuente de datos, como una base de datos. La idea es que el cliente que utiliza esta interfaz no necesite conocer los detalles específicos sobre cómo se almacenan o recuperan los datos.
En este patrón, se establece una Interfaz Repository que define los métodos necesarios para realizar operaciones básicas como crear, leer, actualizar y eliminar (CRUD) en los objetos almacenados. Luego, hay una Implementación concreta del Repository que se encarga de proporcionar la implementación real de estos métodos para una fuente de datos específica, como una base de datos relacional.
Los Objetos de Dominio son esenciales en este contexto, ya que representan los objetos de la aplicación que se almacenan o recuperan mediante el Repository. Estos objetos suelen mapearse directamente a las entidades de la fuente de datos.
El cliente (es decir, lo que llamamos la lógica de negocio de nuestra aplicación, implementada en los ViewModel, como se comentará más adelante) es el componente que utiliza la interfaz del Repository para interactuar con los objetos de dominio, sin la necesidad de comprender los pormenores de cómo se gestionan los datos en la fuente subyacente. En otras palabras, la lógica de negocio se comunica con los objetos de dominio a través del Repository, manteniendo así una separación limpia de responsabilidades.
En términos de ventajas, el patrón Repository proporciona una capa de abstracción que simplifica el acceso a datos y permite que la lógica de negocio trabaje con los objetos de una manera más intuitiva. Además, esta abstracción facilita la reutilización de código y la adaptación a diferentes fuentes de datos sin cambiar la lógica de negocio. En resumen, el patrón Repository es una herramienta valiosa para simplificar la gestión de datos en una aplicación.
El patrón Repository lo hemos incluido como una clase en el paquete uex.aseegps.ga03.tuonce.model, y en él se detallan todos los elementos que hacen falta para que los ViewModel accedan a él y recuperen los datos correctamente.
hay varias variables LiveData y filtros que se utilizan para observar y obtener datos específicos de estas fuentes de datos. Aquí está la explicación de las variables y cómo algunas dependen de los filtros correspondientes:
userDao, ligaDao, futbolistaDao, equipoDao, actividadDao: Son instancias de DAO (Data Access Objects) que proporcionan métodos para acceder a datos relacionados con usuarios, ligas, futbolistas, equipos y actividades respectivamente.
userFilter, equipoFilter, ligaFilter: Son variables LiveData que actúan como filtros. Estos filtros se utilizan para cambiar dinámicamente las consultas y obtener datos específicos basados en ciertos criterios, como el ID de usuario, el ID de equipo o el ID de liga.
userName: Variable LiveData que contiene el nombre de usuario actual. usuarioConectado: LiveData que observa el cambio en el nombre de usuario y recupera los detalles del usuario conectado desde userDao.
futbolistas: LiveData que observa los cambios en la base de datos de futbolistas y obtiene la lista completa de futbolistas.
actividades: LiveData que observa los cambios en el filtro de usuario y recupera la lista de actividades asociadas a ese usuario.
equipoUsuario: LiveData que observa el filtro de usuario y obtiene el equipo asociado a ese usuario. ligaUsuario: LiveData que observa el filtro de usuario y obtiene la liga asociada a ese usuario.
usuariosLiga: LiveData que observa el filtro de liga y obtiene la lista de usuarios asociados a esa liga.
bot1, bot2, bot3: LiveData que contiene información de usuarios específicos (bots)
equipoBot1, equipoBot2, equipoBot3: LiveData que observa los cambios en la información del bot y recupera el equipo asociado a ese bot.
futbolistasEquipoBot1, futbolistasEquipoBot2, futbolistasEquipoBot3: LiveData que observa los cambios en la información del equipo del bot y obtiene la lista de futbolistas asociados a ese equipo.
-
actualizarFutbolista actualiza un futbolista en la base de datos utilizando el método update de futbolistaDao con el futbolista proporcionado como parámetro.
-
actualizarEquipo actualiza un equipo en la base de datos utilizando el método update de equipoDao con el equipo opcional proporcionado como parámetro.
-
venderFutbolistaDelequipo realiza varias operaciones al vender un futbolista de un equipo. Primero, actualiza el valor del equipo sumándole el valor del futbolista vendido mediante actualizarValorEquipoSumar. Luego, actualiza el futbolista vendido quitándole el equipo asignado mediante actualizarFutbolistaSinEquipo. Finalmente, marca la actividad de venta con el usuario y el nombre del jugador mediante marcarActividadVenta.
-
eliminarUsuario elimina un usuario de la base de datos utilizando el método delete de userDao con el ID proporcionado como parámetro.
-
eliminarEquipo elimina un equipo de la base de datos utilizando el método delete de equipoDao con el equipo proporcionado como parámetro.
-
eliminarLiga elimina la liga de la base de datos utilizando el método eliminarLiga de ligaDao.
-
eliminarFutbolistaDelMercado realiza varias operaciones al eliminar un futbolista del mercado. Primero, actualiza el valor del equipo restando el valor del futbolista comprado mediante actualizarValorEquipo. Luego, actualiza el equipo del futbolista comprado asignándole el equipo del usuario mediante actualizarEquipoDelFutbolista. Finalmente, marca la actividad de compra con el usuario y el nombre del jugador mediante marcarActividadCompra.
-
actualizarFutbolistaSinEquipo quita el equipo asignado a un futbolista estableciendo su equipoId a null y luego lo actualiza en la base de datos mediante el método update de futbolistaDao.
-
actualizarEquipoDelFutbolista asigna un nuevo equipo a un futbolista estableciendo su equipoId al equipoUsuario proporcionado y luego lo actualiza en la base de datos mediante el método update de futbolistaDao.
-
moveral11 establece que un futbolista está en el once titular estableciendo su estaEnel11 a 2 y luego lo actualiza en la base de datos mediante el método update de futbolistaDao.
-
modificarDatos realiza modificaciones en dos futbolistas. Establece que el primer futbolista no está en el once titular (estaEnel11 a 0) y que el segundo futbolista está en el once titular (estaEnel11 a 1). Luego, actualiza ambos futbolistas en la base de datos mediante el método update de futbolistaDao.
-
noCambio establece que un futbolista está en el once titular (estaEnel11 a 1) y que otro no está en el once titular (estaEnel11 a 0). Luego, actualiza ambos futbolistas en la base de datos mediante el método update de futbolistaDao.
-
actualizarValorEquipoSumar suma el valor de un futbolista al presupuesto de un equipo y luego actualiza el equipo en la base de datos mediante el método update de equipoDao.
-
actualizarValorEquipo resta el valor de un futbolista al presupuesto de un equipo y luego actualiza el equipo en la base de datos mediante el método update de equipoDao.
-
marcarActividadCompra crea una nueva actividad de compra y la inserta en la base de datos utilizando el método insertar de actividadDao.
-
marcarActividadVenta crea una nueva actividad de venta y la inserta en la base de datos utilizando el método insertar de actividadDao.
-
actualizarPuntos actualiza los puntos de un usuario en la base de datos utilizando el método updatePoints de userDao.
-
marcarActividadCrearLiga crea una nueva actividad de inicio de jornada y la inserta en la base de datos utilizando el método insertar de actividadDao.
-
marcarActividadTerminarLiga crea una nueva actividad de finalización de liga y la inserta en la base de datos utilizando el método insertar de actividadDao.
-
insertarLiga inserta una nueva liga en la base de datos y devuelve su identificador utilizando el método insertarLiga de ligaDao.
-
marcarActividadNuevaLiga crea una nueva actividad de inicio de liga y la inserta en la base de datos utilizando el método insertar de actividadDao.
-
insertarBot inserta un nuevo bot en la base de datos y devuelve su identificador utilizando el método insert de userDao.
-
insertarFutbolista inserta un nuevo futbolista en la base de datos utilizando el método insert de futbolistaDao.
-
insertarEquipo inserta un nuevo equipo en la base de datos y devuelve su identificador utilizando el método insert de equipoDao.
-
insertarUsuario inserta un nuevo usuario en la base de datos y devuelve su identificador utilizando el método insert de userDao.