Wahl eines Datenzugriffsmuster
2.5.x ✅ 4.0.x ✅
Welches Muster sollte ich verwenden? Dieser Entscheidungsbaum hilft Ihnen, zwischen direkten Handlerin, Repository-Muster, Service Layer und CQRS zu wählen.
Schneller Entscheidungsbaum
Abschnitt betitelt „Schneller Entscheidungsbaum“flowchart TD START([Start hier]) --> Q1{Wie komplex ist<br/>Ihr Modul?}
Q1 -->|Einfaches CRUD<br/>1-3 Entitäten| Q2{Testen oder<br/>Mocking erforderlich?} Q1 -->|Moderat<br/>4-10 Entitäten| Q3{Mehrere Datenquellen?} Q1 -->|Komplex<br/>10+ Entitäten| Q4{Hoher Traffic oder<br/>Read/Write-Asymmetrie?}
Q2 -->|Nein| HANDLER[✅ Direkter Handler] Q2 -->|Ja| REPO[✅ Repository-Muster]
Q3 -->|Nein, nur DB| REPO Q3 -->|Ja, APIs/Cache| SERVICE[✅ Service Layer]
Q4 -->|Nein| SERVICE Q4 -->|Ja, separate<br/>Skalierung| CQRS[✅ CQRS-Muster]
HANDLER --> DONE([Muster wählen]) REPO --> DONE SERVICE --> DONE CQRS --> DONE
style HANDLER fill:#c8e6c9,stroke:#2e7d32 style REPO fill:#bbdefb,stroke:#1565c0 style SERVICE fill:#fff9c4,stroke:#f9a825 style CQRS fill:#ffcdd2,stroke:#c62828Vergleich der Muster
Abschnitt betitelt „Vergleich der Muster“| Kriterium | Direkter Handler | Repository | Service Layer | CQRS |
|---|---|---|---|---|
| Komplexität | ⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Testbarkeit | ❌ Schwierig | ✅ Gut | ✅ Hervorragend | ✅ Hervorragend |
| Flexibilität | ❌ Niedrig | ✅ Mittel | ✅ Hoch | ✅ Sehr hoch |
| XOOPS 2.5.x | ✅ Nativ | ✅ Funktioniert | ✅ Funktioniert | ⚠️ Komplex |
| XOOPS 4.0 | ⚠️ Veraltet | ✅ Empfohlen | ✅ Empfohlen | ✅ Für Skalierung |
| Team-Größe | 1 Dev | 1-3 Devs | 2-5 Devs | 5+ Devs |
| Wartung | ❌ Höher | ✅ Moderat | ✅ Niedriger | ⚠️ Expertise erforderlich |
Wann Sie jedes Muster verwenden
Abschnitt betitelt „Wann Sie jedes Muster verwenden“✅ Direkter Handler (XoopsPersistableObjectHandler)
Abschnitt betitelt „✅ Direkter Handler (XoopsPersistableObjectHandler)“Beste für: Einfache Module, schnelle Prototypen, XOOPS-Lernen
// Einfach und direkt - gut für kleine Module$handler = xoops_getModuleHandler('article', 'news');$articles = $handler->getObjects(new Criteria('status', 1));Wählen Sie dies, wenn:
- Sie ein einfaches Modul mit 1-3 Datenbanktabellen erstellen
- Sie einen schnellen Prototyp erstellen
- Sie der einzige Entwickler sind und keine Tests benötigen
- Das Modul wird nicht bedeutend wachsen
Einschränkungen:
- Schwer zu Unit-Test (globale Abhängigkeit)
- Enge Kopplung an XOOPS-Datenbankschicht
- Geschäftslogik neigt dazu, in Controller zu fließen
✅ Repository-Muster
Abschnitt betitelt „✅ Repository-Muster“Beste für: Die meisten Module, Teams, die Testbarkeit wünschen
// Abstraktion ermöglicht Mocking für Testsinterface ArticleRepositoryInterface { public function findPublished(): array; public function save(Article $article): void;}
class XoopsArticleRepository implements ArticleRepositoryInterface { private $handler;
public function __construct() { $this->handler = xoops_getModuleHandler('article', 'news'); }
public function findPublished(): array { return $this->handler->getObjects(new Criteria('status', 1)); }}Wählen Sie dies, wenn:
- Sie Unit-Tests schreiben möchten
- Sie möglicherweise später Datenquellen ändern (DB → API)
- Mit 2+ Entwicklern arbeiten
- Module für Verteilung erstellen
Upgrade-Pfad: Dies ist das empfohlene Muster für die XOOPS 4.0-Vorbereitung.
✅ Service Layer
Abschnitt betitelt „✅ Service Layer“Beste für: Module mit komplexer Geschäftslogik
// Service koordiniert mehrere Repositories und enthält Geschäftsregelnclass ArticlePublicationService { public function __construct( private ArticleRepositoryInterface $articles, private NotificationServiceInterface $notifications, private CacheInterface $cache ) {}
public function publish(int $articleId): void { $article = $this->articles->find($articleId); $article->setStatus('published'); $article->setPublishedAt(new DateTime());
$this->articles->save($article); $this->notifications->notifySubscribers($article); $this->cache->invalidate("article:{$articleId}"); }}Wählen Sie dies, wenn:
- Operationen mehrere Datenquellen umfassen
- Geschäftsregeln komplex sind
- Sie Transaktionsverwaltung benötigen
- Mehrere Teile der App tun dasselbe
Upgrade-Pfad: Mit Repository für eine robuste Architektur kombinieren.
⚠️ CQRS (Command Query Responsibility Segregation)
Abschnitt betitelt „⚠️ CQRS (Command Query Responsibility Segregation)“Beste für: Module mit hohem Skalierungsbedarf und Read/Write-Asymmetrie
// Commands ändern Zustandclass PublishArticleCommand { public function __construct( public readonly int $articleId, public readonly int $publisherId ) {}}
// Queries lesen Zustand (können denormalisierte Read-Modelle verwenden)class GetPublishedArticlesQuery { public function __construct( public readonly int $limit = 10 ) {}}Wählen Sie dies, wenn:
- Lesevorgänge überwiegen Schreibvorgänge deutlich (100:1 oder mehr)
- Sie unterschiedliche Skalierung für Lesevorgänge vs. Schreibvorgänge benötigen
- Komplexe Berichts-/Analyseanforderungen
- Event Sourcing würde Ihrer Domäne zugute kommen
Warnung: CQRS fügt erhebliche Komplexität hinzu. Die meisten XOOPS-Module benötigen dies nicht.
Empfohlener Upgrade-Pfad
Abschnitt betitelt „Empfohlener Upgrade-Pfad“flowchart LR H0["Direkter Handler<br/>(XOOPS 2.5.x heute)"] R["Repository-Muster<br/>(Empfohlen als nächster Schritt)"] S["+ Service Layer<br/>(Wenn Komplexität wächst)"] C["+ CQRS<br/>(Nur wenn Skalierung erforderlich)"]
H0 -->|"Schritt 1"| R R -->|"Schritt 2"| S S -->|"Schritt 3<br/>(selten)"| C
style H0 fill:#ffcdd2 style R fill:#c8e6c9 style S fill:#bbdefb style C fill:#fff9c4Schritt 1: Handler in Repositories wrappen (2-4 Stunden)
Abschnitt betitelt „Schritt 1: Handler in Repositories wrappen (2-4 Stunden)“- Erstellen Sie ein Interface für Ihre Datenzugriffsanforderungen
- Implementieren Sie es unter Verwendung des vorhandenen Handlers
- Injizieren Sie das Repository statt
xoops_getModuleHandler()direkt zu aufrufen
Schritt 2: Service Layer hinzufügen, wenn nötig (1-2 Tage)
Abschnitt betitelt „Schritt 2: Service Layer hinzufügen, wenn nötig (1-2 Tage)“- Wenn Geschäftslogik in Controllern auftritt, extrahieren Sie sie in einen Service
- Service verwendet Repositories, nicht Handler direkt
- Controller werden dünn (Route → Service → Response)
Schritt 3: Erwägen Sie CQRS nur, wenn (selten)
Abschnitt betitelt „Schritt 3: Erwägen Sie CQRS nur, wenn (selten)“- Sie haben Millionen von Lesevorgängen pro Tag
- Read- und Write-Modelle unterscheiden sich erheblich
- Sie benötigen Event Sourcing für Audit-Trails
- Sie haben ein Team mit CQRS-Erfahrung
Schnellreferenzkarte
Abschnitt betitelt „Schnellreferenzkarte“| Frage | Antwort |
|---|---|
| ”Ich muss nur Daten speichern/laden” | Direkter Handler |
| ”Ich möchte Tests schreiben” | Repository-Muster |
| ”Ich habe komplexe Geschäftsregeln” | Service Layer |
| ”Ich muss Lesevorgänge separat skalieren” | CQRS |
| ”Ich bereite mich auf XOOPS 4.0 vor” | Repository + Service Layer |
Verwandte Dokumentation
Abschnitt betitelt „Verwandte Dokumentation“- Repository-Muster-Leitfaden
- Service Layer-Muster-Leitfaden
- CQRS-Muster-Leitfaden (fortgeschritten)
- Hybrid Mode Contract
#patterns #data-access #decision-tree #best-practices #xoops