domain - PowerSystem2024/CapybaraFilms_ProyectoTercerSemestre GitHub Wiki

arriba

📖 Contenido:

📁 Domain/

La Capa de Dominio constituye el corazón del sistema Capybara Films, encapsulando la lógica de negocio fundamental y las reglas que gobiernan las operaciones de reserva de cine. Esta capa implementa los principios de Domain-Driven Design (DDD), manteniendo la independencia de la infraestructura y enfocándose exclusivamente en los conceptos del negocio.

1. Propósito y Responsabilidades

La capa de dominio tiene como objetivo principal modelar los conceptos del mundo real del negocio cinematográfico en código, proporcionando:

  • Entidades de Negocio: Representan los objetos principales del dominio como Cliente.py , Reserva.py , Butaca.py , Pelicula.py , Sala.py y Candy.py.

  • Reglas de Negocio: Implementa validaciones y lógica específica del dominio directamente en las entidades, como las validaciones de DNI en Cliente.py:37-40 y el cálculo de precios en Reserva.py:28-55.

  • Tipos de Dominio: Define enumeraciones y value objects que garantizan consistencia y type safety, incluyendo TipoButaca.py , TipoCandy.py , FormatoPelicula.py y Ubicacion.py.

2. Arquitectura del Dominio

El diseño sigue patrones establecidos de DDD:

  • Aggregate Root: La entidad Reserva actúa como agregado raíz, coordinando todas las operaciones relacionadas con una reserva de cine.
  • Value Objects: Ubicacion proporciona inmutabilidad para las posiciones de butacas.
  • Domain Services: La lógica de negocio está distribuida entre las entidades apropiadas.
  • Enumerations: Los tipos como TipoButaca y TipoCandy encapsulan tanto valores como comportamiento relacionado.
graph TD
    subgraph Capa de Dominio
        subgraph Entidades Principales
            Reserva --> Cliente
            Reserva --> Butaca
            Reserva --> Sala
            Reserva --> Candy
            Pelicula
        end

        subgraph Tipos de Dominio
            Butaca --> TipoButaca
            Butaca --> Ubicacion
            Candy --> TipoCandy
            Pelicula --> FormatoPelicula
        end
    end
Loading

3. Integración con el Sistema

Esta capa se integra de manera limpia con las otras capas del sistema:

  • Servicios: cine_services.py orquesta las operaciones utilizando las entidades de dominio
  • Acceso a Datos: Los DAOs persisten y recuperan las entidades manteniendo su integridad
  • Presentación: main.py coordina el flujo de usuario a través de las capas superiores

La separación clara de responsabilidades permite que la lógica de negocio permanezca estable e independiente de cambios en la infraestructura o la presentación, facilitando el mantenimiento y la evolución del sistema.


🔑 Entidades Principales


📄 Cliente.py

1. Propósito y Responsabilidades

La entidad Cliente representa a los usuarios del sistema de cine con validaciones integradas para garantizar la integridad de los datos.

🔸 Responsabilidades principales

  • Almacenar información personal del cliente (DNI, nombre, apellido, email).
  • Validar datos de entrada según reglas de negocio.
  • Proporcionar acceso controlado a los atributos mediante getters/setters.
  • Servir como identificador único para las reservas.

2. Atributos Principales

Atributo Tipo Propósito Validación
id_cliente int Identificador único en BD Asignado automáticamente
dni str Documento de identidad Solo números, 8 dígitos
nombre str Nombre del cliente No vacío, solo letras y espacios
apellido str Apellido del cliente No vacío, solo letras y espacios
email str Correo electrónico Debe contener '@' y '.'

3. Métodos Clave con Ejemplos de Uso

🔸 Validación de DNI:

cliente = Cliente()  
try:  
    cliente.set_dni("12345678")  # Válido  
    cliente.set_dni("1234567a")  # Lanza ValueError  
except ValueError as e:  
    print(f"Error: {e}")

🔸 Validación de Nombres:

try:  
    cliente.set_nombre("Juan Carlos")  # Válido  
    cliente.set_nombre("")  # Lanza ValueError  
except ValueError as e:  
    print(f"Error: {e}")

🔸 Validación de Email:

falta esto

4. Manejo de Errores

La entidad Cliente implementa validación defensiva mediante excepciones ValueError:

  • DNI inválido: "El DNI debe contener solo números"
  • Nombre/Apellido vacío: "El nombre/apellido no puede estar vacío"
  • Email inválido: "El email no es válido"

6. Integración con Otras Entidades

classDiagram
    ServicioValidacion : +es_nombre_valido()

    class Cliente {
        - dni: str
        - nombre: str
        - apellido: str
        - email: str
    }

    class Reserva {
        - cliente: Cliente
    }

    class ClienteDAO {
        +buscar_por_dni()
    }

    ServicioValidacion --> Cliente

    Cliente "1" --o "1" Reserva : cliente
    Cliente --> ClienteDAO
