Agnostico al patron de diseño - RickContreras/telconova-supportsuite-tracking-service GitHub Wiki

  • Cambiar de proveedor sin tocar el core del sistema.

  • Escribir pruebas más fácilmente (incluso locales con MinIO).

  • Cumplir con el principio Open/Closed y la Inversión de Dependencias (SOLID).


✅ ¿Qué debes hacer?

1. Definir una interfaz común

Define una interfaz como StorageService que tenga métodos genéricos como:

public interface StorageService {
    String upload(File file, String path);
    InputStream download(String fileKey);
    void delete(String fileKey);
}

2. Implementaciones específicas en subpaquetes:

storage/
├── StorageService.java              # Interfaz común
├── model/
│   └── UploadedFile.java            # Metadata del archivo
├── s3/
│   └── S3StorageService.java
├── azure/
│   └── AzureBlobStorageService.java
├── minio/
│   └── MinioStorageService.java

Cada clase implementa la interfaz usando el SDK del proveedor correspondiente.


3. Inyección condicional por configuración

Usa @ConditionalOnProperty en cada implementación:

@Service
@ConditionalOnProperty(name = "storage.provider", havingValue = "s3")
public class S3StorageService implements StorageService {
    // implementación usando AWS SDK
}

En application.yml:

storage:
  provider: s3 # o azure, o minio

4. Usar la interfaz donde lo necesites

Por ejemplo, en EvidenciaService:

@Service
@RequiredArgsConstructor
public class EvidenciaService {
private final StorageService storageService;

public String guardarArchivo(MultipartFile archivo) {
    return storageService.upload(archivo, "avances/");
}

}


🧠 Bonus: puedes incluso usar strategy pattern explícitamente

Si algún día necesitas elegir en tiempo de ejecución el backend, podrías usar un StorageStrategyFactory.


📦 Dependencias necesarias por backend

Proveedor Dependencia Maven
AWS S3 software.amazon.awssdk:s3
Azure Blob com.azure:azure-storage-blob
MinIO io.minio:minio
⚠️ **GitHub.com Fallback** ⚠️