Enhed af arbejdsmønster
Oversigt
Sektion kaldt “Oversigt”Arbejdsenhedsmønsteret vedligeholder en liste over objekter, der er påvirket af en forretningstransaktion, og koordinerer udskrivning af ændringer. Det sikrer, at alle relaterede ændringer forpligtes sammen eller rulles tilbage ved fejl.
Formål
Sektion kaldt “Formål”- Transaktionsstyring - Koncernrelaterede operationer
- Skift sporing - Spor modificerede enheder
- Batch Operations - Optimer databaseskrivning
- Konsistens - Sikre dataintegritet
Implementering
Sektion kaldt “Implementering”Unit of Work Interface
Sektion kaldt “Unit of Work Interface”<?php
declare(strict_types=1);
namespace XoopsModules\MyModule\Infrastructure;
interface UnitOfWorkInterface{ public function begin(): void; public function commit(): void; public function rollback(): void; public function registerNew(object $entity): void; public function registerDirty(object $entity): void; public function registerDeleted(object $entity): void;}Grundlæggende implementering
Sektion kaldt “Grundlæggende implementering”<?php
declare(strict_types=1);
namespace XoopsModules\MyModule\Infrastructure;
final class UnitOfWork implements UnitOfWorkInterface{ private array $newEntities = []; private array $dirtyEntities = []; private array $deletedEntities = []; private bool $inTransaction = false;
public function __construct( private readonly \XoopsDatabase $db, private readonly EntityMapperRegistry $mappers ) {}
public function begin(): void { if ($this->inTransaction) { throw new \RuntimeException('Transaction already started'); }
$this->db->query('START TRANSACTION'); $this->inTransaction = true; }
public function commit(): void { if (!$this->inTransaction) { throw new \RuntimeException('No transaction in progress'); }
try { $this->insertNew(); $this->updateDirty(); $this->deleteRemoved();
$this->db->query('COMMIT'); $this->clear(); } catch (\Exception $e) { $this->rollback(); throw $e; } }
public function rollback(): void { if ($this->inTransaction) { $this->db->query('ROLLBACK'); $this->clear(); } }
public function registerNew(object $entity): void { $id = spl_object_id($entity); $this->newEntities[$id] = $entity; }
public function registerDirty(object $entity): void { $id = spl_object_id($entity); if (!isset($this->newEntities[$id])) { $this->dirtyEntities[$id] = $entity; } }
public function registerDeleted(object $entity): void { $id = spl_object_id($entity); unset($this->newEntities[$id], $this->dirtyEntities[$id]); $this->deletedEntities[$id] = $entity; }
private function insertNew(): void { foreach ($this->newEntities as $entity) { $mapper = $this->mappers->getMapper($entity::class); $mapper->insert($entity); } }
private function updateDirty(): void { foreach ($this->dirtyEntities as $entity) { $mapper = $this->mappers->getMapper($entity::class); $mapper->update($entity); } }
private function deleteRemoved(): void { foreach ($this->deletedEntities as $entity) { $mapper = $this->mappers->getMapper($entity::class); $mapper->delete($entity); } }
private function clear(): void { $this->newEntities = []; $this->dirtyEntities = []; $this->deletedEntities = []; $this->inTransaction = false; }}Brug i tjenester
Sektion kaldt “Brug i tjenester”final class ArticleService{ public function __construct( private readonly UnitOfWorkInterface $unitOfWork, private readonly ArticleRepository $articles, private readonly CommentRepository $comments ) {}
public function publishWithComments( Article $article, array $comments ): void { $this->unitOfWork->begin();
try { // Mark article as modified $article->publish(); $this->unitOfWork->registerDirty($article);
// Add new comments foreach ($comments as $comment) { $this->unitOfWork->registerNew($comment); }
// Commit all changes together $this->unitOfWork->commit();
} catch (\Exception $e) { $this->unitOfWork->rollback(); throw $e; } }}Med Repository Integration
Sektion kaldt “Med Repository Integration”final class ArticleRepository implements ArticleRepositoryInterface{ public function __construct( private readonly UnitOfWorkInterface $unitOfWork, private readonly ArticleMapper $mapper ) {}
public function add(Article $article): void { $this->unitOfWork->registerNew($article); }
public function update(Article $article): void { $this->unitOfWork->registerDirty($article); }
public function remove(Article $article): void { $this->unitOfWork->registerDeleted($article); }
public function findById(ArticleId $id): ?Article { return $this->mapper->findById($id); }}Bedste praksis
Sektion kaldt “Bedste praksis”- Korte transaktioner - Hold transaktioner korte
- Enkelt ansvar - Én arbejdsenhed pr. forretningsdrift
- Tydelige grænser - Definer transaktionsomfang klart
- Fejlhåndtering - Håndter altid scenarier med tilbagerulning
- Undgå indlejret - Indlejr ikke arbejdsenheder
Relateret dokumentation
Sektion kaldt “Relateret dokumentation”- Repository-Layer - Repository mønster
- Service-Layer - Servicemønster
- ../Database/Database-Schema - Databaseoperationer
- Domæne-model - Domæne-enheder