0

Consider we have a BankCard Entity that is a part of Client Aggregate. Client may want to cancel her BankCard

class CancellBankCardCommandHandler
{
    public function Execute(CancelBankCardCommand $command)
    {
        $client = $this->_repository->get($command->clienId);
        $bankCard = $client->getBankCard($command->bankCardId);
        $bankCard->clientCancelsBankCard();

        $this->_repository->add($client);
    }
}

class BankCard implements Entity
{    
    // constructor and some other methods ...

    public function clientCancelsBankCard()
    {
        $this->apply(new BankCardWasCancelled($this->id);
    }
}

class Client implements AggregateRoot
{
    protected $_bankCards;

    public function getBankCard($bankCardId)
    {
       if (!array_key_exists($bankCardId, $this->_bankCards) {
           throw new DomainException('Bank card is not found!');
       }

       return $this->_bankCard[$bankCardId]);
    }        
}

Finally we have some domain repository instance which is reponsible for storing Aggregates.

class ClientRepository implements DomainRepository
{
     // methods omitted

     public function add($clientAggregate)
     {
         // here we somehow need to store BankCardWasCancelled event
         // which is a part of BankCard Entity     
     } 
}

My question is whether AggregateRoot responsible for tracking its Entities' events or not. Is it possible to get events of an Entity which is a part of an Aggregate from within its Aggregate or not?

How to actually persist the Client with all changes made to the bank card saving its consistency?

  • I'd guess that in the same way that you don't expose public properties and methods directly on your child entities in an aggregate, then you shouldn't expose events. I'd expect your aggregate root could subscribe to your child entity events, but if it wanted to expose these event, then it would do so by raising new events from the aggregate root. – Adrian Thompson Phillips Aug 08 '14 at 08:52
  • "if it wanted to expose these event, then it would do so by raising new events from the aggregate root". Do I get it correctly that in my case I have to implement a method on Client which changes BankCard? Client->cancellBankCard($cardId); If it is so, the problem is that instead of a BankCard there may be a very huge Entity which has a lot of bussiness logic, however it cannot be another AggregateRoot, because its consistency boundary completely depends on Client. – Maksim Shcherbo Aug 08 '14 at 09:02
  • 2
    On the subject of aggregate size, it does sound as though the client and bank card(s) should be linked in some way, rather than it be part of the client aggregate. – Adrian Thompson Phillips Aug 08 '14 at 11:35

1 Answers1

0

I would say the aggregate as a whole is responsible for tracking the changes that happened to it. Mechanically, that could be "distributed" among the aggregate root entity and any other entities within the aggregate or the aggregate root entity as the sole recorder or some external unit of work. Your choice, really. Don't get too hung up on the mechanics. Different languages/paradigms, different ways of implementing all this. If something happens to a child entity, just consider it a change part of the aggregate and record accordingly.

Yves Reynhout
  • 2,982
  • 17
  • 23