领域驱动设计示例(2)

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

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


构建模块


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


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


新的架构总览


让我们看下新的架构


image.png


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

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


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

Aggregates和Entites是我们模型中具有唯一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

相关文章
|
消息中间件 缓存 前端开发
COLA架构 入门
COLA架构 入门
5008 0
|
存储 自然语言处理 前端开发
领域驱动设计(DDD)-基础思想
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。 二、领域驱动设计 DDD是什么 wiki释义:     领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂
8951 0
|
设计模式 Java 开发者
如何在Java项目中实现领域驱动设计(DDD)
如何在Java项目中实现领域驱动设计(DDD)
1156 3
|
存储 SQL 分布式计算
大数据-142 - ClickHouse 集群 副本和分片 Distributed 附带案例演示
大数据-142 - ClickHouse 集群 副本和分片 Distributed 附带案例演示
1811 0
|
前端开发 小程序 Java
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
本文详细介绍了如何在SpringBoot项目中统一处理接口返回结果及全局异常。首先,通过封装`ResponseResult`类,实现了接口返回结果的规范化,包括状态码、状态信息、返回信息和数据等字段,提供了多种成功和失败的返回方法。其次,利用`@RestControllerAdvice`和`@ExceptionHandler`注解配置全局异常处理,捕获并友好地处理各种异常信息。
8701 1
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
|
Java Linux Windows
windows版java版本管理器
本文介绍了如何在Windows上使用JDK版本管理器jvms来管理多个Java版本,包括下载、初始化、列出本地安装的JDK版本、在线查看可用版本、切换和安装特定版本的Java。
4961 0
windows版java版本管理器