领域驱动设计示例(2)

简介: 领域驱动设计示例(2)

现在我们需要将子问题空间与我们的解决方案设计对齐,我们需要形成一个解决方案空间。DDD术语中的解决方案空间也称为有界上下文,并且最好将一个问题空间/子域与一个解空间/有界上下文对齐。


构建模块


领域驱动设计的构建模块分为战术和战略模式。我写了一篇关于DDD构建块的文章,所以如果你想深入了解,请访问这篇文章。


请注意,以下架构模式和类图不依赖于技术。该解决方案可以使用Java SE / EE,C#甚至JavaScript实现。无关紧要,我们可以使用每种目标技术存档相同的好处。


新的架构总览


让我们看下新的架构


image.png


好的,这里发生了什么?现在每个已识别的子域都有有界上下文。有界上下文是孤立的,彼此一无所知。它们仅由一组常见类型粘合在一起,如UserId,ProjectId和CustomerId。在DDD中,这组常见类型称为“共享内核”。我们还可以看到什么是“核心领域”的一部分,什么不是。如果有界上下文是我们试图解决的问题的一部分,并且不能被另一个系统替换,那么它就是“核心域”的一部分。如果它可以被另一个系统替换,那么它就是“通用子域”。“身份和访问管理”上下文是“通用子域”,因为它可以由现有的IAM解决方案替换,例如Active Directory或其他。

我们将一组战术和战略模式应用于模型。这些模式有助于我们构建更好的模型,提高容错能力并提高可维护性。


在每个有界上下文中都有聚合和值对象。聚合是对象层次结构,但只能从聚合外部访问层次结构的根。聚合处理业务常量。对对象树的每次访问都必须通过Aggregate,而不是通过其中的一个元素。这大大增加了封装性。

AggregatesEntites是我们模型中具有唯一ID的东西。值对象不是事物,它们是值或度量,如UserId。值对象被设计为不可变的,它们不能改变它们的状态。每个状态更改方法都返回值Object的新实例。这有助于我们消除不必要的副作用。


设计行为


让我们设计一些行为,“Freelancer迁移到新位置”用例。在没有DDD的情况下,我们可以创建一个简单的POJO,如下所示:


image.png


我们可以通过调用实例的setter来更改Freelancer的名称。可是等等!我们的用例在哪里?可以从其他地方调用setter。实施基于角色的安全性可能会变得很麻烦。因为我们在调用setter时没有调用上下文。此外,这个模型中还缺少一个概念,即地址。它只是通过Freelancer类的简单属性以非常隐式的方式建模。

通过应用域驱动设计,我们得到以下结果:


image.png


这要好得多。现在有一个显式的Address类,它封装了整个地址状态。现在,地址更改用例显式建模为Freelancer聚合提供的moveTo()方法。我们只能使用此方法更改Freelancer状态。当然,这种方法可以通过某种安全模型轻松保护。


完整的用例和持久性


好的,我们继续模仿“自由职业者迁移到新位置”的用例。首先,我们需要为Freelancer Aggregate提供一种存储空间。DDD将这样的存储称为存储库。使用存储库,我们可以按名称搜索Freelancer,通过Id加载现有的Freelancer,从存储中删除它或向存储添加新的Freelancer。根据经验,每种类型的聚合都应该有一个存储库。请注意,存储库是业务术语中描述的接口。我们将在下一章讨论实现。


下图显示了建模的用例。你会看到一些新的工件。首先是用户界面,我们的域模型的客户端。客户端可以是一切,从JSF 2.0前端到SOAP Web服务或REST资源。所以请以一般方式考虑客户。客户端向ApplicationService发送命令。ApplicationService将命令转换为域模型用例调用。因此,FreelancerApplicationService将从FreelancerRepository加载Freelancer Aggregate,并在Freelancer Aggregate上调用moveTo()操作。FreelancerApplicationService也构成了事务边界。每次调用都会导致新的事务。基于角色的安全性也可以使用FreelancerApplicationService实现。将事务控制保留在域模型之外始终是一个很好的选择。事务控制更多是技术问题,而不是业务问题,因此不应在域模型中实现。


image.png

相关文章
|
存储 自然语言处理 前端开发
领域驱动设计(DDD)-基础思想
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。 二、领域驱动设计 DDD是什么 wiki释义:     领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂
8207 0
|
5月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1040 152
|
6月前
|
存储 SQL 关系型数据库
RDS DuckDB技术解析一:当 MySQL遇见列式存储引擎
RDS MySQL DuckDB分析实例以​列式存储与向量化计算​为核心,实现​复杂分析查询性能百倍跃升​,为企业在海量数据规模场景下提供​实时分析能力​,加速企业数据驱动型决策效能。​​
|
9月前
|
JavaScript 搜索推荐 前端开发
通义灵码2.5智能体模式联合MCP:打造自动化菜品推荐平台,实现从需求到部署的全流程创新
本项目利用通义灵码2.5的智能体模式与MCP服务,构建在线点餐推荐网站。基于Qwen3模型,实现从需求到代码生成的全流程自动化,集成“今天吃什么”和EdgeOne MCP服务,提供个性化推荐、偏好管理等功能。技术架构采用React/Vue.js前端与Node.js后端,结合MCP工具链简化开发。项目涵盖功能测试、部署及未来扩展方向,如餐厅推荐、语音交互等,展示高效开发与灵活扩展能力。
|
Java 数据库连接 API
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
1677 1
|
存储 运维 NoSQL
分布式表的写入流程
分布式表的写入流程
232 2
|
存储 SQL 分布式计算
大数据-142 - ClickHouse 集群 副本和分片 Distributed 附带案例演示
大数据-142 - ClickHouse 集群 副本和分片 Distributed 附带案例演示
1352 0
|
设计模式 Java 开发者
如何在Java项目中实现领域驱动设计(DDD)
如何在Java项目中实现领域驱动设计(DDD)