Loading

🔸 Relaciones:

  • Con Reserva: Un cliente puede tener múltiples reservas.
  • Con ClienteDAO: Persistencia y recuperación de datos.
  • Con ServicioValidacion: Validación adicional de nombres.

📄 Reserva.py

1. Propósito y Responsabilidades

La entidad Reserva actúa como agregado raíz del dominio, orquestando una transacción completa de reserva de cine.

🔸 Responsabilidades principales

  • Coordinar todos los componentes de una reserva (cliente, sala, butacas, combos)
  • Calcular el precio total de la reserva
  • Generar resúmenes detallados para el cliente
  • Gestionar la fecha/hora de la reserva
  • Mantener la integridad del agregado

2. Atributos Principales

Atributo Tipo Propósito Valor por Defecto
id_reserva str Identificador único Asignado por BD
cliente Cliente Cliente que reserva Requerido
sala Sala Sala de cine Requerido
candy list[Candy] Combos seleccionados Lista vacía
butacas_asignadas list[Butaca] Butacas reservadas Lista vacía
fecha_hora datetime Timestamp de reserva datetime.now()

3. Métodos Clave con Ejemplos de Uso

🔸 Cálculo de Precio Total:

reserva = Reserva(cliente, sala, candy=[combo1, combo2], butacas_asignadas=[butaca1, butaca2])  
precio_total = reserva.calcular_precio_total()  
print(f"Total a pagar: ${precio_total}")

🔸 Generación de Resumen:

reserva.mostrar_resumen()  
# Imprime resumen detallado con:  
# - Información del cliente  
# - Butacas reservadas con precios  
# - Combos seleccionados  
# - Total a pagar

4. Manejo de Errores

La entidad Reserva implementa manejo robusto de errores:

🔸 En cálculo de precios:

  • Captura errores al obtener categoría de butacas
  • Maneja errores al acceder a precios de combos
  • Continúa el cálculo aunque falle un elemento individual

🔸 En generación de resumen:

  • Captura errores generales durante la presentación
  • Proporciona mensajes de error descriptivos

5. Integración con Otras Entidades

