Skip to content

Design Patterns

Este documento detalla los patrones de diseño utilizados en el microservicio Storage Manager.

  • Descripción: El Singleton Pattern asegura que una clase tenga solo una instancia y proporciona un punto de acceso global a ella. Este patrón es útil cuando se necesita exactamente un objeto para coordinar acciones en todo el sistema.

  • Componentes clave:

    1. Implementación en la capa de Infrastructure:
      • mongodb.ts: El cliente de MongoDB está implementado como un singleton para asegurar que solo se mantenga una conexión a la base de datos durante todo el ciclo de vida de la aplicación.
      let mongoClient: MongoClient
      export async function getMongoClient(): Promise<MongoClient> {
      if (mongoClient == null) {
      // Inicializar el cliente
      mongoClient = new MongoClient(appConfig.databases.mongo.url, props)
      await mongoClient.connect()
      }
      return mongoClient
      }
    2. Beneficios:
      • Asegura una única conexión a MongoDB
      • Previene el desperdicio de recursos
      • Proporciona un punto de acceso consistente
  • Descripción: El Factory Pattern proporciona una interfaz para crear objetos sin especificar sus clases concretas. Este patrón se utiliza para crear objetos basados en ciertas condiciones.

  • Componentes clave:

    1. Implementación en la capa de Infrastructure:
      • providers/services.ts: Crea instancias de servicios
      • providers/repositories.ts: Crea instancias de repositories
      • providers/usecases.ts: Crea instancias de casos de uso
    2. Ejemplo de usecases.ts:
      export function createStoreContainerUseCase(
      locationService: LocationService,
      containerService: ContainerService,
      inventoryService: InventoryService,
      utilsService: WmsUtilsService,
      repository: StorageRepository,
      idGenerator: IdGenerator,
      metricsService: MetricService,
      calendar: Calendar,
      ): StoreContainer {
      return new StoreContainer(
      locationService,
      containerService,
      inventoryService,
      utilsService,
      repository,
      idGenerator,
      metricsService,
      calendar,
      )
      }
    3. Beneficios:
      • Centraliza la creación de objetos
      • Simplifica la inyección de dependencias
      • Hace que el código sea más mantenible
  • Descripción: El Repository Pattern media entre el dominio y las capas de mapeo de datos, actuando como una colección en memoria de objetos del dominio.

  • Componentes clave:

    1. Interfaces en la capa de Domain:
      • domain/storage/repository.ts: Define la interfaz para los repositories de almacenamiento
    2. Implementación en la capa de Infrastructure:
      • infrastructure/repositories/storage/: Implementa la interfaz del repository de almacenamiento usando MongoDB
    3. Beneficios:
      • Desacopla el dominio de la lógica de acceso a datos
      • Hace que el dominio sea más testeable
      • Centraliza la lógica de acceso a datos
  • Descripción: La Dependency Injection es una técnica donde un objeto recibe otros objetos de los que depende, en lugar de crearlos internamente.

  • Componentes clave:

    1. Implementación en toda la aplicación:
      • Los casos de uso reciben sus dependencias a través de constructores
      • Los servicios reciben sus dependencias a través de constructores
      • Los controladores reciben sus dependencias a través de constructores
    2. Ejemplo de StoreContainer:
      constructor(
      private readonly locationService: LocationService,
      private readonly containerService: ContainerService,
      private readonly inventoryService: InventoryService,
      private readonly utilsService: WmsUtilsService,
      private readonly repository: StorageRepository,
      private readonly idGenerator: IdGenerator,
      private readonly metricsService: MetricService,
      private readonly calendar: Calendar,
      ) {}
    3. Beneficios:
      • Mejora la testeabilidad
      • Reduce el acoplamiento
      • Hace que el código sea más modular
  • Descripción: El Strategy Pattern define una familia de algoritmos, encapsula cada uno y los hace intercambiables. Permite que el algoritmo varíe independientemente de los clientes que lo utilizan.

  • Componentes clave:

    1. Implementación en la capa de Domain:
      • Diferentes estrategias para validar operaciones de almacenamiento basadas en tipos de ubicación y zonas
    2. Ejemplo en StoreContainer:
      if (location.type !== LocationType.Storage) {
      return Either.left(LocationNotStorageError.valueOf(location.name.value))
      }
      if (!LocationZoneStorageByContainer.includes(location.zone)) {
      return Either.left(
      LocationInvalidZoneError.valueOfContainer(location.name.value, location.zone),
      )
      }
    3. Beneficios:
      • Encapsula la lógica de validación
      • Facilita la adición de nuevas estrategias de validación
      • Mantiene el código limpio y mantenible