Skip to content

Instantly share code, notes, and snippets.

@webdevilopers
Last active March 10, 2020 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webdevilopers/1357abd0d639337d5e7e56346f64ad67 to your computer and use it in GitHub Desktop.
Save webdevilopers/1357abd0d639337d5e7e56346f64ad67 to your computer and use it in GitHub Desktop.
Domain-Driven Design - Creating aggregates and enforcing invariants spanning multiple aggregates
<?php
final class Deployment1
{
public static function with(DeploymentId $anId, EmploymentContractId $anEmploymentContractId,
DeploymentPeriod $aPeriod): Deployment
{
// No period range validation, final period was already validated and passed
}
}
final class Deployment2
{
public static function with(DeploymentId $anId, EmploymentContractId $anEmploymentContractId,
EmploymentPeriod $anEmploymentPeriod, DeploymentPeriod $aPeriod): Deployment
{
// Check range of deployment period inside employment period
}
}
final class Deployment3
{
public static function with(DeploymentId $anId, EmploymentContractReadModelInterface $anEmploymentContractReadModel,
DeploymentPeriod $aPeriod): Deployment
{
// Get employment period from read model, then do the check
// Check range of deployment period inside employment period
if (!$this->inRange($aPeriod, $anEmploymentContractReadModel->period())) {
throw new InvalidDeploymentPeriodException();
}
return new self($anId, $anEmploymentContractReadModel->id(), $aPeriod);
}
}
<?php
final class DeployEmployeeHandler
{
public function __invoke(DeployeEmployee $command): void
{
$contract = $this->contracts->ofId($command->contractId()); // Event-sourced aggregate root WRITE model
$deployment = $contract->deploy($command->deploymentId(), $command->deploymentPeriod());
$this->deployments->add($deployment); // Add to deployment event-stream
}
}
final class EmploymentContract
{
/** @var EmploymentContractId */
private $id;
/** @var EmploymentPeriod */
private $period;
public function deploy(DeploymentId $anId, DeploymentPeriod $aPeriod): Deployment1
{
// Check range of deployment period inside employment period
if (!$this->inRange($aPeriod, $this->period)) {
throw new InvalidDeploymentPeriodException();
}
return Deployment1::with($anId, $this->id, $aPeriod);
}
}
<?php
final class DeployEmployeeHandler
{
public function __invoke(DeployeEmployee $command): void
{
$contract = $this->contracts->ofId($command->contractId()); // READ model
$deployment = Deployment2::with(
$command->deploymentId(), $command->employmentContractId(),
$contract->employmentPeriod(), $command->deploymentPeriod()
);
$this->deployments->add($deployment); // Add to deployment event-stream
}
}
<?php
final class DeployEmployeeHandler
{
public function __invoke(DeployeEmployee $command): void
{
$contract = $this->contracts->ofId($command->contractId()); // READ model
$deployment = Deployment2::with(
$command->deploymentId(), $contract, $command->deploymentPeriod()
);
$this->deployments->add($deployment); // Add to deployment event-stream
}
}
@webdevilopers
Copy link
Author

Please follow the issue here:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment