2

My system has the language of a "Contact" which is a sort of "ghost user" that we have some information on - it's validation rules are slim and it's state is largely contact information. We also have a concept of a "User" which is a fully-vetted and registered user. Think of a "User" as a fleshed out "Contact".

The lifecycle we are trying to capture is that a "Contact" will be replaced by a "User" once someone registers with that "Contact"s information.

We have other aggregate roots in the system that make reference to a "ContactId" pointing to the UUID of a "Contact". When that "Contact" registers, we'd like to use a new concept of a "User" to represent them in the domain and the "User" now has it's own "UserID" UUID.

  1. How can we keep relationships that still reference the "Contact" via a ContactID, to now reference the "User" via a UserID?
  2. Is there a fundamental problem with trying to transition my aggregate into another one?
  3. If so, how should I model this particular lifecycle of a "Contact" -> "Registered User"?
  4. If the answer is to merge the two ideas into a single aggregate root, how can I keep my domain objects being valid at all times, despite a "User" not being valid until this "Contact" actually registers?

As a side note, we are using CQRS/ES for the overall architecture.

Thanks!

Chris Tickner
  • 2,008
  • 2
  • 20
  • 24
  • 1
    I would keep using the Contact, may be find another name for it. It will get appropriate link to Authentication subdomain when user will be registered. For other aggregates/BCs it might be only partially interesting if this is a lead or actual user but if they want to know you can always include this info in the value object that you keep the Contact reference in, along with the name, for example – Alexey Zimarev Mar 26 '16 at 18:21
  • I use the term *Applicant* for users that are yet to be fully registered in one of my projects. You could also maybe use the sales term *Lead*. – Adrian Thompson Phillips Mar 29 '16 at 07:48
  • @ChrisTickner Why do you need to turn the `Contact` relationship into a `User` relationship ? Why would the referring entity care ? Do you have an example of a use case for that ? – guillaume31 Mar 29 '16 at 11:55

1 Answers1

2

What you are describing is actually not that strange since it happens all the time.

You could have a ShoppingCart that becomes a Quote that becomes an Order that becomes an Invoice.

Trying to merge concepts usually leads to pain and suffering.

I suggest keeping them separate and handling them with their own life-cycle since they may seem very closely related by they certainly do appear to be concepts distinct from each other.

There may be a clue in your 'ghost user'. That is probably an entity/AR that you are after that hasn't been properly defined. There are going to be different ways of handling that concept depending on how it is being used. It may be as simple as a value object representing wither of the two source entities.

Eben Roux
  • 12,983
  • 2
  • 27
  • 48
  • Thanks. Could it make sense to use a single AR that encapsulates both? For example an "Identity" AR that has a Value Object for the "Contact" data, and also a "User" entity if the user is registered? Or, is that adding too much into one "idea"? Remember, my main concern here is with other ARs storing UUID references to this AR. – Chris Tickner Mar 28 '16 at 11:44
  • That depends on your domain. What you are proposing doesn't sound too far fetched. For instance, an `OrderLine` could have a `OrderProduct` VO where it has the Id of the `Product` that has been ordered. But what would happen if we don't typically stock a specific item? For instance, when I'm selling a second-hand bike in my cycle shop there would be no `ProductId`; rather just a `Description` and `Price`. Perhaps something along those lines would help. Your domain experts should be able to assist here. – Eben Roux Mar 28 '16 at 12:01