# Capa de Aplicación (Application Layer) ## 📋 Propósito La **Capa de Aplicación** contiene los **Use Cases** que orquestan la lógica de negocio de la aplicación. Actúa como punto de entrada coordinando el flujo entre la UI/API y la Capa de Dominio. Esta capa es el **corazón de la arquitectura limpia**, encapsulando las reglas de negocio específicas de la aplicación sin conocer detalles de implementación. ## 🎯 Responsabilidades ### ✅ QUÉ HACE - **Orquestar flujo de la aplicación**: Coordina la secuencia de operaciones necesarias para completar un caso de uso - **Coordinar llamadas entre capas**: Actúa como intermediario entre la presentación y el dominio - **Transformar datos (DTOs)**: Utiliza Data Transfer Objects para encapsular entrada/salida - **Manejar transacciones**: Coordina operaciones que deben ejecutarse de forma atómica - **Validar entrada**: Verifica que los datos de entrada sean válidos antes de procesarlos - **Gestionar cache**: Coordina estrategias de cache para optimizar rendimiento ### ❌ QUÉ NO HACE - **NO contiene lógica de negocio**: La lógica de dominio vive en la Capa de Dominio - **NO conoce detalles de implementación**: Solo depende de interfaces, nunca de implementaciones concretas - **NO accede directamente a BD**: Usa repositorios a través de interfaces - **NO maneja detalles de UI**: No conoce si la petición viene de REST, CLI o WordPress Admin ## 📁 Estructura ``` Application/ ├── UseCases/ │ ├── SaveComponent/ │ │ ├── SaveComponentUseCase.php (Orquestador) │ │ ├── SaveComponentRequest.php (DTO entrada) │ │ └── SaveComponentResponse.php (DTO salida) │ ├── GetComponent/ │ │ ├── GetComponentUseCase.php │ │ ├── GetComponentRequest.php │ │ └── GetComponentResponse.php │ ├── SyncSchema/ │ │ ├── SyncSchemaUseCase.php │ │ ├── SyncSchemaRequest.php │ │ └── SyncSchemaResponse.php │ └── DeleteComponent/ │ ├── DeleteComponentUseCase.php │ ├── DeleteComponentRequest.php │ └── DeleteComponentResponse.php └── README.md (este archivo) ``` ## 🔧 Use Cases Disponibles ### 1. SaveComponent **Propósito**: Guardar o actualizar la configuración de un componente. **Flujo**: 1. Validar datos de entrada 2. Crear/actualizar entidad Component 3. Persistir en repositorio 4. Invalidar cache 5. Retornar confirmación **Ejemplo de uso**: ```php use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentUseCase; use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentRequest; $useCase = new SaveComponentUseCase($repository, $validator, $cache); $request = new SaveComponentRequest('top_bar', [ 'background_color' => '#ffffff', 'text_color' => '#000000', 'show_logo' => true ]); $response = $useCase->execute($request); if ($response->isSuccess()) { echo "Componente guardado exitosamente"; } else { echo "Error: " . $response->getError(); } ``` ### 2. GetComponent **Propósito**: Obtener la configuración de un componente con cache-first strategy. **Flujo**: 1. Verificar cache 2. Si existe en cache → retornar 3. Si no → consultar repositorio 4. Guardar en cache 5. Retornar datos **Ejemplo de uso**: ```php use ROITheme\Shared\Application\UseCases\GetComponent\GetComponentUseCase; use ROITheme\Shared\Application\UseCases\GetComponent\GetComponentRequest; $useCase = new GetComponentUseCase($repository, $cache); $request = new GetComponentRequest('top_bar'); $response = $useCase->execute($request); if ($response->isSuccess()) { $data = $response->getData(); // Procesar datos del componente } else { echo "Error: " . $response->getError(); } ``` ### 3. SyncSchema **Propósito**: Sincronizar múltiples componentes desde un archivo JSON de schemas. **Flujo**: 1. Leer archivo JSON 2. Validar formato 3. Procesar cada componente del schema 4. Identificar cambios (agregados/actualizados/eliminados) 5. Retornar resumen de cambios **Ejemplo de uso**: ```php use ROITheme\Shared\Application\UseCases\SyncSchema\SyncSchemaUseCase; use ROITheme\Shared\Application\UseCases\SyncSchema\SyncSchemaRequest; $useCase = new SyncSchemaUseCase($componentRepo, $defaultsRepo); $request = new SyncSchemaRequest('/path/to/schemas.json'); $response = $useCase->execute($request); if ($response->isSuccess()) { echo $response->getSummary(); // Output: "Added: 2, Updated: 3, Deleted: 1" } else { foreach ($response->getErrors() as $error) { echo "Error: {$error}\n"; } } ``` ### 4. DeleteComponent **Propósito**: Eliminar un componente del sistema. **Flujo**: 1. Verificar que el componente existe 2. Eliminar de repositorio 3. Invalidar cache 4. Retornar confirmación **Ejemplo de uso**: ```php use ROITheme\Shared\Application\UseCases\DeleteComponent\DeleteComponentUseCase; use ROITheme\Shared\Application\UseCases\DeleteComponent\DeleteComponentRequest; $useCase = new DeleteComponentUseCase($repository, $cache); $request = new DeleteComponentRequest('old_component'); $response = $useCase->execute($request); if ($response->isSuccess()) { echo $response->getMessage(); } else { echo "Error: " . $response->getError(); } ``` ## 🏛️ Principios Arquitectónicos ### Regla de Dependencias ``` Application Layer ↓ (depende de) Domain Layer (solo interfaces) ↑ NO depende de Infrastructure Layer ``` La capa de aplicación **solo** puede depender de la capa de dominio, y únicamente de sus **interfaces**, nunca de implementaciones concretas. ### Dependency Inversion Principle **✅ CORRECTO**: ```php namespace ROITheme\Shared\Application\UseCases\SaveComponent; use ROITheme\Shared\Domain\Contracts\ComponentRepositoryInterface; use ROITheme\Shared\Domain\Contracts\ValidationServiceInterface; final class SaveComponentUseCase { public function __construct( private ComponentRepositoryInterface $repository, // ✅ Interfaz private ValidationServiceInterface $validator, // ✅ Interfaz private CacheServiceInterface $cache // ✅ Interfaz ) {} } ``` **❌ INCORRECTO**: ```php use ROITheme\Infrastructure\Persistence\WordPress\WordPressComponentRepository; final class SaveComponentUseCase { public function __construct( private WordPressComponentRepository $repository // ❌ Implementación concreta ) {} } ``` ### DTOs Inmutables Todos los Request y Response utilizan `readonly class` para garantizar inmutabilidad: ```php final readonly class SaveComponentRequest { public function __construct( private string $componentName, private array $data ) {} // Solo getters, sin setters public function getComponentName(): string { return $this->componentName; } } ``` ### Factory Methods en Responses Los responses utilizan factory methods para encapsular lógica de creación: ```php final readonly class SaveComponentResponse { // Constructor privado private function __construct( private bool $success, private ?string $error ) {} // Factory methods públicos public static function success(): self { return new self(true, null); } public static function failure(string $error): self { return new self(false, $error); } } ``` ## 🧪 Testing ### Estrategia de Testing Todos los Use Cases tienen tests unitarios con mocks de dependencias: ```php namespace ROITheme\Tests\Unit\Application\UseCases; use PHPUnit\Framework\TestCase; use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentUseCase; use ROITheme\Shared\Domain\Contracts\ComponentRepositoryInterface; use ROITheme\Shared\Domain\Contracts\ValidationServiceInterface; class SaveComponentUseCaseTest extends TestCase { private ComponentRepositoryInterface $repository; private ValidationServiceInterface $validator; private SaveComponentUseCase $useCase; protected function setUp(): void { $this->repository = $this->createMock(ComponentRepositoryInterface::class); $this->validator = $this->createMock(ValidationServiceInterface::class); $this->useCase = new SaveComponentUseCase( $this->repository, $this->validator, $this->cache ); } public function test_saves_component_successfully(): void { // Test implementation } } ``` ### Ubicación de Tests ``` tests/Unit/Application/UseCases/ ├── SaveComponentUseCaseTest.php ├── GetComponentUseCaseTest.php ├── SyncSchemaUseCaseTest.php └── DeleteComponentUseCaseTest.php ``` ### Cobertura Esperada - **Objetivo**: 95% - **Mínimo aceptable**: 90% ### Ejecutar Tests ```bash # Todos los tests de Application cd _planeacion/roi-theme/_testing-suite vendor/bin/phpunit tests/Unit/Application # Test específico vendor/bin/phpunit tests/Unit/Application/UseCases/SaveComponentUseCaseTest.php # Con cobertura vendor/bin/phpunit tests/Unit/Application --coverage-text # Reporte HTML de cobertura vendor/bin/phpunit tests/Unit/Application --coverage-html coverage ``` ## 🔍 Requisitos Técnicos Todos los archivos de la capa de aplicación deben cumplir: ### 1. Strict Types ```php = 90% cobertura - [ ] Sin dependencias de Infrastructure ## 🚀 Próximos Pasos Después de completar la Capa de Aplicación: 1. **Fase 6**: Infrastructure Layer (Repositorios, Adaptadores) 2. **Fase 7**: API Layer (REST Endpoints) 3. **Fase 8**: Integration Tests 4. **Fase 9**: Migración gradual del código legacy --- **Mantenedor**: ROI Theme Development Team **Última actualización**: 2025-01-19 **Versión**: 1.0.0