---
# System prepended metadata

title: Segundo reporte de programación

---

# Reporte de Proyecto: Módulo de Carrito y Compras - Avance 2

## 1. Declaración Inicial del Módulo

### i. Nombre de Equipo e Integrantes
- **Nombre del Equipo:** Carrito y Compras
- **Integrantes:**
  - Elías Currihuil
  - Agustín Troncoso

## 1.1 Estructura de Proyecto: Implementación del Patrón MVC y Capa de Repositorios

Dentro del marco de mejoras continuas, se ha reestructurado el proyecto para adoptar prácticas reconocidas en diseño y arquitectura de software.

### Patrón Modelo-Vista-Controlador (MVC)

El proyecto ha integrado el patrón **MVC**, que separa responsabilidades en:

- **Modelo**: Gestiona datos y lógica de negocio.
- **Vista**: Presenta información al usuario a través de interfaces.
- **Controlador**: Coordina la interacción entre Modelo y Vista.

La adopción de este patrón facilita la modularidad y mantenibilidad del software.

### Capa de Repositorios

Se ha añadido una **capa de repositorios** para gestionar la interacción con las fuentes de datos. Aunque el actual almacenamiento se basa en archivos JSON en el directorio `test-api`. Debido a lo anterior, actualmente los registros del sistema son estáticos y no se pueden modificar, pero se espera que en la siguiente entrega, y con la futura conexión a una fuente de almacenamiento de datos, su implementación sea la adecuada.

Resumiendo, esta capa permite una estructurada deserialización y presentación de datos a los controladores. Esta estrategia posiciona al proyecto para futuras adaptaciones en el almacenamiento de datos.

## 2. Entidades Principales y Flujo de Datos

## Flujo de Datos y Estructura de Entidades

Es esencial destacar que las acciones principales realizadas con cada entidad dentro del flujo de datos de la aplicación, se gestionan a través de un `Controller` y un `Repository` asociados. Estos componentes manejan la lógica de negocio y las transacciones con los sistemas de almacenamiento de datos. Las entidades actúan como un componente clave para la transacción de datos entre las diferentes capas de abstracción del sistema.

## Entidades Principales

La aplicación cuenta con una serie de entidades o modelos clave, que residen en el paquete `models`. Estas entidades definen la estructura y el flujo de datos de la app. A continuación, se presenta en detalle la entidad `Product`.

### Product 

La entidad `Product` es la encargada de representar los productos, en este caso, los juegos, dentro de la aplicación. Esta entidad juega un papel crucial en el flujo de datos, utilizando inicialmente al `ProductController`, que a su vez interactúa con el `ProductRepository` para gestionar las transacciones de datos en el sistema.

Sus principales atributos son:

- **id (int)**: Identificador único del producto.
- **name (String)**: Nombre del juego.
- **price (double)**: Precio del juego.
- **publisher (String)**: Editorial o empresa que publica el juego.
- **release (String)**: Fecha de lanzamiento.
- **categories (List<Category>)**: Lista de categorías a las que pertenece el juego. Esta lista está vinculada a un Enum `Category`, que define las posibles categorías a las que un juego puede ser asociado.
- **developer (String)**: Nombre del desarrollador.
- **stockQuantity (int)**: Cantidad disponible en stock.

#### Nota sobre el atributo `developer`:
Actualmente, el atributo `developer` se maneja como un `String`. Sin embargo, esto es una medida temporal. En futuras iteraciones, y con la integración de las instancias de usuario, se espera cambiar este atributo a una ID de Developer. De esta manera, se garantiza que cada producto pertenezca a un único desarrollador, proporcionando robustez y coherencia a la estructura.
    
### Cart

La entidad `Cart` representa el carrito de compras de un usuario en la aplicación, gestionado a través del `CartController`. Dada su naturaleza, se crea en tiempo de ejecución y no tiene una representación persistente a través de un `Repository` ya que se almacena en conjunto con la orden. Sus atributos principales son:

- **cartItems (List<CartItem>)**: Esta lista representa los artículos dentro del carrito. Cada `CartItem` tiene un producto asociado y una cantidad (representada por el atributo `int quantity`).
    
### DiscountCode

`DiscountCode` es la entidad responsable de representar los códigos de descuento en la aplicación. Esta entidad juega un papel vital al proporcionar descuentos a los usuarios y mejorar la experiencia de compra. Se apoya en el `DiscountCodeController` para su gestión y utiliza `DiscountCodeRepository` para la transacción y flujo de datos en el sistema. Los principales atributos de `DiscountCode` son:

- **code (String):** El identificador único y alfanumérico del código de descuento.
- **value (double):** Representa el valor de descuento que el código aporta, ya sea como un monto fijo o un porcentaje.

Este diseño permite una fácil integración con los sistemas de carrito y pago, garantizando que los descuentos se apliquen correctamente y se gestionen de manera eficiente.

### Payment

`Payment` es la entidad responsable de representar la transacción de pago realizada por un usuario en la aplicación. Para su gestión y funcionamiento, cuenta con un `PaymentController` dedicado. No requiere de un `Repository` específico, ya que la información se guarda conjuntamente con la entidad `Order`. Los atributos principales de `Payment` incluyen:

- **paymentID (int):** Identificador único del pago.
- **amount (double):** Monto total a pagar.
- **paymentMethod (PaymentMethod):** Relacionado con el Enum `PaymentMethod`, que contiene todos los métodos de pago posibles.
- **paymentDateTime (LocalDateTime):** Fecha y hora exacta del pago.
- **lastFourDigits (String):** Muestra únicamente los últimos cuatro dígitos de la tarjeta utilizada, garantizando la privacidad y seguridad del usuario.

#### Notas adicionales sobre `Payment`
Por el momento, se trabaja exclusivamente con tarjetas de crédito como método de pago y de forma ficticia, dados los recursos disponibles para integrar un sistema de transacciones bancarias auténtico. Actualmente, no se realiza una verificación real de la tarjeta de crédito; simplemente se comprueba que el número de tarjeta tenga 16 dígitos, que el CVV contenga 3 dígitos y que la fecha de vencimiento esté correctamente formatada. Para una validación genuina, sería esencial modificar el `PaymentController` para integrarse con una API bancaria o un servicio similar. Sin embargo, esta implementación solo se llevará a cabo si se dispone de los recursos y herramientas necesarios.


### Order

La entidad `Order` simboliza una orden realizada por un usuario. Para el manejo de datos y flujo de información, se apoya en el `OrderController` y el `OrderRepository`. Es crucial mencionar que esta entidad agrupa otras entidades fundamentales como `Cart` y `Payment`. Sus atributos centrales son:

- **orderID (int)**: Identificador único para la orden.
- **cart (Cart)**: Representa el carrito asociado con la orden.
- **orderDateTime (LocalDateTime)**: Fecha y hora en que se realizó la orden.
- **payment (Payment)**: Información de pago asociada a la orden.

#### Notas adicionales sobre `Order`:
1. Actualmente, el sistema cuenta solo con una orden de prueba que puede ser revisada por el usuario administrador. Esta implementación sirve para simular una interacción real y será mejorada con la introducción de una base de datos.
2. La entidad `Order` no posee un atributo `userID` que la relacione directamente con un usuario. Esta característica está en planes de implementación, una vez que se tenga la instancia de usuario en el sistema, permitiendo asociar y buscar órdenes por usuario específico.




### Flujos Principales de Entidades

A continuación, se presenta el principal flujo de datos entre las entidades de la aplicación:

- **Product**: View - ProductController - ProductRepository
- **Order**: View - OrderController - OrderRepository
- **DiscountCode**: View - DiscountCodeController - DiscountCodeRepository

### Excepciones en la Estructura

Existen ciertas excepciones en este flujo:

- **CheckoutController**: Actúa como un intermediario para la creación de una orden (Order) y el proceso de pago (Payment). Por ello, no interactúa directamente con una base de datos.
  
