0

I know there are lots of questions talking about aggregates references here. But after reading some of them I still do not get an answer.

First I will describe my business logic.

I have two Entities:

Resource which describe the resource of a computation unit, including cpu, gpu, memory, disk. Resource can be used by users.

class Resource {
  CPU cpu;
  GPU gpu;
  Memory memory;
  Disk disk;

  int totalCount; // The number of resource if limited
  boolean isAvailable; // Resource can be unavailable
  List<UserId> whiteLists; // Resource can give a white list where only limited users can use
}

Plan is a merchandise. It has a price and bind with a Resource and time.

class Plan {
  String resourceId;
  Money price;
  int hours;
}

Right now I just save resourceId in Plan to follow the DDD principle: Aggregates should reference other aggregates by Id. But here is some business logic which make it quite difficult:

  1. Plan should also follow the Resource.whiteList, it means that when a Resource is only accessful by some users then the Plan using this Resource should also follow this whiteList.
  2. Plan should not be availabe if its Resource is not available.
  3. Plan with the same Resource (but have different time) should follow some variants. For example, Plan with more time should always be expensive than the Plan with less time.

This three logic all means that Plan should always access Plan.Resource. And I think this is not just the CQRS read model's logic which only show the Plan and Resource together. It is necessary even in some Plan creation workflow.

So right now I think use Resource in Plan is quite necessary. But how to solve the conflict with the DDD principle, I just do not know how to explain this situation. Am I wrong to make them two separate aggregates? But the Plan and Resource do need to be editable separately.

Update

There are some details I did not describe well.

  1. The Plan will not be more than 100 during a very long lifecycle.
  2. The Plan and Resource can only be edited by the administrator. There is no concurrency issue there. The Plan be bought buy users but users never edit it.
  3. The Plan should always follow the whiteList in Resource, it is not acceptable that one user buy a Plan which he / she even have no rights to use the Resource.
aisensiy
  • 1,460
  • 3
  • 26
  • 42

1 Answers1

0

The principle is used to hint the boundaries of the aggregate.
You can achieve the same effect by querying for the Resource before creating the Plan.
Reading at your validation rules that doesn't solve them, how do you know if the Resource is free in a given time?
You need to check all the Plans associated to that Resource to understand it.

Now there are 2 ways to solve for those invariants:
1.
Have a single aggregate Resource that has in in it a List<Plan>, and it takes care of creating them and can guarantee 100% consistencies of invariants.
2.
Have them separated, you create a Plan through some service that does some queries to check the status of the Resource and other Plans to ensure the invariants, and then create the new aggregate.

Solution 1 is hard to scale, the more Plan associated to a single Resource, more optimization you will need to have good performance.
Solution 2 allows for inconsistencies, it can happen that concurrent operations allow for two Plan to be created at the same time, or creating a Plan for a user that is concurrently removed from the whitelist.

Solution 1, what "good performance" means? How many plans will be there?
Solution 2 how much is the probability for concurrent writes to happen? Is that error rate acceptable? Can these issues being managed after it happens?

No general right answer, it depends on your specific use case.

rascio
  • 8,968
  • 19
  • 68
  • 108
  • Thanks for your answer. So from your answer, the `Reference By Id` should be followed? I see the two solutions do not break it. – aisensiy Apr 28 '22 at 09:58
  • I see referencing the other aggregate with its id as more explicit in showing the aggregate boundary, forcing a query for the data of the Resource. – rascio Apr 28 '22 at 15:21
  • I have given some update for your questions – aisensiy Apr 29 '22 at 04:54