ADR-002 - Abstracción de Base de Datos
ADR-002: Abstracción de Base de Datos
Sección titulada «ADR-002: Abstracción de Base de Datos»Registro de Decisión Arquitectónica para el patrón de acceso a base de datos orientado a objetos de XOOPS.
Aceptado - Patrón central desde XOOPS 2.0
Contexto
Sección titulada «Contexto»XOOPS necesitaba una estrategia de interacción de base de datos que:
- Abstraiga la sintaxis SQL específica de la base de datos
- Proporcione operaciones CRUD consistentes en todos los módulos
- Permita la desinfección y escape automático de datos
- Apoye futuros cambios de motor de base de datos
- Simplifique las operaciones comunes para los desarrolladores
Las alternativas eran:
- SQL sin procesar en todo el código
- ORM completo (Doctrine, Eloquent)
- Abstracción personalizada ligera
Diagrama de Decisión
Sección titulada «Diagrama de Decisión»graph TB subgraph "Application Layer" A[Module Code] B[Handler Methods] end
subgraph "Abstraction Layer" C[XoopsObjectHandler] D[XoopsPersistableObjectHandler] E[Criteria System] end
subgraph "Database Layer" F[XoopsDatabase] G[MySQLDatabase] H[PDO Wrapper] end
subgraph "Storage" I[(MySQL/MariaDB)] end
A --> B B --> C B --> D C --> E D --> E E --> F F --> G F --> H G --> I H --> IDecisión
Sección titulada «Decisión»Implementaremos un Patrón Handler con:
1. XoopsObject - Contenedor de Datos
Sección titulada «1. XoopsObject - Contenedor de Datos»Cada entidad de datos extiende XoopsObject:
class Item extends XoopsObject{ public function __construct() { $this->initVar('id', XOBJ_DTYPE_INT, null, false); $this->initVar('title', XOBJ_DTYPE_TXTBOX, '', true, 255); $this->initVar('content', XOBJ_DTYPE_TXTAREA, '', false); $this->initVar('status', XOBJ_DTYPE_INT, 0, false); }}2. Handler - Gestor de Operaciones
Sección titulada «2. Handler - Gestor de Operaciones»Cada objeto tiene un handler correspondiente:
class ItemHandler extends XoopsPersistableObjectHandler{ public function __construct($db) { parent::__construct($db, 'mymodule_items', Item::class, 'id', 'title'); }
// CRUD methods inherited: // - create(), get(), insert(), delete() // - getObjects(), getCount(), getAll()}3. Criteria - Constructor de Consultas
Sección titulada «3. Criteria - Constructor de Consultas»Condiciones de consultas orientadas a objetos:
$criteria = new CriteriaCompo();$criteria->add(new Criteria('status', 1));$criteria->add(new Criteria('created', time() - 86400, '>='));$criteria->setSort('created');$criteria->setOrder('DESC');$criteria->setLimit(10);
$items = $handler->getObjects($criteria);Constantes de Tipo de Dato
Sección titulada «Constantes de Tipo de Dato»// Variable types with automatic sanitizationXOBJ_DTYPE_INT // IntegerXOBJ_DTYPE_TXTBOX // Single-line text (escaped)XOBJ_DTYPE_TXTAREA // Multi-line text (escaped)XOBJ_DTYPE_EMAIL // Email validationXOBJ_DTYPE_URL // URL validationXOBJ_DTYPE_ARRAY // Serialized arrayXOBJ_DTYPE_OTHER // No processingXOBJ_DTYPE_FLOAT // Floating pointHerencia de Handler
Sección titulada «Herencia de Handler»classDiagram class XoopsObjectHandler { <<abstract>> #db: XoopsDatabase +create(): XoopsObject +get(id): XoopsObject +insert(object): bool +delete(object): bool }
class XoopsPersistableObjectHandler { +getObjects(criteria): array +getCount(criteria): int +getAll(criteria): array +deleteAll(criteria): bool +updateAll(field, value, criteria): bool }
class ItemHandler { +getPublishedItems(): array +getByCategory(catId): array }
XoopsObjectHandler <|-- XoopsPersistableObjectHandler XoopsPersistableObjectHandler <|-- ItemHandlerConsecuencias
Sección titulada «Consecuencias»Positivas
Sección titulada «Positivas»- Consistencia: Todos los módulos usan los mismos patrones
- Seguridad: El escape automático previene inyección SQL
- Simplicidad: Las operaciones comunes requieren código mínimo
- Mantenibilidad: Los cambios en la capa de base de datos no afectan los módulos
- Testeabilidad: Los handlers pueden ser simulados para pruebas
Negativas
Sección titulada «Negativas»- Rendimiento: Sobrecarga de abstracción adicional
- Complejidad: Curva de aprendizaje para nuevos desarrolladores
- Limitaciones: Las consultas complejas pueden necesitar SQL sin procesar
- Problema N+1: Sin carga anticipada incorporada
Mitigaciones
Sección titulada «Mitigaciones»- Rendimiento: Cachea objetos accedidos frecuentemente
- Consultas complejas: Permite SQL sin procesar cuando sea necesario
- N+1: Usa getAll() con criterios apropiados
Evolución a XOOPS 4.0
Sección titulada «Evolución a XOOPS 4.0»flowchart LR subgraph "Current (2.5.x)" A[XoopsDatabase] B[Handlers] C[Criteria] end
subgraph "Future (4.0.x)" D[PDO/DBAL] E[Repository Pattern] F[Query Builder] G[DI Container] end
A --> D B --> E C --> F D --> G E --> GPlanes XOOPS 4.0:
- Doctrine DBAL para abstracción de base de datos
- Patrón Repository reemplazando handlers
- Constructor de consultas para consultas complejas
- Integración completa del contenedor PSR-11
Ejemplos de Código
Sección titulada «Ejemplos de Código»CRUD Básico
Sección titulada «CRUD Básico»$helper = Helper::getInstance();$handler = $helper->getHandler('Item');
// Create$item = $handler->create();$item->setVar('title', 'New Item');$handler->insert($item);
// Read$item = $handler->get($id);$title = $item->getVar('title');
// Update$item->setVar('title', 'Updated Title');$handler->insert($item);
// Delete$handler->delete($item);Consulta Compleja
Sección titulada «Consulta Compleja»$criteria = new CriteriaCompo();$criteria->add(new Criteria('status', 'published'));$criteria->add(new Criteria('category_id', '(1,2,3)', 'IN'));$criteria->add(new Criteria('created', strtotime('-30 days'), '>='));$criteria->setSort('views');$criteria->setOrder('DESC');$criteria->setLimit(10);$criteria->setStart(0);
$items = $handler->getObjects($criteria);$total = $handler->getCount($criteria);Decisiones Relacionadas
Sección titulada «Decisiones Relacionadas»- ADR-001: Arquitectura Modular
- ADR-003: Motor de Plantillas Smarty
Referencias
Sección titulada «Referencias»- Martin Fowler - Patrones de Arquitectura de Aplicaciones Empresariales
- Conceptos de Domain-Driven Design
- Patrones Active Record vs Data Mapper
#xoops #architecture #adr #database #handler #design-decision