用亚型(DDD/CQRS)建模骨料

发布于 2025-02-04 16:36:32 字数 1057 浏览 3 评论 0原文

我有一个子域,涉及跟踪不同财务帐户类型的用户财务数据。

例如,用户可以输入其:

  • 银行帐户,
  • 信用卡,
  • 贷款,
  • 信用额度,
  • 房地产
  • 等等……

现在在每种单独类型中,都有更多的子类型。

例如,在贷款下:

  • 个人贷款,
  • 业务贷款,
  • 抵押,
  • 汽车贷款
  • 等……

他们每个人都有自己的特定不变性,具有一些独特的属性和功能,以及一些共享的属性和功能。

我一直在使用构图,为每个子类型创建一个聚合,并使用接口和辅助接口实现在聚合中共享相似的逻辑。

但是,在对所有这些不同的帐户类型进行建模时,我似乎最终会遇到数十个不同的聚合。这感觉不正确。

我已经考虑过的替代方案:

  • 贷款上具有类型属性汇总,以及基于类型的有条件逻辑。
  • 为每种类型创建不同的有限上下文:这感觉就像过度杀伤,我相信这是同一业务子域的一部分。
  • 创建基于共享功能的聚合 - 例如securedloan unscuredloan聚合
  • 在常规聚合中创建子类以保持子类型的独特功能。获得亚型特定逻辑的一些封装,并具有某些条件逻辑(例如,骨料上的条件属性)。不确定这之间的区别并只是为每个子类型

折衷创建一个单独的汇总似乎是,实现越笼统,最终将有大量的条件逻辑,以及基于子类型的条件属性。 与为每个子类型构建特定的聚集体相比,每个汇总的逻辑是简化的,但是最终在应用层中有数百个命令,其中许多基本上是同一件事,但对不同的子类型。此外,最终有数十个存储库。

感觉就像我要么在一般骨料中爆炸有条件的逻辑复杂性,要​​么如果每个子类型构建一个,则爆炸(或上下文)数量(或上下文)。

问题 - 是否有针对这种建模问题的已知模式?还是真的只是在处理上述折衷方案,找到最合适的东西?在这种情况下,我可以在决策过程中申请一些先例,因为我正在努力在上述方法之间做出决定。如果在给定的上下文中最终有数十个聚集体,是否有问题?

I have a subdomain which involves tracking user financial data across different financial account types.

For example, users can input data for their:

  • bank accounts,
  • credit cards,
  • loans,
  • lines of credit,
  • real estate,
  • and more...

Now within each individual type, there are more subtypes.

For instance, under loans:

  • personal loans,
  • business loans,
  • mortgages,
  • car loans,
  • and more...

They would each have their own particular invariants, with some unique properties and functionality, and some shared properties and functionality.

I've been approaching this using composition, creating an aggregate for each subtype, and using interfaces and helper interface implementations to share similar logic between aggregates.

However, it appears as though I'm going to end up with dozens of different aggregates when modelling all these different account types. This doesn't feel right.

Alternatives I've considered:

  • have a type property on the loan aggregate, and conditional logic based off the type.
  • create different bounded contexts for each of these types: This feels like overkill, I believe this is all part of the same business subdomain.
  • create aggregates based off shared functionality - eg SecuredLoan and UnsecuredLoan aggregates
  • creating subclasses in the general aggregates to hold the subtype's unique functionality. get some encapsulation of subtype specific logic, with some conditional logic still (eg conditional properties on the aggregate). Not really sure the difference between this and just creating a separate aggregate for each subtype

Tradeoffs seem to be, the more general the implementation, there will end up being a ton of conditional logic, and conditional properties based off the subtype.
Versus building specific aggregates for each subtype, the logic per aggregate is simplified, but there ends up being hundreds of commands in the application layer, a lot of them which are basically the same thing but to a different subtype. Additionally, there end up being dozens of repositories.

It feels like I either get an explosion of conditional logic complexity in a general aggregate, or an explosion of the number of aggregates (or contexts) if building one per subtype.

Question - is there a known pattern for dealing with this type of modelling problem? Or is it really just dealing with the above tradeoffs, and finding something which fits best? In that case, is there some precedent I can apply to the decision-making process, as I'm struggling to decide between the above approaches. And is it problematic if there end up being many dozens of aggregates within a given context?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹏雨一样淡蓝的深情 2025-02-11 16:36:32

而不是从静止的数据开始以获取汇总,而是考虑将执行哪些操作/更改(“命令”),以及这些操作的结果如何影响未来的操作,这导致了聚合想要成为什么。事件袭击风格的方法可能有助于弄清国家变化之间的这些关系。

例如,每种贷款中的每一个都可能具有AccrueInterestdrawprincipalrecord> recordpayment在余额上运行的命令(给出了可配置的速率,参数等)并且不会影响且不会受到其他命令的影响。在这种情况下,您可以拥有贷款汇总的汇总,该贷款是有利息和本金余额进行利息和付款的贷款的想法。 autoloan总体可以使用VIN 1G1234567890来管理贷款ABC123的抵押品。

Rather than starting with the data at rest to get your aggregates, consider instead what operations/changes ("commands" one might say) will be performed and how the results of those operations affect future operations is what leads to what the aggregates want to be. Event storming style approaches can be helpful for figuring out these relationships between state changes.

For instance, each of these kinds of loans might have AccrueInterest, DrawPrincipal, and RecordPayment commands which operate on the balances identically (given perhaps configurable rate parameters etc.) and which don't affect and aren't affected by other commands. In that scenario, you can have a Loan aggregate which models the idea that there's a loan with interest and principal balances on which interest accrues and payments are made. An AutoLoan aggregate might then just be managing the collateralization of Loan ABC123 with VIN 1G1234567890.

旧街凉风 2025-02-11 16:36:32

对不起,对于简单的起始答案,但是……

根据您的实际用例构建聚集体。

汇总A - 方案A

汇总B-场景B

避免为一般条件建立聚合,DDD和无处不在的语言是关于开发围绕用例的语言,聚集物和系统而不是通用目的。

通用案例具有其用例,不是必需的抗DDD;但是重点是创建然后将其抽象到一般性。

Sorry for the simple starting answer, but …

Build your aggregates based on your actual use cases.

Aggregate A - Scenario A

Aggregate B - Scenario B

Avoid building aggregates for general conditions, DDD and ubiquitous language is about developing language, aggregates and systems around the use case not general purpose.

General purpose has its use cases and isn’t necessary anti DDD; but the focus is on creating the specifics then abstracting to generality.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文