- **CartController**: Se genera en la instancia actual de la aplicación y se almacena en el detalle de la orden. Debido a esto, no necesita interacción con una base de datos.
  
- **PaymentController**: Se crea y se almacena junto con la orden, y se necesita para la selección del método de pago, por lo que no requiere interacción con una base de datos.

### Reflexión sobre el Diseño

Las excepciones mencionadas se deben principalmente a una intención de mantener un diseño sistemáticamente simple en la interacción con las entidades dentro de la base de datos. Tanto el pago (Payment) como el carrito (Cart) se almacenan directamente en la orden (Order). Aunque esto puede no ser ideal en situaciones donde la escalabilidad sea una prioridad, esta estructura se considera adecuada para el diseño actual del sistema. Sin embargo, en futuras versiones de la aplicación, sería recomendable reconsiderar esta estructura, atomizando lo más posible cada entidad dentro de las tablas en el sistema de almacenamiento de datos, y aplicando ciertas formas normales a éstas últimas, especialmente si la escalabilidad se convierte en una preocupación central.

---



## 3. Funcionalidades Desarrolladas

Dentro de esta sección, se describen en detalle las funcionalidades implementadas en el proyecto, proporcionando una comprensión clara y concisa de las capacidades y características desarrolladas.

---

### 3.1 Funcionalidad de Navegación: Clase NavigationHandler

Dentro del paquete `navigation`, se encuentra una clase crucial denominada `NavigationHandler`. Esta clase ha sido diseñada para gestionar de forma eficiente la navegación entre los menús del proyecto, adoptando un comportamiento similar al de una estructura de datos tipo stack (pila).

### Navegación Tipo Stack

La navegación tipo stack permite a los usuarios desplazarse cómodamente entre los menús, teniendo la capacidad de avanzar hacia nuevos menús y regresar a menús anteriores. Esta estructura garantiza que se mantenga un orden lógico y coherente en la navegación del usuario.

### Métodos Principales

1. **navigateTo(Menu menu)**:
   - Este método permite avanzar hacia un nuevo menú.
   - Se espera que el parámetro `menu` sea una instancia de una clase que herede de la clase abstracta `Menu`.
   - Al invocar este método, la instancia del menú proporcionada se coloca (o apila) en la estructura de stack, quedando en la cima.

2. **goBack()**:
   - Facilita la navegación hacia el menú anterior.
   - Al invocar este método, se retira (o desapila) el menú actual de la cima del stack, permitiendo que el usuario regrese al menú que se encontraba inmediatamente antes en la secuencia de navegación.

3. **pushReplacement(Menu menu)**:
   - Esta función, además de colocar un nuevo menú en la cima del stack, elimina todos los menús que estaban previamente en la pila, dejando solamente el nuevo menú proporcionado.
   - Es útil para situaciones donde se desea iniciar una nueva secuencia de navegación sin la necesidad de mantener el historial anterior.

La implementación de estos métodos y la estructura tipo stack en `NavigationHandler` aseguran una navegación fluida, intuitiva y organizada para los usuarios, permitiendo una experiencia de usuario optimizada y coherente.

---

###  3.2 Funcionalidades de Usuarios : Menús
Las funcionalidades específicas para cada tipo de usuario se reflejan en las vistas de la aplicación, alojadas en el paquete `views/menus`. La gestión y navegación de estas vistas se realiza a través de una clase principal: `MenuHandler`.

#### MenuHandler

`MenuHandler` es la clase encargada de determinar y presentar el menú adecuado en función del tipo de usuario que ingrese, una vez que se cuente con una instancia concreta del mismo. El método principal de esta clase es `startApp()`, el cual define la vista inicial que se mostrará al usuario.

Es importante señalar que el método `startApp()` tiene una conexión directa con la clase principal del módulo, denominada `App`. A través del método `run()` en `App`, se realiza una llamada a `MenuHandler`, activando la interfaz de usuario correspondiente y dando inicio a la interacción.

