diff --git a/src/Application/Security/Models/Entities/Client.php b/src/Application/Security/Models/Entities/Client.php index e6a3725..ef0ce52 100644 --- a/src/Application/Security/Models/Entities/Client.php +++ b/src/Application/Security/Models/Entities/Client.php @@ -8,14 +8,14 @@ use Application\Security\Models\ValueObjects\ClientIdentifier; use Application\Security\Models\ValueObjects\ClientName; use Application\Security\Models\ValueObjects\ClientSecret; use Application\Security\Models\ValueObjects\Entities\ClientId; -use Shared\DDD\Model\Entity; +use Shared\DDD\Model\AggregateRoot; use Shared\DDD\Model\HasTimestampIdentifier; use Shared\Time\Utc; /** - * @implements Entity + * @implements AggregateRoot */ -final class Client implements Entity, HasTimestampIdentifier +final class Client implements AggregateRoot, HasTimestampIdentifier { private function __construct( public readonly ClientId $id, diff --git a/src/Application/Security/Models/Entities/SecurityAuditLogEntry.php b/src/Application/Security/Models/Entities/SecurityAuditLogEntry.php index 430c44b..e8236cf 100644 --- a/src/Application/Security/Models/Entities/SecurityAuditLogEntry.php +++ b/src/Application/Security/Models/Entities/SecurityAuditLogEntry.php @@ -7,13 +7,13 @@ namespace Application\Security\Models\Entities; use Application\Security\Models\ValueObjects\Entities\SecurityAuditLogDetails; use Application\Security\Models\ValueObjects\Entities\SecurityAuditLogEntryId; use Ramsey\Uuid\UuidInterface; -use Shared\DDD\Model\Entity; use Shared\DDD\Model\HasTimestampIdentifier; +use Shared\DDD\Model\ReadModel; /** - * @implements Entity + * @implements ReadModel */ -final readonly class SecurityAuditLogEntry implements Entity, HasTimestampIdentifier +final readonly class SecurityAuditLogEntry implements HasTimestampIdentifier, ReadModel { public function __construct( public SecurityAuditLogEntryId $id, diff --git a/src/Domain/Models/Entities/Brand.php b/src/Domain/Models/Entities/Brand.php index a4f98f6..9bdf1d7 100644 --- a/src/Domain/Models/Entities/Brand.php +++ b/src/Domain/Models/Entities/Brand.php @@ -9,21 +9,18 @@ use Domain\Models\ValueObjects\Brand\BrandCode; use Domain\Models\ValueObjects\Brand\BrandId; use Domain\Models\ValueObjects\Brand\BrandName; use Ramsey\Uuid\Uuid; -use Shared\DDD\Model\Entity; +use Shared\DDD\Model\AggregateRoot; use Shared\DDD\Model\HasTimestampIdentifier; -/** @implements Entity */ -final readonly class Brand implements Entity, HasTimestampIdentifier +/** @implements AggregateRoot */ +final readonly class Brand implements AggregateRoot, HasTimestampIdentifier { - public BrandId $id; - private function __construct( - BrandId $id, + public BrandId $id, public BrandName $name, public BrandCode $code, public ArcadiaId $arcadiaId, ) { - $this->id = $id; } #[\Override] diff --git a/src/Domain/Models/Entities/Employee.php b/src/Domain/Models/Entities/Employee.php index 4a8b1bb..76e377f 100644 --- a/src/Domain/Models/Entities/Employee.php +++ b/src/Domain/Models/Entities/Employee.php @@ -8,10 +8,10 @@ use Domain\Models\ValueObjects\Employees\ArcadiaEmployeeId; use Domain\Models\ValueObjects\EstablishmentCode; use Domain\Models\ValueObjects\ServiceId; use Domain\Models\ValueObjects\SiteId; -use Shared\DDD\Model\Entity; +use Shared\DDD\Model\ReadModel; -/** @implements Entity */ -final readonly class Employee implements Entity +/** @implements ReadModel */ +final readonly class Employee implements ReadModel { private function __construct( public ArcadiaEmployeeId $publicEmployeeNumber, diff --git a/src/Domain/Models/Entities/Inco/Composition/IncoComposition.php b/src/Domain/Models/Entities/Inco/Composition/IncoComposition.php index 5dd31c4..f8d53a3 100644 --- a/src/Domain/Models/Entities/Inco/Composition/IncoComposition.php +++ b/src/Domain/Models/Entities/Inco/Composition/IncoComposition.php @@ -21,10 +21,10 @@ use Domain\Models\ValueObjects\Inco\Composition\ReferenceMacronutrients; use Domain\Models\ValueObjects\Inco\Composition\SpecialCompounds; use Domain\Models\ValueObjects\Inco\Composition\Vitamins; use Domain\Models\ValueObjects\Inco\IncoId; -use Shared\DDD\Model\Entity; +use Shared\DDD\Model\ReadModel; -/** @implements Entity */ -final readonly class IncoComposition implements Entity +/** @implements ReadModel */ +final readonly class IncoComposition implements ReadModel { private function __construct( public IncoCompositionId $id, diff --git a/src/Domain/Models/Entities/Inco/IncoSheet.php b/src/Domain/Models/Entities/Inco/IncoSheet.php index 4908418..e9f343e 100644 --- a/src/Domain/Models/Entities/Inco/IncoSheet.php +++ b/src/Domain/Models/Entities/Inco/IncoSheet.php @@ -14,10 +14,10 @@ use Domain\Models\ValueObjects\Inco\Ingredients; use Domain\Models\ValueObjects\Inco\Nutriscore; use Domain\Models\ValueObjects\Inco\PortionAmount; use Domain\Models\ValueObjects\Inco\StorageCondition; -use Shared\DDD\Model\Entity; +use Shared\DDD\Model\ReadModel; -/** @implements Entity */ -final readonly class IncoSheet implements Entity +/** @implements ReadModel */ +final readonly class IncoSheet implements ReadModel { /** * @param array<\Domain\Models\ValueObjects\Inco\Allergen> $allergens diff --git a/src/Domain/Models/Entities/Inco/IncoShortSheet.php b/src/Domain/Models/Entities/Inco/IncoShortSheet.php index a0342bb..403b611 100644 --- a/src/Domain/Models/Entities/Inco/IncoShortSheet.php +++ b/src/Domain/Models/Entities/Inco/IncoShortSheet.php @@ -5,10 +5,10 @@ declare(strict_types=1); namespace Domain\Models\Entities\Inco; use Domain\Models\ValueObjects\Inco\IncoId; -use Shared\DDD\Model\Entity; +use Shared\DDD\Model\ReadModel; -/** @implements Entity */ -final readonly class IncoShortSheet implements Entity +/** @implements ReadModel */ +final readonly class IncoShortSheet implements ReadModel { private function __construct( public IncoId $id, diff --git a/src/Domain/Models/ValueObjects/Brand/ArcadiaBrand.php b/src/Domain/Models/ValueObjects/Brand/ArcadiaBrand.php index effcfb0..773eea3 100644 --- a/src/Domain/Models/ValueObjects/Brand/ArcadiaBrand.php +++ b/src/Domain/Models/ValueObjects/Brand/ArcadiaBrand.php @@ -4,11 +4,20 @@ declare(strict_types=1); namespace Domain\Models\ValueObjects\Brand; -final readonly class ArcadiaBrand +use Shared\DDD\Model\ReadModel; + +/** @implements ReadModel */ +final readonly class ArcadiaBrand implements ReadModel { public function __construct( public ArcadiaId $id, public BrandName $name, ) { } + + #[\Override] + public function id(): ArcadiaId + { + return $this->id; + } } diff --git a/src/Shared/DDD/Model/AggregateRoot.php b/src/Shared/DDD/Model/AggregateRoot.php new file mode 100644 index 0000000..63b1408 --- /dev/null +++ b/src/Shared/DDD/Model/AggregateRoot.php @@ -0,0 +1,14 @@ + + */ +interface AggregateRoot extends Entity +{ +} diff --git a/src/Shared/DDD/Model/ReadModel.php b/src/Shared/DDD/Model/ReadModel.php new file mode 100644 index 0000000..f2b8b17 --- /dev/null +++ b/src/Shared/DDD/Model/ReadModel.php @@ -0,0 +1,19 @@ + + */ +interface ReadModel extends Entity +{ +} diff --git a/src/Shared/DDD/Port/Directory.php b/src/Shared/DDD/Port/Directory.php index f5aa84a..2c03df3 100644 --- a/src/Shared/DDD/Port/Directory.php +++ b/src/Shared/DDD/Port/Directory.php @@ -5,10 +5,10 @@ declare(strict_types=1); namespace Shared\DDD\Port; /** - * @template TId - * @template TEntity + * @template TId of \Shared\DDD\Model\EntityId + * @template TReadModel of \Shared\DDD\Model\ReadModel * - * @method TEntity|null find(TId $id) + * @method TReadModel|null find(TId $id) */ interface Directory { diff --git a/src/Shared/DDD/Port/Repository.php b/src/Shared/DDD/Port/Repository.php index 4b344ee..965ffbf 100644 --- a/src/Shared/DDD/Port/Repository.php +++ b/src/Shared/DDD/Port/Repository.php @@ -6,11 +6,11 @@ namespace Shared\DDD\Port; /** * @template TId of \Shared\DDD\Model\EntityId - * @template TEntity of \Shared\DDD\Model\Entity + * @template TAggregate of \Shared\DDD\Model\AggregateRoot * - * @method TEntity|null find(TId $id) - * @method void persist(TEntity $entity) - * @method void delete(TEntity $entity) + * @method TAggregate|null find(TId $id) + * @method void persist(TAggregate $aggregate) + * @method void delete(TAggregate $aggregate) * * @throws \Shared\DDD\Exception\NotFoundException */ diff --git a/tests/Architecture/DomainTest.php b/tests/Architecture/DomainTest.php index 4bab3f6..57b20be 100644 --- a/tests/Architecture/DomainTest.php +++ b/tests/Architecture/DomainTest.php @@ -4,7 +4,9 @@ declare(strict_types=1); namespace Tests\Architecture; +use Shared\DDD\Model\AggregateRoot; use Shared\DDD\Model\Entity; +use Shared\DDD\Model\ReadModel; use Shared\DDD\Port\Directory; use Shared\DDD\Port\Repository; @@ -93,3 +95,22 @@ describe('Domain Architecture Rules', function (): void { 'view', ]); }); + +describe('AggregateRoot & ReadModel Architecture Rules', function (): void { + arch('AggregateRoot implementations are final') + ->expect(AggregateRoot::class) + ->classes() + ->toBeFinal(); + + arch('Domain AggregateRoot implementations are readonly') + ->expect('Domain\Models\Entities') + ->classes() + ->toBeReadonly(); + + arch('ReadModel implementations are final and readonly') + ->expect(ReadModel::class) + ->classes() + ->toBeFinal() + ->toBeReadonly() + ->ignoring(ReadModel::class); +});