ADR-002 - Astrazione Database
ADR-002: Astrazione Database
Sezione intitolata “ADR-002: Astrazione Database”Record di Decisione Architettura per il pattern di accesso database orientato agli oggetti di XOOPS.
Accettato - Pattern core dal XOOPS 2.0
Contesto
Sezione intitolata “Contesto”XOOPS aveva bisogno di una strategia di interazione database che potesse:
- Astrarre la sintassi SQL specifica del database
- Fornire operazioni CRUD coerenti in tutti i moduli
- Abilitare la sanitizzazione e l’escaping automatici dei dati
- Supportare i futuri cambiamenti del motore database
- Semplificare le operazioni comuni per gli sviluppatori
Le alternative erano:
- SQL grezzo in tutto il codebase
- ORM completo (Doctrine, Eloquent)
- Astrazione personalizzata leggera
Diagramma Decisione
Sezione intitolata “Diagramma Decisione”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 --> IDecisione
Sezione intitolata “Decisione”Implementeremo un Handler Pattern con:
1. XoopsObject - Contenitore Dati
Sezione intitolata “1. XoopsObject - Contenitore Dati”Ogni entità dati estende 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 - Gestore Operazioni
Sezione intitolata “2. Handler - Gestore Operazioni”Ogni oggetto ha un handler corrispondente:
class ItemHandler extends XoopsPersistableObjectHandler{ public function __construct($db) { parent::__construct($db, 'mymodule_items', Item::class, 'id', 'title'); }
// Metodi CRUD ereditati: // - create(), get(), insert(), delete() // - getObjects(), getCount(), getAll()}3. Criteria - Query Builder
Sezione intitolata “3. Criteria - Query Builder”Condizioni query orientate agli oggetti:
$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);Costanti Tipo Dati
Sezione intitolata “Costanti Tipo Dati”// Tipi di variabile con sanitizzazione automaticaXOBJ_DTYPE_INT // IntegerXOBJ_DTYPE_TXTBOX // Testo una linea (escaped)XOBJ_DTYPE_TXTAREA // Testo multilinea (escaped)XOBJ_DTYPE_EMAIL // Validazione emailXOBJ_DTYPE_URL // Validazione URLXOBJ_DTYPE_ARRAY // Array serializzatoXOBJ_DTYPE_OTHER // Nessuna elaborazioneXOBJ_DTYPE_FLOAT // Virgola mobileEredità Handler
Sezione intitolata “Eredità 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 <|-- ItemHandlerConseguenze
Sezione intitolata “Conseguenze”Positivo
Sezione intitolata “Positivo”- Coerenza: Tutti i moduli usano lo stesso pattern
- Sicurezza: L’escaping automatico previene l’iniezione SQL
- Semplicità: Le operazioni comuni richiedono codice minimo
- Manutenibilità: I cambiamenti al livello database non influenzano i moduli
- Testabilità: I handler possono essere mock per il test
Negativo
Sezione intitolata “Negativo”- Prestazioni: Sovraccarico di astrazione extra
- Complessità: Curva di apprendimento per nuovi sviluppatori
- Limitazioni: Le query complesse possono necessitare SQL grezzo
- Problema N+1: Nessun caricamento eager incorporato
Mitigazioni
Sezione intitolata “Mitigazioni”- Prestazioni: Memorizza nella cache gli oggetti frequentemente accessibili
- Query complesse: Consenti SQL grezzo quando necessario
- N+1: Usa getAll() con criterio appropriato
Evoluzione a XOOPS 4.0
Sezione intitolata “Evoluzione 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 --> GPiani XOOPS 4.0:
- Doctrine DBAL per astrazione database
- Pattern Repository che sostituisce i handler
- Query builder per query complesse
- Integrazione contenitore PSR-11 completa
Esempi di Codice
Sezione intitolata “Esempi di Codice”CRUD Base
Sezione intitolata “CRUD Base”$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);Query Complessa
Sezione intitolata “Query Complessa”$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);Decisioni Correlate
Sezione intitolata “Decisioni Correlate”- ADR-001: Architettura Modulare
- ADR-003: Motore Template Smarty
Riferimenti
Sezione intitolata “Riferimenti”- Martin Fowler - Patterns of Enterprise Application Architecture
- Concetti Domain-Driven Design
- Pattern Active Record vs Data Mapper
#xoops #architecture #adr #database #handler #design-decision