### 3.2.1 Usuario Común

**Descripción general**: El usuario común posee diversas acciones y capacidades dentro de la aplicación, permitiéndole navegar y gestionar sus productos de interés a través de diversos menús.

#### Menú Principal: Clase `MainMenu`

Las acciones disponibles en el menú principal para el usuario común son:

- **Ver todos los productos**: Permite al usuario visualizar todos los productos disponibles en la aplicación.
- **Buscar productos**: Facilita la búsqueda específica de productos según las necesidades o gustos del usuario.
- **Agregar productos al carrito**: Brinda la opción de añadir productos seleccionados al carrito de compras del usuario.
- **Mostrar el carrito**: Navega al menú específico del carrito, representado por la clase `CartMenu`.

#### Menú del Carrito: Clase `CartMenu`

Una vez dentro del menú del carrito, el usuario cuenta con las siguientes opciones:

- **Mostrar productos en el carrito**: Visualizar todos los productos que ha agregado previamente al carrito.
- **Modificar cantidad de un producto**: Permite ajustar la cantidad deseada de un producto específico dentro del carrito.
- **Eliminar un producto del carrito**: Facilita la eliminación de productos que el usuario decida no adquirir.
- **Ir a pagar**: Navega hacia el menú de finalización de compra, representado por la clase `CheckoutMenu`.

#### Menú de Finalización de Compra: Clase `CheckoutMenu`

En el menú destinado a finalizar la compra, el usuario tiene a su disposición las siguientes acciones:

- **Revisar el carrito**: Posibilita una revisión final de los productos seleccionados antes de concretar la compra.
- **Ingresar información y método de pago**: Espacio donde el usuario proporciona los detalles para procesar el pago.
- **Aplicar un código de descuento**: En caso de contar con uno, permite la inserción de un código promocional.
- **Finalizar compra y generar orden**: Una vez satisfecho con su selección y datos proporcionados, el usuario puede finalizar su compra, generando así una orden en el sistema.
    
### 🎥 Vídeo Demostrativo

En el siguiente enlace, se pueden ver las principales funcionalidades asociadas al usuario común:

[🔗 Ver Vídeo en Google Drive](https://drive.google.com/file/d/1qbysXkMQOmvRdMljdng_Lfph8VzR3hes/view?usp=sharing)
    

---

### 3.2.2 Usuario Administrador

**Descripción general**: El usuario administrador dispone de capacidades ampliadas dentro de la aplicación, permitiendo gestionar varios aspectos clave con un enfoque administrativo.

#### Menú Principal Administrativo: Clase `AdminMainMenu`

Las acciones principales disponibles en el menú del administrador son:

- **Gestionar Catálogo de Productos**: Navega a un submenú específico para la gestión de productos, representado por la clase `ProductManagementMenu`.
- **Gestionar Transacciones**: Dirige al usuario a un submenú dedicado a la gestión de transacciones, representado por la clase `OrderManagementMenu`.
- **Gestionar Ofertas (Códigos de descuento)**: Navega hacia un submenú destinado a la administración de códigos promocionales, representado por la clase `DiscountManagementMenu`.

#### Submenú de Gestión de Productos: Clase `ProductManagementMenu`

Dentro de este submenú, el administrador tiene las siguientes opciones:

- **Mostrar todos los productos**: Visualización completa del catálogo de productos disponibles.
- **Buscar Productos**: Permite la búsqueda de productos ya sea por su ID o por coincidencia en el nombre.
- **Eliminar Producto**: Facilita la eliminación de un producto del catálogo.

#### Submenú de Gestión de Transacciones: Clase `OrderManagementMenu`

Las capacidades en este submenú incluyen:

- **Listar todas las órdenes**: Presenta un resumen de todas las transacciones realizadas en la aplicación.
- **Buscar Orden por ID**: Posibilita la búsqueda específica de una transacción mediante su identificador.

**Nota**: En base a las conversaciones previas con el módulo de Cuentas de Usuario, se tiene la intención de agregar una funcionalidad adicional que permitiría buscar una orden a través del ID de usuario asociado. Sin embargo, debido a que actualmente no se puede acceder a una instancia del usuario, gestionado por dicho módulo, esta funcionalidad está en espera de implementación.

#### Submenú de Gestión de Códigos de Descuento: Clase `DiscountManagementMenu`

En esta sección, el administrador puede:

- **Crear un nuevo código de descuento**: Permite introducir nuevos códigos promocionales al sistema.
- **Eliminar un código de descuento**: Facilita la remoción de códigos que ya no están en uso o que se desean descartar.
- **Buscar un código de descuento**: Búsqueda específica de códigos promocionales.
- **Listar todos los códigos de descuento**: Visualización completa de todos los códigos disponibles para promociones.
    
### 🎥 Vídeo Demostrativo

En el siguiente enlace, se pueden ver las principales funcionalidades asociadas al usuario administrador:

[🔗 Ver Vídeo en Google Drive](https://drive.google.com/file/d/11Lipq7zS4vTadsUt1i9hN_UhfqLBK5lO/view?usp=sharing)

---
### 3.2.3 Usuario Dev

El usuario `dev` desempeña un rol vital dentro de la aplicación, teniendo una serie de acciones especiales a su disposición, centradas en la gestión de juegos. Las funcionalidades son las siguientes:

#### Gestión de Juegos

- **Registrar/Crear un nuevo juego**: Permite a los desarrolladores añadir nuevos títulos a la plataforma.
- **Eliminar juego**: Esta función requiere especificar un ID para identificar y eliminar el juego correspondiente.
- **Actualizar detalles del juego**: Mediante un ID, el desarrollador puede modificar detalles específicos del juego. 
  - **Nota**: Esta funcionalidad está parcialmente completada. Se espera concluir su implementación en la próxima entrega, permitiendo que el usuario determine qué aspectos específicos del juego desea modificar.
  
- **Listar sus juegos**: Ofrece un resumen de todos los juegos asociados al desarrollador.
  - **Nota**: Dado que se trabaja con datos simulados y aún no hay una instancia del usuario en el sistema, esta funcionalidad será perfeccionada en la próxima entrega.
  
- **Buscar sus juegos**: La búsqueda se puede realizar por coincidencia de nombre o mediante un ID.
  - **Nota**: Esta función también está pendiente de ajustes debido a la falta de una instancia del usuario.

- **Ver número de venta de sus juegos**: Una herramienta que permite visualizar el éxito comercial de sus títulos.
  - **Nota**: Al igual que otras funciones, esta necesita mejoras por las mismas razones previamente mencionadas.

#### Reflexión sobre el Desarrollo del Usuario Dev

A lo largo de la implementación, ha quedado claro que el perfil de usuario `dev` necesita un enfoque y trabajo intensivo para su correcta implementación. Esta situación tiene su origen en la decisión tardía del módulo de Cuentas de Usuario sobre cómo manejar la instancia del usuario. No obstante, en recientes reuniones, se acordó la incorporación del usuario `dev` dentro de este módulo. Por ello, se espera que para la próxima entrega, este perfil esté completamente desarrollado y operativo.
    
### 🎥 Vídeo Demostrativo

En el siguiente enlace, se pueden ver las principales funcionalidades asociadas al usuario dev:

[🔗 Ver Vídeo en Google Drive](https://drive.google.com/file/d/10TQ7uUfKXNinLQJL6jE8-yjizPz9Kira/view?usp=sharing)
    
---

## 3. Utilidades

En el marco del desarrollo de la aplicación, se ha establecido un paquete denominado `utils` que organiza y alberga las diferentes utilidades o "handlers" que facilitan y optimizan la operatividad del sistema. A continuación, se detallan estas utilidades:

### DisplayHandler

`DisplayHandler` actúa como el principal administrador de la presentación de las vistas en la consola. A través de sus métodos, esta herramienta ofrece soluciones para mostrar y formatear la información de manera adecuada, garantizando una experiencia amigable para el usuario. Es ampliamente utilizada por clases que derivan tanto de `Menu` como de `Controller`, para presentar y actualizar la información visualizada por el usuario.

### InputHandler

`InputHandler` está destinada a administrar y validar las entradas o "inputs" realizadas por el usuario. Gracias a esta utilidad y sus respectivos métodos, es posible verificar que las entradas del usuario sean las adecuadas; por ejemplo, garantizar que un input esperado como un entero (`int`) no sea ingresado como una cadena de texto (`String`). Al igual que `DisplayHandler`, esta herramienta es esencial para clases que heredan de `Menu` y de `Controller`.

### Messages

El módulo `Messages` tiene el propósito de contener mensajes estáticos que se despliegan al usuario. Al conservar estos mensajes como constantes, se facilita la adaptabilidad del sistema; por ejemplo, si en el futuro se desea implementar soporte multilenguaje, simplemente sería necesario traducir los textos almacenados en esta utilidad, favoreciendo la escalabilidad y accesibilidad de la aplicación.

### ANSIColors

Finalmente, `ANSIColors` se encarga de enriquecer la experiencia visual del usuario al almacenar y administrar los colores empleados en las vistas gestionadas por `DisplayHandler`. Estos colores, almacenados en formato ANSI, garantizan compatibilidad con la mayoría de las consolas o terminales en uso, proporcionando un ambiente visual atractivo y amigable para el usuario.
    
---
    
## 4. Análisis de la Complejidad Ciclomática
    
La complejidad ciclomática es una métrica de software que mide la cantidad de caminos independientes a través del código fuente de un programa. Esencialmente, indica cuántos flujos diferentes o caminos lógicos puede tomar un programa durante su ejecución. Esta métrica es útil para determinar la complejidad de un programa y, por lo tanto, puede ayudar a identificar áreas que podrían beneficiarse de pruebas adicionales o refactoring. Un valor más alto suele indicar una mayor complejidad y potencialmente un mayor riesgo de defectos.    

### Complejidad Ciclomática Total

En el contexto del proyecto, se observa una complejidad ciclomática total significativamente alta, alcanzando un valor de **305**.

![Imagen de la complejidad ciclomática total](https://hackmd.io/_uploads/rJZksLtfp.png)
    
    
Esta magnitud puede ser inicialmente alarmante, pero su interpretación adquiere sentido al considerar la estructura y funcionamiento del sistema. Para proporcionar un panorama más claro:

1. **Cantidad de métodos y clases**: La aplicación cuenta con 170 métodos distribuidos en 35 clases.

![Imagen de cantidad de métodos y clases](https://hackmd.io/_uploads/H1HEiLFza.png)
    

La complejidad ciclomática es un valor acumulativo, por lo que un sistema con un número elevado de métodos y clases tenderá a tener un valor de complejidad más alto.

2. **Estructuras switch-case**: Las clases que heredan de `Menu` emplean extensivamente estructuras `switch-case` para gestionar las opciones ingresadas por el usuario. Debido a que existen tres tipos de usuarios (Admin, Dev y el usuario común), es imperativo tener múltiples menús que contemplan diferentes interacciones. Además, los menús anidados y las actualizaciones de vistas a través de `Controller` incrementan la complejidad.

3. **Métodos de gestión de menús**: Cada clase que hereda de `Menu` implementa métodos como `runMenuLoop()`, que encapsula la estructura `switch-case` dentro de un bucle, permitiendo una correcta funcionalidad del menú. Esto conlleva a un incremento exponencial en los caminos dentro de un menú, reflejándose directamente en la complejidad ciclomática.

**Posible solución**: Para mitigar este crecimiento en la complejidad, sería recomendable considerar el uso de librerías de interfaces gráficas como JavaFX. Esta aproximación reduciría la necesidad de estructuras `switch-case` al gestionar menús, y por consiguiente, reduciría la complejidad asociada.

### Complejidad Ciclomática por Método

La complejidad ciclomática por método se calcula dividiendo la complejidad ciclomática total entre el número de métodos. En este caso, el valor resultante es **1.79 por método**.

Este valor representa el promedio de caminos distintos que un método puede tomar durante su ejecución. Aunque el valor total de la complejidad es alto, un valor de 1.79 por método sugiere que, en promedio, los métodos del sistema no son excesivamente complejos por sí mismos.

**Evaluación de Riesgo**: A pesar de la complejidad ciclomática total elevada, el valor por método es bastante razonable. Esto sugiere que el sistema, a pesar de su complejidad global, está compuesto por métodos individuales que son manejables y, en su mayoría, directos. Al compararlo con la complejidad total, es evidente que la principal contribución a la complejidad se debe a la estructura general y la gestión de menús, y no a la complejidad intrínseca de los métodos individuales.

---
    
## 5. Análisis de Acoplamiento (CBO)
    
### 5.1 Identificación de clases y organización según el patrón MVC y la capa de repositorios

#### Modelo (Model)
- `Cart`
- `CartItem`
- `DiscountCode`
- `Order`
- `Payment`

#### Vista (View/Menu)
- `AdminMainMenu`
- `DiscountManagementMenu`
- `OrderManagementMenu`
- `ProductManagementMenu`
- `DevMainMenu`
- `CartMenu`
- `CheckoutMenu`
- `MainMenu`
- `Menu` (Clase Abstracta)
- `MenuHandler`

#### Controlador (Controller)
- `CartController`
- `CheckoutController`
- `Controller` (Clase abstracta) 
- `DiscountCodeController` 
- `OrderController`
- `PaymentController`
- `ProductController`


#### Repositorios
- `DiscountCodeRepository`
- `OrderRepository`
- `ProductRepository`
- `Repository` (Interface)
    
#### Utils
- `ANSIColors` 
- `DisplayHandler` 
- `NavigationHandler`
- `InputHandler` 
- `Messages`    
    
#### Otros
- `App`
- `Main`
    
### 5.2 Diagrama de Dominio    
  
![](https://hackmd.io/_uploads/ry9TLt2za.png)
        
### 5.3 Análisis de CBO (Coupling Between Object classes)

| Clase                  | CBO |
|------------------------|-----|
| `App`                  | 1   |
| `MenuHandler`          | 5   |

#### Models
| Clase          | CBO |
|----------------|-----|
| `Cart`         | 3   |
| `CartItem`     | 1   |
| `Payment`      | 2   |
| `Order`        | 4   |
| `DiscountCode` | 2   |
| `Product`      | 2   |

#### Views/Menus
| Clase             | CBO |
|-------------------|-----|
| `MainMenu`        | 7   |
| `AdminMainMenu`   | 7   |
| `DevMainMenu`     | 7   |

#### Controllers
| Clase                   | CBO |
|-------------------------|-----|
| `PaymentController`     | 7   |
| `OrderController`       | 8   |
| `CheckoutController`    | 8   |
| `DiscountCodeController`| 7   |
| `ProductController`     | 7   |
| `CartController`        | 7   |

> **Nota:** Hay ciertos controladores que no se conectan a un repositorio, específicamente `CartController`, `PaymentController` y `CheckoutController`, por lo que tienen una relación menos.


#### Repositories
| Clase                   | CBO |
|-------------------------|-----|
| `ProductRepository`     | 1   |
| `DiscountCodeRepository`| 1   |
| `OrderRepository`       | 1   |

#### Utils
| Clase            | CBO |
|------------------|-----|
| `NavigationHandler` | 2 |
| `InputHandler`     | 3 |
| `DisplayHandler`   | 3 |
| `ANSIColors`       | 2 |
| `Messages`         | 2 |

---

### Plan de Mejora

A partir del análisis de CBO, se identifica que los controladores presentan un alto grado de acoplamiento. Sin embargo, algunos de ellos, como `CartController`, `PaymentController` y `CheckoutController`, tienen un acoplamiento ligeramente reducido debido a la falta de conexión con los repositorios. Las clases dentro de la sección de "Views/Menus" también muestran un elevado CBO, sugiriendo una intensa interacción con otras partes del sistema. Por otro lado, las clases utilitarias y los modelos presentan un CBO más equilibrado. Estos hallazgos generales nos llevan a proponer ciertas mejoras en la estructura del sistema.

En base a lo anterior, se podría considerar:

1. **Inyección de Dependencias**: Implementar la inyección de dependencias puede ser útil, especialmente para clases utilitarias. Esta práctica no solo facilitaría las pruebas sino que reduciría el acoplamiento. Actualmente, se hacen llamadas estáticas a clases utilitarias como `Messages` y `ANSIColors`, lo que hace que la dependencia esté firmemente codificada. La inyección de dependencias ayudaría a separar las dependencias de su implementación.

2. **Uso de Interfaces Gráficas**: Al utilizar librerías de interfaces gráficas como JavaFX, es posible reducir el número de clases relacionadas con las vistas, lo que a su vez reduce el CBO para los controladores.

3. **Capa de Abstracción Adicional**: Pensando en la escalabilidad y los principios SOLID, agregar una capa de servicios o `services` sería beneficioso. Esto permitiría que los controladores manejen principalmente la interacción con la interfaz del usuario y deleguen la lógica a los servicios; los controladores pasarían a tener una única responsabilidad:  mediar entre la vista y los servicios.

---
## 6. Análisis de Cohesión por Clase: `ProductRepository`
### LCOM (Lack of Cohesion in Methods)

El método **LCOM** (Lack of Cohesion in Methods) es una métrica que evalúa la cohesión entre los métodos de una clase. Aunque la cohesión puede ser interpretada subjetivamente, el LCOM proporciona una forma cuantitativa de medirlo.

La clase `ProductRepository` contiene los siguientes métodos que operan sobre la única variable de instancia presente, `products`:

- `loadProducts()`
- `findAll()`
- `findByID(int id)`
- `findByName(String name)`
- `deleteByID(int id)`
- `save(Product entity)`
- `exists(int id)`
- `existsByName(String name)`

### Cálculo del LCOM:

1. Se crea un conjunto para cada método que contiene las variables de instancia que utiliza.
2. Se cuentan cuántos conjuntos no tienen intersección entre sí.
3. Se cuentan cuántos conjuntos sí tienen intersección entre sí.
4. **LCOM** = Número de conjuntos sin intersección - Número de conjuntos con intersección.

Si todos los conjuntos tienen al menos una intersección con otro conjunto, entonces **LCOM** = 0, indicando una alta cohesión. Si **LCOM** > 0, la cohesión es baja.

Para `ProductRepository`, todos los métodos acceden a la variable de instancia `products`. Por lo tanto, todos los conjuntos tendrán intersección con otros conjuntos. Esto resulta en un **LCOM = 0**, indicando alta cohesión.

### Tipo de Cohesión:

La clase exhibe cohesión funcional, ya que todos los métodos están relacionados con una función específica: administrar productos. Cada método tiene la tarea de acceder, consultar o modificar una lista de productos.

### Mejoras:

- La gestión de la carga de productos desde un archivo JSON podría delegarse en una clase dedicada o en un método de una clase de utilidad para reducir la responsabilidad de `ProductRepository` y aumentar la cohesión funcional.
- Aunque la clase muestra cohesión, tiene una variedad de responsabilidades, incluida la lectura del archivo JSON. Siguiendo el principio de responsabilidad única, sería recomendable tener una clase separada para cargar productos desde archivos o fuentes de datos externas.
- El manejo de errores, como el hecho de imprimir el error directamente en `loadProducts()`, podría mejorarse. En lugar de simplemente imprimir el error, sería recomendable lanzar una excepción personalizada y manejarla en una capa superior.








