diyes: practical modeling of aggregates

I decided to start working on a simple example, a bank application, that shows how aggregates can be modeled using Diyes.

The aggregate I decided to model is a bank account, it will exemplify some basic concepts of aggregate modeling. First of, we create a class that inherits from AbstractAggregate

public class Account : AbstractAggregate

How we normally go about modeling aggregates is we expose methods which are the commands that can be performed on our aggregates. So in this case I decided to have an Open, a Deposit and a Withdraw method. First thing we do in these methods is checking the preconditions for their execution, if the preconditions are met, we apply an event describing what happened. So this is how the Open method looks like:

public void Open()
{
  if (IsOpen)
  {
    throw new BankAccountException("This account was already open");
  }  

  Apply(new AccountOpened());
}

In this case, the precondition is that the account isn’t already Open and after we verified that, we apply an AccountOpened event. Until here you might think that everything looks pretty normal, except for the weird apply event and that there is no state changes in the aggregate. But for each event applied, we will need a When method that changes the state accordingly to the event.

private void When(AccountOpened e)
{
  IsOpen = true;
  Balance = 0;
}

The When method is called internally by the Apply and also when the AggregateRepository is re-hydrating the loaded aggregates. This is how we can find the state of our aggregates by only looking at the events that were applied to them.

The AccountOpened aggregate contains nothing but the id of the account opened which is inherited from the Event aggregate (the event always gets the aggregate id of the aggregate in which was applied)

public class AccountOpened : Event { }

Probably you are already imagining how the Deposit method looks.

public void Deposit(int value)
{
  if(!IsOpen)
  {
    throw new BankAccountException("Trying to deposit money in an non existing account");
  }

  Apply(new DepositMade(value));
 }

And the When method for the DepositMade event.

private void When(DepositMade e)
{
  Balance = Balance + e.Value;
}

First we checked the precondition, in this case if the account actually was opened before and then we proceed to apply the DepositMade event which actually updates the Balance state of our account. The DepositMade event carries information in this case.

public class DepositMade : Event
{
  public readonly int Value;
  public DepositMade(int value)
  {
    Value = value;
  }
}

The fields used in events should always be made readonly because events should be immutable.

The Withdrawal method has a precondition that is a bit more interesting but besides that it does not differs much from the rest.

public void Withdraw(int value)
{
  IsOpenGuard();
  if (value > Balance)
  {
    throw new BankAccountException("Trying to withdraw more money than what is available");
  }
 
  Apply(new WithdrawalMade(value));
}

First we start by checking if the account actually exists (IsOpenGuard) and then we check if there is actual funds for the withdraw. We finishing by applying the WithdrawalMade event which actually withdraws the money of the account.

Conclusion

So this was a very simple introduction to how to model aggregates. In the future I will concentrate more on the CQRS pattern and why using Event Sourcing really fits the pattern. I also started working on MsSql AppendOnlyStore so that we can actually persist our events.

I also got to know that I will be participating in the GOTO Aarhus conference as a blogger and I am really excited to see Greg Young, one of the biggest advocates for Event Sourcing and CQRS.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s