graph TD
    ReservaDAO --> Reserva
    CineServices --> Reserva

    subgraph Reserva - Aggregate Root
        Reserva["Reserva - Aggregate Root
        - calcular_precio_total
        - mostrar_resumen"]
    end

    Reserva --> Cliente["Cliente
    - nombre, apellido, email"]
    Reserva --> Sala["Sala
    - id_sala"]
    Reserva --> Butaca["Butaca
    - categoria, fila, columna"]
    Reserva --> Candy["Candy
    - tipo, precio"]

    Butaca --> TipoButaca
    Candy --> TipoCandy
Loading

🔸 Relaciones complejas:

  • Agregado raíz: Controla acceso a entidades relacionadas
  • Con TipoButaca: Utiliza enum para cálculo de precios
  • Con CineServices: Integración para obtener precios por categoría
  • Con ReservaDAO: Persistencia del agregado completo

6. Patrones de Diseño Implementados

🔸 Aggregate Root Pattern:

  • Reserva controla el acceso a todas las entidades relacionadas
  • Mantiene la consistencia del dominio
  • Coordina operaciones complejas entre múltiples entidades

🔸 Domain Services Integration:

  • Utiliza CineServices.obtener_precio_por_categoria() para cálculos
  • Delega validaciones específicas a servicios apropiados

La entidad Reserva demuestra cómo un agregado raíz puede coordinar múltiples entidades mientras mantiene la integridad del dominio y proporciona una interfaz cohesiva para operaciones complejas de negocio.


📄 Butaca.py

1. Propósito y Responsabilidades

La entidad Butaca representa asientos individuales de cine con seguimiento de ubicación y gestión de disponibilidad.

Responsabilidades principales:

  • Gestionar el estado de disponibilidad de cada asiento (ocupado/libre).
  • Mantener información de ubicación física (fila y columna).
  • Categorizar asientos por tipo (común o premium).
  • Proporcionar métodos para cambio de estado controlado.

2. Atributos Principales

Atributo Tipo Propósito Validación
id_butaca int Identificador único Asignado por BD
fila int Número de fila (1-12) Rango válido
columna int Número de columna (1-12) Rango válido
categoria str Tipo de butaca (común/premium) Valores predefinidos
estado bool Disponibilidad (True=ocupada, False=libre) Booleano

3. Métodos Clave con Ejemplos de Uso

🔸 Gestión de Estado:

butaca = Butaca(1, 5, 3, "premium", False)  
butaca.set_estado(True)  # Marcar como ocupada  
print(butaca.is_estado())  # True - está ocupada

🔸 Acceso a Ubicación:

fila = butaca.get_fila()      # Obtiene número de fila  
columna = butaca.get_columna()  # Obtiene número de columna  
categoria = butaca.get_categoria()  # Obtiene tipo de butaca

🔸 Representación Textual:

 def __str__(self): # texto a imprimir de la butaca seleccionada por el cliente
        return f"Categoria: {self.categoria}, Ubicacion: {self.ubicacion}, Estado: {'Ocupada' if self.estado else 'Libre'}"

4. Manejo de Errores

La entidad Butaca implementa validación básica:

  • Los métodos getter/setter proporcionan acceso controlado.
  • La representación textual maneja estados booleanos de forma legible.
  • No implementa validaciones complejas, delegando esto a la capa de servicios.

5. Integración con Otras Entidades

graph TD
    Reserva --> ButacaNode
    ButacaDAO --> ButacaNode
    CineServices --> ButacaNode

    subgraph ButacaSubgraph
        ButacaNode["Butaca
        - fila: int
        - columna: int
        - categoria: str
        - estado: bool"]
    end

    ButacaNode --> TipoButaca["TipoButaca
    COMUN/PREMIUM"]
    ButacaNode --> Ubicacion["Ubicacion
    Value Object"]
Loading

🔸 Relaciones:

  • Con TipoButaca: Determina precios según categoría.
  • Con Ubicacion: Value object para posicionamiento.
  • Con Reserva: Múltiples butacas por reserva.
  • Con ButacaDAO: Persistencia y consultas de disponibilidad.
  • Con CineServices: Visualización de matriz y selección.

📄 Pelicula.py

1. Propósito y Responsabilidades

La entidad Pelicula encapsula toda la información relacionada con las películas disponibles en el sistema de cine.

🔸 Responsabilidades principales:

  • Almacenar información completa de películas (título, director, duración, etc.)
  • Gestionar formatos de proyección (2D/3D)
  • Proporcionar métodos de acceso y modificación controlados
  • Convertir formatos de string a enumeraciones

2. Atributos Principales

Atributo Tipo Propósito Validación
id_pelicula int Identificador único Asignado por BD
nombre str Título de la película Requerido
director str Director de la película Requerido
duracion int Duración en minutos Número positivo
genero str Género cinematográfico Texto libre
idioma str Idioma de la película Texto libre
formato FormatoPelicula Formato de proyección Enum 2D/3D

3. Métodos Clave con Ejemplos de Uso

🔸 Conversión de Formato:

pelicula = Pelicula(1, "Avatar", "James Cameron", 180, "Sci-Fi", "Inglés", "3D")  
formato_enum = pelicula.convertir_formato("3D")  # Convierte string a enum

🔸 Métodos Getter/Setter:

pelicula.set_nombre("Avatar: El Camino del Agua")  
pelicula.set_duracion(192)  
print(f"Película: {pelicula.get_nombre()}, Duración: {pelicula.get_duracion()} min")

🔸 Gestión de Formato:

    def get_formato(self) -> FormatoPelicula:
        """Devuelve el formato de la película."""
        return self.formato

    def set_formato(self, formato: FormatoPelicula):
        """Establece un nuevo formato a la película."""
        self.formato = formato

4. Manejo de Errores

La entidad Pelicula implementa manejo de errores específico:

  • Formato inválido: Lanza ValueError si el formato no existe en el enum.
  • Validación de tipos: Los setters incluyen type hints para validación.
  • Conversión segura: El método convertir_formato() valida antes de convertir.

5. Integración con Otras Entidades

graph TD
    Sala --> PeliculaNode
    PeliculaDAO --> PeliculaNode
    CineServices --> PeliculaNode

    subgraph PeliculaSubgraph
        PeliculaNode["Pelicula
        - nombre: str
        - director: str
        - duracion: int
        - formato: FormatoPelicula"]
    end

    PeliculaNode --> FormatoPelicula["FormatoPelicula DOS_D/TRES_D"]
Loading

🔸 Relaciones:

  • Con FormatoPelicula: Enum para formatos de proyección con precios adicionales
  • Con Sala: Asociación película-sala para proyecciones
  • Con PeliculaDAO: Persistencia y consultas del catálogo
  • Con CineServices: Selección de películas en el flujo de reserva

6. Representación Textual

La representación __str__ proporciona una vista completa de todos los atributos de la película, útil para debugging y logging del sistema.

7. Patrones de Diseño Implementados

Encapsulación: Todos los atributos tienen métodos getter/setter dedicados. Type Safety: Integración con enums para garantizar valores válidos. Domain Validation: Validación de formatos en el nivel de dominio.

Ambas entidades (Butaca y Pelicula) demuestran principios sólidos de diseño de dominio, manteniendo la lógica de negocio encapsulada y proporcionando interfaces claras para su uso en las capas superiores del sistema.


⬆️ Volver arriba
⚠️ **GitHub.com Fallback** ⚠️