Lewati ke konten

ADR-002 - Abstraksi Basis Data

Catatan Keputusan Arsitektur untuk pola akses database berorientasi objek XOOPS.


Diterima - Pola core sejak XOOPS 2.0


XOOPS memerlukan strategi interaksi database yang akan:

  1. Abstrak sintaks SQL khusus database
  2. Menyediakan operasi CRUD yang konsisten di semua module
  3. Aktifkan sanitasi dan pelolosan data otomatis
  4. Mendukung perubahan mesin database di masa depan
  5. Menyederhanakan operasi umum bagi pengembang

Alternatifnya adalah:

  • SQL mentah di seluruh basis kode
  • ORM Lengkap (Doktrin, Fasih)
  • Abstraksi ringan khusus

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 --> I

Kami akan menerapkan Pola handler dengan:

Setiap entitas data memperluas 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);
}
}

Setiap objek memiliki pengendali yang sesuai:

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()
}

Kondisi kueri berorientasi objek:

$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);

// Variable types with automatic sanitization
XOBJ_DTYPE_INT // Integer
XOBJ_DTYPE_TXTBOX // Single-line text (escaped)
XOBJ_DTYPE_TXTAREA // Multi-line text (escaped)
XOBJ_DTYPE_EMAIL // Email validation
XOBJ_DTYPE_URL // URL validation
XOBJ_DTYPE_ARRAY // Serialized array
XOBJ_DTYPE_OTHER // No processing
XOBJ_DTYPE_FLOAT // Floating point

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 <|-- ItemHandler

  1. Konsistensi: Semua module menggunakan pola yang sama
  2. Keamanan: Escape otomatis mencegah injeksi SQL
  3. Kesederhanaan: Operasi umum memerlukan kode minimal
  4. Kemampuan Pemeliharaan: Perubahan pada lapisan database tidak memengaruhi module
  5. Testabilitas: handler dapat diejek untuk pengujian
  1. Kinerja: Overhead abstraksi ekstra
  2. Kompleksitas: Kurva pembelajaran untuk pengembang baru
  3. Keterbatasan: Kueri kompleks mungkin memerlukan SQL mentah
  4. Masalah N+1: Tidak ada pemuatan bersemangat bawaan
  • Kinerja: Menyimpan objek yang sering diakses dalam cache
  • Kueri kompleks: Izinkan SQL mentah bila diperlukan
  • N+1: Gunakan getAll() dengan kriteria yang sesuai

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 --> G

Paket XOOPS 4.0:

  • Doktrin DBAL untuk abstraksi database
  • Pola repositori menggantikan handler
  • Pembuat kueri untuk kueri kompleks
  • Integrasi kontainer PSR-11 penuh

$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);
$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);

  • ADR-001: Arsitektur Modular
  • ADR-003: Mesin template Smarty

  • Martin Fowler - Pola Arsitektur Aplikasi Perusahaan
  • Konsep Desain Berbasis Domain
  • Pola Catatan Aktif vs Pemeta Data

#xoops #architecture #adr #database #handler #design-decision