- eliminar carpetas vacias admin/herosection y bootstrapicons - eliminar 7 scripts legacy con credenciales hardcodeadas - eliminar formbuilder duplicado en shared/infrastructure/ui - eliminar 11 archivos .gitkeep en carpetas con contenido 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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:
- Validar datos de entrada
- Crear/actualizar entidad Component
- Persistir en repositorio
- Invalidar cache
- Retornar confirmación
Ejemplo de uso:
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:
- Verificar cache
- Si existe en cache → retornar
- Si no → consultar repositorio
- Guardar en cache
- Retornar datos
Ejemplo de uso:
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:
- Leer archivo JSON
- Validar formato
- Procesar cada componente del schema
- Identificar cambios (agregados/actualizados/eliminados)
- Retornar resumen de cambios
Ejemplo de uso:
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:
- Verificar que el componente existe
- Eliminar de repositorio
- Invalidar cache
- Retornar confirmación
Ejemplo de uso:
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:
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:
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:
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:
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:
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
# 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
declare(strict_types=1); // ✅ Obligatorio en todos los archivos
2. Namespace Correcto
namespace ROITheme\Shared\Application\UseCases\{UseCase};
Patrón: Context-First → ROITheme\Shared\Application\...
3. PHPDoc Completo
/**
* SaveComponentUseCase - Guardar/actualizar componente
*
* RESPONSABILIDAD: Orquestar guardado de componente
* ...
*
* @package ROITheme\Shared\Application\UseCases\SaveComponent
*/
final class SaveComponentUseCase
{
// ...
}
4. Type Hints Estrictos
// ✅ CORRECTO
public function execute(SaveComponentRequest $request): SaveComponentResponse
{
// ...
}
// ❌ INCORRECTO
public function execute($request) // Sin type hints
{
// ...
}
📚 Referencias
- Documentación de Fase:
_planeacion/roi-theme/_MIGRACION-CLEAN-ARCHITECTURE/Fase-05/FASE-05-PLAN-IMPLEMENTACION.md - Clean Architecture: Robert C. Martin
- Dependency Inversion Principle: SOLID Principles
✅ Checklist de Validación
Para validar que un Use Case cumple con los estándares:
- Usa
declare(strict_types=1) - Namespace correcto:
ROITheme\Shared\Application\UseCases\{UseCase} - PHPDoc completo en clase
- Solo depende de interfaces del Domain
- Request es
final readonly class - Response es
final readonly classcon factory methods - UseCase es
final class - Constructor injection de dependencias
- Método
execute()con type hints - Tests unitarios con >= 90% cobertura
- Sin dependencias de Infrastructure
🚀 Próximos Pasos
Después de completar la Capa de Aplicación:
- Fase 6: Infrastructure Layer (Repositorios, Adaptadores)
- Fase 7: API Layer (REST Endpoints)
- Fase 8: Integration Tests
- 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