Design Patterns
Design Patterns
Section titled “Design Patterns”Este documento detalla los patrones de diseño utilizados en el microservicio Storage Manager.
Singleton Pattern
Section titled “Singleton Pattern”-
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:
- 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: MongoClientexport async function getMongoClient(): Promise<MongoClient> {if (mongoClient == null) {// Inicializar el clientemongoClient = new MongoClient(appConfig.databases.mongo.url, props)await mongoClient.connect()}return mongoClient} - Beneficios:
- Asegura una única conexión a MongoDB
- Previene el desperdicio de recursos
- Proporciona un punto de acceso consistente
- Implementación en la capa de Infrastructure:
Factory Pattern
Section titled “Factory Pattern”-
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:
- Implementación en la capa de Infrastructure:
providers/services.ts: Crea instancias de serviciosproviders/repositories.ts: Crea instancias de repositoriesproviders/usecases.ts: Crea instancias de casos de uso
- 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,)} - Beneficios:
- Centraliza la creación de objetos
- Simplifica la inyección de dependencias
- Hace que el código sea más mantenible
- Implementación en la capa de Infrastructure:
Repository Pattern
Section titled “Repository Pattern”-
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:
- Interfaces en la capa de Domain:
domain/storage/repository.ts: Define la interfaz para los repositories de almacenamiento
- Implementación en la capa de Infrastructure:
infrastructure/repositories/storage/: Implementa la interfaz del repository de almacenamiento usando MongoDB
- 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
- Interfaces en la capa de Domain:
Dependency Injection Pattern
Section titled “Dependency Injection Pattern”-
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:
- 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
- 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,) {} - Beneficios:
- Mejora la testeabilidad
- Reduce el acoplamiento
- Hace que el código sea más modular
- Implementación en toda la aplicación:
Strategy Pattern
Section titled “Strategy Pattern”-
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:
- Implementación en la capa de Domain:
- Diferentes estrategias para validar operaciones de almacenamiento basadas en tipos de ubicación y zonas
- 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),)} - 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
- Implementación en la capa de Domain: