一个springMVC+spring+mybatis的超市订单管理系统,数据库mysql,内涵数据库文件,可直接导入运行,jdk1.8+maven。可用于毕业设计或者期末作业。
文件:590m.com/f/25127180-500471542-6db03e(访问密码:551685)
以下内容无关:
-------------------------------------------分割线---------------------------------------------
围绕DDD和ABP Framework两个核心技术,后面还会陆续发布核心构件实现、综合案例实现系列文章,敬请关注!
ABP Framework 研习社(QQ群:726299208)
ABP Framework 学习及实施DDD经验分享;示例源码、电子书共享,欢迎加入!
领域对象是DDD的核心,我们会依次分析聚合/聚合根、仓储、规约、领域服务的最佳实践和规则。内容较多,会拆分成多个章节单独展开。
本文重点讨论领域对象——聚合和聚合根的最佳实践和原则
首先我们需要一个业务场景,例子中会用到 GitHub 的一些概念,如:Issue(建议)、Repository(代码仓库)、Label(标签)和User(用户)。
下图显示了业务场景对应的聚合、聚合根、实体、值对象以及它们之间的关系。
image
Issue 聚合是由 Issue(聚合根)、Comment(实体)和 IssuelLabel(值对象)组成的集合。因为其他聚合相对简单,所以我们重点分析 Issue 聚合。
image
聚合
正如前面所讲,一个聚合是一系列对象(实体和值对象)的集合,通过聚合根将所有关联对象绑定在一起。本节将介绍与聚合相关的最佳实践和原则。
我们对聚合根和子集合实体都使用实体这个术语,除非明确写出聚合根或子集合实体。
聚合和聚合根原则
包含业务原则
实体负责实现与其自身属性相关的业务规则。
聚合根还负责其子集合实体状态管理。
聚合应该通过实现领域规则和规约来保持自身的完整性和有效性。这意味着,与数据传输对象(DTO)不同,实体具有实现业务逻辑的方法。实际上,我们应该尽可能在实体中实现业务规则。
单个单元原则
聚合及其所有子集合,作为单个单元被检索和保存。例如:如果向 Issue 添加 Comment,需要这样做:
从数据库中获取 Issue 包含所有子集合:Comments (该问题的评论列表) 和 IssueLabels (该问题的标签集合)。
在 Issue 类中调用方法添加一个新的 Comment,比如: Issue.AddCommnet(…)
作为一个单一的数据库更新操作,将 Issue(包括所有子集合)保存到数据库。
对于习惯使用 EF Core 和 关系数据的开发者来说,这看起来似乎有些奇怪。获取 Issue 的所有数据是没有必要且低效的。为什么我们不直接执行一个SQL插入命令到数据库,而不查询任何数据呢?
答案是,我们应该在代码中实现业务规则并保持数据的一致性和完整性。如果我们有一个业务规则,如:用户不能对锁定的 Issue 进行评论,我们如何不通过检索数据库中数据的情况下,检查 Issue 的锁定状态呢?所以,只有当应用程序代码中的相关对象可用时,即获取到聚合及其所有子集合数据时,我们才能执行该业务规则。
另一方面,MongoDB开发者会发现这个规则非常自然。因为在 MongoDB 中,一个聚合对象(包括子集合)被保存在数据库中的一个集合中,而在关系型数据库中,它被分布在数据库中几个表中。因此,当你得到一个聚合时,所有的子集合已经作为查询的一部分被检索出来了,不需要任何额外配置。
ABP框架有助于在您的应用程序中实现这一原则。