域驱动设计 - 从UI增量保存

问题描述 投票:-1回答:1

我是DDD的新手,阅读有关它的文献,但在应用一些概念方面遇到了麻烦。我正在展示我正在构建的应用程序的简化视图。这是一个住房贷款申请系统。 UI有向导收集信息的步骤,如步骤1是收集申请人信息,第2步是收集财产信息,第3步是捕获批准或拒绝的决定。在步骤1中为每个应用程序分配一个唯一ID。我的挑战是如何为每个步骤建模增量保存。贷款申请是我的集合根。从我读到的,每个根只有一个存储库,整个根必须保存在一起,以便它是有效的。但是UI会逐步收集信息,并且在每个步骤中,应用程序实体都是有效的 - 当我从步骤1保存数据时,我的贷款申请对象是有效的。保存步骤2中的数据后,贷款申请对象仍然有效。在这里寻找关于如何设计Api和存储库的一些建议?如果agg root在每一步都有效并且可以小步骤保存,那么一个save api暴露的意义何在?是否应该有3个单独的Api暴露给UI,这3个api调用3个独立的repo类或1个api在一个repo上调用3个单独的方法?我正在使用实体框架来保存到db。谢谢。

domain-driven-design
1个回答
0
投票

应用程序的要求以及对此进行建模的方式将影响您的操作方式。

(注意:我将使用AR作为聚合根)

在您的情况下,如果您有贷款申请AT,则需要包含有关申请人和财产的信息。

假设每个申请人都有一个类似于独特账户的东西,因此您可以跟踪申请人有多少贷款。

在这种情况下,申请人将是一个实体,可能是一个AR。它将拥有自己的存储库:ApplicantRepository。在这种情况下,申请人AR需要从您的LoanApplication AR中引用。

这意味着在向导的第一步中,您可以使用ApplicantRepository搜索申请人或创建新申请人。如果要创建新的,您可以在第一步中创建并保存它。稍后您可以从LoanApplication中引用申请人(通过引用或ID)

如果您不希望这样,那么Applicant可以是值对象,它的信息将存储在LoadApplication AR中。

同样的事情适用于Property:您既可以拥有PropertyRepository的Property Entity,也可以将PropertyInfo值对象存储到LoadApplication AR。

另一个重要的事情是你LoanApplication有一个生命周期。根据它的当前状态,它的不变量可能会改变。拥有将经历不同阶段的AR是可以的。以网上商店为例。当您从亚马逊订购某些东西时,您的订单可以是批准或待定(或在其他州),这是其生命周期的一部分。如果您想完成订单系统,它可能会在提交之前询问您的付款详情。

在你的ca中,你可以通过状态:Pending,SubmittedForApproval,Approved,Rejected等为LoadApplication创建一个生命周期。它可能还需要有关它被拒绝等原因的其他信息。

如果要保存有关创建LoadApplication的过程的信息,可以指定一个Status,表示LoadApplication仍在创建过程中:Pending或InProgress。这样,如果您的应用程序在中间崩溃,它可以通过获取LoadApplication并检查其状态来恢复。

您可以在LoadApplication AR中添加与其状态相关的行为(例如,如果它不处于SubmittedForApproval状态,则不允许转换为Approved状态,如果不处于InProgress状态,则不允许更改属性(您不想更改状态为Approved或SubmittedForApproval时的属性或申请人)。

实施保存:

如果您已确定LoadApplication Aggregate将包含三个实体:LoadApplication,Applicant和Property,则所有这些实体都将保存并加载在一起,因为聚合是事务边界。本指南可以帮助实现Save,但这可能很棘手。

这取决于几个因素:

  • 你的数据库是什么(SQL,MongoDB)?
  • 您使用的是框架(NHibernate,Mongoose)还是使用本机API(使用原始SQL)?

由于只有LoadApplicationRepository将使用Applicant和Property保存LoadApplication,因此即使申请人再次保存到DB也没有问题,因为它不会对其进行任何更改。您只会使用相同的数据覆盖现有数据,而不是性能太酷,但这不是您的逻辑问题。

另一方面,如果您使用ORM,他们可以检测对象中的更改,并仅生成所需的查询以仅更新对数据库的新更改。在这种情况下,如果您说添加一个属性到LoadApplication,如果将选择它并仅更新数据库中的属性。

例如,假设您正在使用带有(N)Hibernate或EntityFramewok的SQL数据库,您的ORM将跟踪添加了Property的更改并生成SQL以将其插入到DB中的Properties表中,但不会生成已更新的插入现有申请人因为没有变更。

如果您使用例如原始SQL编写自己的逻辑,那么您将必须编写自己跟踪更改的逻辑。

一种方法是在LoanApplicaton AR中添加包含更改/事件(ApplicantAssigned,PropertyAssigned,SomethingChanged等)的更改集合,以便您可以在Save方法中使用它们来根据更改生成SQL。保存聚合时,您可以清除更改。

这是关于建模聚合的一篇很棒的文章:http://dddcommunity.org/library/vernon_2011/

以下是关于域名事件的两对:https://www.martinfowler.com/eaaDev/DomainEvent.html https://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/

© www.soinside.com 2019 - 2024. All rights reserved.