I am trying to use Domain-Driven Design in my project. In the project, a seller can create a Post to sell Items. A seller can include multiple items in a post; each item includes details such as quantity, size, and price. A buyer can buy one or many item of the same post.
I am not sure if Post or Item should be the aggregate. I personally feel that it would be more correct for Item to be the aggregate, but I am not entirely sure.
A book I am reading states: "An aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes". Say, post X includes two items, a and b. When a buyer buys item a, we should not lock item b even though it also belongs to Post X, so it makes sense to choose Item to be the aggregate.
However, how about entity Post? If I make Item to be the aggregate, Post would not belong to any aggregate? What would the entrypoint be if a seller wants to create/delete a post or change items in a post? so it kinda makes sense to choose Post to be the aggregate too.
Thank you sooo much in advance for your help!
It seems like Post and Item are each good aggregates.
As a meme on social media asks: "Why not both?"
Note that doing this implies that a Post won't contain Items; instead, a Post will refer to Items by some identifier (which identifier would effectively be a value object).
This also suggests that one shouldn't depend on updates to Posts and Items being mutually consistent: you may need to resort to modeling an explicit process in your domain for disabling/deleting an Item and removing that Item from associated Posts, for instance.
Related
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?
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).
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.
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
So you're almost right with other aggregate, but it is not a simplified version, it's a separate one.
What to do with an object that has two dependencies:
Let's say we have three objects: client, company and a contract.
Contract needs a client and a company to exist.
Naturally, business wise, the contract belongs more to the client than it does to the company, however the companies provides the contract to the client.
For now, I have all three as a separate aggregate root. Because you should be able to quickly query the existing contracts for a specific company as well. If contract would be an entity under the client aggregate root, I'd need to query all the clients which have a contract of X company and then return a flattened list of those contracts. Which seemed a bit odd?
Secondly, contract itself has a lot of entities, with more entities below them.
To explain the hierarchy in a simple way:
Contract aggregates contains a list of entity A, entity A has multiple items of entity B and entity B has multiple items of entity C. So it's a deep structure, which all have to be exposed through the aggregate above it.
If I'd put the contract aggregate root as an entity below client, my client aggregate needs to carry all those extra methods for what's below contract as well. And soon I'll end up with almost everything under the same aggregate.
So my question is: what questions can I ask myself to answer this kind of issue? There's probably no right or wrong, but there should be some guidelines on how to deal with an issue like this?
Thanks!
what questions can I ask myself to answer this kind of issue?
Here is how Eric Evans defined AGGREGATE
An aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes.
"Change" is the important idea here; in designing our aggregate boundaries, we don't particularly care about data that appears in the same report (read-only view), we care instead about what data needs be to considered when making changes.
See also Mauro Servienti: All our aggregates are wrong.
I've written a script to make a cafeteria system at college. I need to know whether my diagram is correct, especially the shares of the operations.
The student selects one of the restaurants available in the cafeteria.
The student selects the item you want with the possibility of adding some ingredients to the item and receive the sellers.
The student pays to the seller. The delivery of a request is included, an update to the store at the moment the student is paid.
The seller's issue the invoice to the student and includes an addition to the account of exports and imports of the restaurant.
Administrator for the restaurant When you want to add new item, the sellers are notified of the new item added.
Administrator records attendance and absence of sellers.
Use correct naming for use cases: predicate, subject (, object).
Do not use include/extend as it's simply mistaken for functional decomposition, which is plain wrong.
Synthesize function descriptions to extract the added value hidden behind those descriptions and make them use cases (single added values the system under consideration delivers to its actors).
It's ok to indicate primary and secondary actors by using directed associations. However, this in no standard, but a convention and needs to be explained in separate modeling rules.
Your saller should likely be Seller. Note the upper case first char too (also wrong with Student).
With little effort your diagram could have been uncluttered!
I'm working on a side project to learn and apply DDD within the "Daily Deal' domain. In my purchasing context, i have an invariant where a user can only purchase 'x' amount of deals per deal.
so it seems wasteful for my deal aggregate to load all purchases from all users just to check and see how many times (if any) the user has purchased this deal. I see two ways i could go about this.
Put this logic within a domain service which would allow a pre-condition to already have been met when the Purchase method on the Deal aggregate is invoked.
My repository implementation could always populate the purchases collection of the deal for the purchasing user. hmm...not sure about this one.
any guidance would be great!
I would take the second approach, but with one important change. I would instead create a value object called PurchasedDeal, that consists of just a DealID and Quantity field. The User aggregate could instead load a collection of this more lightweight purchase history object. Performance should be good with this approach, since I'm guessing that the average user will only have a few dozen purchase records.
Also remember that with DDD, you can and probably should have different models per bounded context. So you might design your User aggregate like this in the context of deals/purchasing. However, your User aggregate in another context would look different and not have a purchase history if it's not needed.
I'm facing a typical DDD problem. It must be very basic. I have an order and customer.
A customer can create multiple orders. Customer is the root of its own aggregate. Order is the root of its own aggregate. But when a customer creates an order, we display some portion of the customer information on the order. Should Order aggregate hold reference to customer?
When it holds it then when the Order Repository gets the order, we are able to retrieve some portion of customer information as well for display. But when we involve the order in a transaction, customer also gets into it which is creating problem if the customer is also getting updated at the same time. Please advise guys ! My gut feeling says I MUST not hold reference to customer from order.
Question 2: (NEW)
Can I get and hold a reference to the Customer (from Customer Repository) for a given Order while creating an Order (using Order Factory) and safely save the Order (without updating the Customer inside in anyway, Customer is there only for information/query?) without creating contention if the same Customer is getting modified else where? Lets assume NHibernate as ORM.
A simple answer will be that you hold the ID of the customer or, if needed for your domain some ValueObject with a minimal set of information about the customer ( ID, Name ).
A more complex answer is to think about Bounded Context. See Eric Evans's presentation where he wishes he had put the BC chapter as the first chapter in the book.
The idea is that in your Customer Management Bounded Context, your Customer entity can be the AR of the Customer Aggregate and the Orders can be entities in the Customer Aggregate. In the Billing Bounded Context you can have an Order AR with a Customer entity inside.