I am looking at a scenario for creating an aggregate instance from a trigger an a different aggregate.
I've incorporated some logic in my DDD
and Event Sourcing
with Onion architecture
learning scenario around User Registration and creation of a User Account.
Currently I have a simple Registration class instance which has a number of attributes around Email Address and Name. This currently has a single method named Activate.
When the Registration is activated, an Account should be created.
Internally, I am recording events on the various actions.
public partial class NewRegistration : EventSourcedAggregate
{
internal NewRegistration(
string organisationName,
AccountContact contact)
{
OrganisationName = organisationName ?? throw new ArgumentNullException(nameof(organisationName));
Contact = contact ?? throw new ArgumentNullException(nameof(contact));
RequestedDate = SystemClock.Current.GetCurrentUtcDateTime();
Apply(new RegistrationCreated(
OrganisationName,
Contact.EmailAddress.ToString(),
Contact.Name.GivenName,
Contact.Name.FamilyName,
RequestedDate));
}
NewRegistration(Guid id, int version)
: base(id, version)
{
}
public string OrganisationName { get; private set; }
public AccountContact Contact { get; private set; }
public string ActivationCode { get; private set; }
public DateTime RequestedDate { get; private set; }
public DateTime? ActivatedDate { get; private set; }
public void ChangeActivationCode(string activationCode)
{
if (ActivatedDate.HasValue) throw new InvalidOperationException("The registration has already been activated");
if (activationCode != ActivationCode)
{
Apply(new ActivationCodeChanged(activationCode));
}
}
public void Activate()
{
Apply(new RegistrationActivatedEvent(SystemClock.Current.GetCurrentUtcDateTime()));
}
protected sealed override void Apply(DomainEvent changes)
{
When((dynamic)changes);
}
private void When(ActivationCodeChanged activationCodeChanged)
{
ActivationCode = activationCodeChanged.ActivationCode;
}
private void When(RegistrationActivatedEvent registrationActivatedEvent)
{
ActivatedDate = registrationActivatedEvent.ActivationDate;
}
}
Although the above is stored in a SQL table, it does not fully realise Event Sourcing - as it will only ever have a single record that will only get updated should the user reset the activation code.
So when Registration is activated, I need to created a new instance of Account. I currently see Registration and Account as part of the Customers bounded context
. I feel Registration and Accounts are two separate domains
/sub-domains
within the context - I might be wrong! I was also feeling the account could be an Event sourced aggregate
, although reading Udi Dahans blog post on when not to use CQRS I feel a little disappointed with what I was planning.
Now there are a number of ways to implement this. My first thought was to simply handle this in an Application Service
. Typically I would put that logic here as they coordinate things. This would require the INewRegistrationRepository
and IAccountRepository
injected - to copy the information from one to the other.
We've been using a lot of application services at work and I have become bogged down in the number we have due to the way our business logic is (static managers, helpers, infrastructure mixed in with anaemic domain model.
But having been reading a little on Process Managers and Sagas, I which has confused me somewhat and halted my thoughts for the day.
I am all for keeping things simple, and this is a simple part of a domain implementation I am looking at. I feel a bit overcome with Application Services - is the domain Process Manager or Saga a better fit for this scenario.
How do DDD practitioners on here look at implementing such a scenario?