1

I have an aggregate called Survey - you can create a Survey, send a Survey and respond to a Survey.

I also have an aggregate called Person. They can receive a Survey and respond to a Survey. This aggregate includes demographic information that describes the Person.

I think my Survey aggregate should contain a list of people that have received the Survey. That would include the date they received it and any of their answers, if they have responded. But I feel like I don't need most of the demographic information that would normally come along with my existing Person aggregate.

I tried playing around with different concepts, like calling a send a "Delivery" and calling the employees "Recipients", but the business doesn't speak in those terms. It's just - "I create a Survey and then I send that Survey to people".

So does it make sense to create a different Person aggregate just within Survey? The action of sending a Survey to someone exists as records in the DB, along with responses to the Survey. Is this a better use case for Value Objects?

Kit
  • 20,354
  • 4
  • 60
  • 103
Nick N
  • 49
  • 5

2 Answers2

2

As soon as you use phrases like "I don't need all of the...data" or "this is like that but with a few more attributes but not these original ones" you are implicitly introducing the notion of a projection of an entity from one bounded context into another bounded context.

In your case a Person is in a different bounded context from a Person taking a survey (I will call the latter a SurveyParticipant) because even though it's the same actual person taking the survey, the focus of the two entities is different.

Here's a possible solution to your problem (expanded a bit, just for context).

enter image description here

Person is projected into the Survey Taking bounded context as a SurveyParticipant. As a bonus, Survey is really the definition of a survey, but SurveyInstance is a Survey that can be/is taken by these SurveyParticipants.

SurveyParticipant is not a Person. A SurveyParticipant is a person who is (going to) participate in completing a SurveyInstance.

Bottom line,

Can you use a simplified existing Aggregate in a different Aggregate Root

Yes. You do this by projecting the data from one aggregate to an entity in another context (at least in my proposed solution).

So does it make sense to create a different Person aggregate just within Survey?

Sort of. An aggregate can never contain another aggregate, but it can refer to one in the same bounded context. I didn't do this in this solution. The alternative, as shown, is that an aggregate can contain information from another aggregate as a projection of that other aggregate.

Kit
  • 20,354
  • 4
  • 60
  • 103
  • This is awesome, thanks. I think you and the other commenter are right - this is definitely a case of additional bounded contexts. For my application, it feels like 2 - the "admin" context or the person who is creating and sending surveys and inspecting results. And then the "participant/recipient" context where the person is taking the survey. – Nick N Feb 17 '22 at 14:21
1

This is a strategic design problem.

I think you have two Bounded Contexts here, so you should split your Person domain model between them. Person from Survey Context will contain only data and behavior you need for your Surveys. Person from other one (Marketing Context for example) covers marketing team needs.

Here is an example from Martin Fowler's blogpost about BC's enter image description here

So you're almost right with other aggregate, but it is not a simplified version, it's a separate one.

AlmostDev
  • 85
  • 1
  • 5
  • I had thought about that. It seemed like there was a Context for creating/sending a Survey. And then another for the person receiving the Survey and answering it. But my application is small, so I thought it would be overkill to split it up. Are there any patterns for separating contexts without using microservices? – Nick N Feb 16 '22 at 21:11
  • 1
    Microservices are good for separating bounded contexts, but their use is optional. You can simply separate two or more contexts in the same application using different namespaces. These are also boundaries, unfortunately, not as strong as those of microservices, but much easier to implement. – AlmostDev Feb 16 '22 at 21:37