我知道这里有很多关于聚合引用的问题。但读了其中一些后,我仍然没有得到答案。
首先我将描述我的业务逻辑。
我有两个实体
Resource
,表示计算单元的资源,包括cpu、gpu、内存、磁盘。Resource
可供用户使用
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
是商品。它具有价格,并与Resource
和时间绑定。
class Plan {
String resourceId;
Money price;
int hours;
}
现在我只是保存resourceId
在Plan
遵循DDD原则:Aggregates should reference other aggregates by Id
。但是这里有一些业务逻辑使它变得相当困难:
Plan
也应该遵循Resource.whiteList
,这意味着当Resource
只被一些用户访问时,使用Resource
的Plan
也应该遵循whiteList
。 如果Plan
应该遵循一些变体。例如,使用更多时间的Plan
应该总是比使用更少时间的Plan
昂贵。
Resource
不可用,则Plan
不可用。具有相同Resource
(但时间不同)的这三个逻辑都意味着Plan
应该总是访问Plan.Resource
。我认为这不仅仅是CQRS读取模型的逻辑,它只显示计划和资源在一起。甚至在一些Plan
创建工作流程中也是必要的。
所以现在我认为在Plan
中使用Resource
是非常必要的。但是如何解决与DDD原则的冲突,我只是不知道如何解释这种情况。我把它们当作两个单独的集合有错吗?但是Plan
和Resource
确实需要单独编辑。
更新有一些细节我没有描述好。
Plan
在很长的生命周期内不会超过100。Plan
和Resource
只能由管理员编辑。这里不存在并发性问题。Plan
可以购买用户,但用户从不编辑它。Plan
应该始终遵循Resource
中的whiteList
,如果一个用户购买了Plan
,他/她甚至没有权利使用Resource
,这是不可接受的。
该原则用于提示聚合的边界。
可以通过在创建计划之前查询"资源"来达到相同的效果。
查看不解决问题的验证规则,如何知道资源在给定时间内是否空闲?
您需要检查与该资源关联的所有计划以了解它。
现在有两种方法来解决这些不变量:
1。
有一个单独的聚合资源,其中有一个List<Plan>
,它负责创建它们,并可以保证不变量的100%一致性。
2。
将它们分开,通过一些服务创建一个计划,该服务执行一些查询来检查资源和其他计划的状态,以确保不变性,然后创建新的聚合。
解决方案1很难扩展,与单个资源关联的Plan越多,您将需要更多的优化以获得良好的性能。
方案2允许不一致性,可能发生并发操作允许同时创建两个Plan,或者为同时从白名单中删除的用户创建一个Plan。
解决方案1,什么"性能好";意味着什么?一共有多少个计划?
解决方案2并发写发生的概率是多少?这个错误率可以接受吗?这些问题发生后能得到管理吗?
没有一般的正确答案,这取决于你的具体用例。