防腐层防的是哪门子腐

本文转载自微信公众号「codeasy」,防腐腐作者阎华 。层防转载本文请联系codeasy公众号。防腐腐
使用了DDD(领域驱动设计)后,层防代码编写有什么不一样呢?防腐腐这个系列文章会对一些优秀的DDD实例代码进行分析,管中窥豹,层防略见数斑。防腐腐这是层防第六篇,继续以IDDD_Sample为例做分析。防腐腐
防腐层不是层防PORT/ADAPTER
防腐层(ACL)是比较容易被开发人员接受的概念,是防腐腐因为很多人会把远程调用的port/adapter理解成防腐层,虽然它们有一定的层防关系,但这种理解并不准确。防腐腐
防腐层讲的层防不是技术实现,它讲的防腐腐“知识”——虽然A上下文依赖B上下文的概念,但还是尽可能不要让B上下文里的领域概念侵入到A上下文的领域层,否则,A就被B腐化了。
在IDDD_Sample中有三个限界上下文:
身份认证上下文,亿华云计算这里的领域模型主要有“用户”、“角色”等 协作上下文,这里的的领域模型主要有“论坛”、“帖子”、“日历”、“讨论”、“作者”等 敏捷管理上下文,这里的主要领域模型是和Scrum相关的概念,比如Sprint,ProductOwner,Backlog等协作上下文和敏捷管理上下文都依赖于身份认证上下文。

这里的关键点在于虽然依赖,但在协作上下文里有“作者”等概念,但没有“用户”这个概念,虽然它们有对应关系;在敏捷管理上下文里,有“ProductOwner”、“TeamMember”等概念,但没有“用户”这个概念,虽然它们有对应关系。
另外,“用户”这个概念映射到敏捷管理上下文里,对应的是多个实体;而映射到协作上下文里是多个值对象。下面我们分别来看一下。云服务器
实体到实体的映射
一个上下文里的实体在另一个上下文里体现为一个或多个实体,这是一种很常见的做法,有点儿像我们常见的“数据集成”。
在敏捷管理上下文里,有两个实体,一个是 ProuctOwner ,一个是 TeamMember 。

在身份认证上下文里,我们给一个用户分配了 ScrumProductOwner 这个角色,会在敏捷管理上下文里生成一个 ProductOwner 实体;给一个用户分配了 ScrumTeamMember 这个角色,会在敏捷管理上下文里生成一个 TeamMember 实体。
敏捷管理上下文监听了身份认证上下文里用户分配角色的事件,是通过agilepm.port.adapter.messaging.rabbitmq.RabbitMQTeamMemberEnablerListener这个监听实现的:
@Override protected String[] listensTo() { return new String[] { "com.saasovation.identityaccess.domain.model.access.UserAssignedToRole" }; }处理逻辑如下:
@Override protected void filteredDispatch(String aType, String aTextMessage) { NotificationReader reader = new NotificationReader(aTextMessage); String roleName = reader.eventStringValue("roleName"); String username = reader.eventStringValue("username"); String emailAddress = reader.eventStringValue("emailAddress"); String firstName = reader.eventStringValue("firstName"); …… if (roleName.equals("ScrumProductOwner")) { this.teamApplicationService().enableProductOwner( new EnableProductOwnerCommand( tenantId, username, firstName, lastName, emailAddress, occurredOn)); } ……事件监听器调用应用服务生成了一个 ProductOwner ,在敏捷管理上下文的领域逻辑里,就只会理解 ProductOwner 这个概念,而不会理解用户这个概念了。
实体到值对象的映射
有时候使用值对象比使用实体更经济。比如在协作上下文里,一篇帖子有作者的概念,但这个作者在只是源码下载一个值对象。

image.png
作者是一种类型的协作者,除了身份标识,还有name、email等属性。
但在创建一篇帖子时,传给帖子创建服务的一个参数是 username ,但帖子上的Author 这个值对象是怎么构建出来的呢?
这就需要调用身份认证上下文的服务去获取user更多的信息,来构建 Author。但应用层或领域层不能直接去调用一个RPC/REST服务,这里定义了一个 CollaboratorService 接口,里面有一个 authorFrom 方法可以通过用户名来创建一个 Author 的方法。在它实现类里,调用了 UserInRoleAdapter/HttpUserInRoleAdapter ,通过HTTP远程获取了user的信息。这里要特别注意的是,CollaboratorService 和 Author 这个领域模型再同一个包下,即在 collaboration.domain.model.collaborator 这个包下。而其它的几个类都在port/adapter 包下,即 collaboration.port.adapter.service 下面。
是的,你没猜错,这里用了IoC容器实现了依赖倒置

image.png
上下文集成的两种技术手段
上面的两种映射方式正好用到了技术上两种常用的集成手段 —— 基于消息和基于API。但首先要记住的是防腐层是关于领域概念的防腐,不是关于技术的,虽然我们需要通过 port/adaper 这种技术实现来把应用层/领域层和具体的实现技术做隔离,但防腐层不等于是port/adaper。
相关文章
如何解决在苹果电脑上安装JDK路径错误问题(正确设置JDK路径,让开发环境无忧)
摘要:在使用苹果电脑进行Java开发时,经常会遇到安装JDK时路径错误的问题,这会导致开发环境无法正常配置和运行。本文将详细介绍如何解决这个问题,让您的苹果电脑顺利安装和使用JDK。...2025-11-04
干货|SpringBoot JMS(ActiveMQ)API实践应用详解
前言Active是一种开源的,实现了JMS1.1规范的,面向消息(MOM)的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。AC-tiveMQ使用Apache提供的授权,任何人都2025-11-04
在开发 web 应用程序时,性能都是必不可少的话题。对于webpack打包的单页面应用程序而言,我们可以采用很多方式来对性能进行优化,比方说 tree-shaking、模块懒加载、利用 extrens2025-11-04
前言话说Java中String是有长度限制的,听到这里很多人不禁要问,String还有长度限制?是的有,而且在JVM编译中还有规范,而且有的家人们在面试的时候也遇到了,本人就遇到过面试的时候问这个的,2025-11-04电脑日志错误8198的原因与解决方法(深入探究电脑日志错误8198的发生情况及解决办法)
摘要:电脑日志错误8198是一种常见的技术问题,经常出现在操作系统中。本文将详细介绍电脑日志错误8198的原因和解决方法,帮助读者更好地理解和解决该问题。错误8198是什么?...2025-11-04
使用Scrapy开发一个分布式爬虫?你知道最快的方法是什么吗?一分钟真的能 开发好或者修改出 一个分布式爬虫吗?话不多说,先让我们看看怎么实践,再详细聊聊细节。快速上手Step 0:首先安装 Scra2025-11-04

最新评论