当前位置: 首页 > 科技观察

防腐层防的是哪门子腐

时间:2023-03-21 19:05:22 科技观察

防腐层防止什么样的腐败?转载本文请联系codeeasy公众号。使用DDD(领域驱动设计)后,代码写法有什么不同?本系列文章会分析一些优秀的DDD示例代码,看管中的几个点。这是第六篇,继续以IDDD_Sample为例进行分析。防腐层不是PORT/ADAPTER防腐层(ACL)是一个比较容易被开发者接受的概念,因为很多人会把远程调用端口/适配器理解为防腐层。虽然他们有一定的关系,但这种理解并不准确。防腐层不是技术实现,而是“知识”——虽然A上下文依赖于B上下文的概念,但还是可以不让B上下文中的领域概念侵入到领域层的A上下文,否则,A将被阻塞。B已损坏。IDDD_Sample中有3个限界上下文:身份认证上下文,这里的领域模型主要包括“用户”、“角色”等协作上下文,这里的领域模型主要包括“论坛”、“帖子”、“日历”、“讨论”、“Author”等敏捷管理上下文,这里主要的领域模型是Scrum相关的概念,比如Sprint、ProductOwner、Backlog等协作上下文和敏捷管理上下文都依赖于身份认证上下文。这里的关键点在于,虽然有依赖关系,但协作上下文中有“作者”等概念,但没有“用户”的概念,虽然它们有对应关系;在敏捷管理的语境中,有“ProductOwner”、“TeamMember”等概念,但是没有“用户”的概念,虽然他们有对应关系。另外,将“用户”的概念映射到敏捷管理上下文中,对应多个实体;并映射到协作上下文的是多个值对象。让我们来看看它们中的每一个。实体到实体映射一个上下文中的实体表示为另一个上下文中的一个或多个实体。这是一种很常见的做法,有点像我们常见的“数据集成”。在敏捷管理语境中,有两个实体,一个是ProuctOwner,一个是TeamMember。在认证上下文中,如果我们将ScrumProductOwner角色分配给一个用户,那么在敏捷管理上下文中就会生成一个ProductOwner实体;如果为用户分配了ScrumTeamMember角色,则将在敏捷管理上下文中生成一个TeamMember实体。敏捷管理上下文在认证上下文中监听用户的角色分配事件,通过agilepm.port.adapter.messaging.rabbitmq.RabbitMQTeamMemberEnablerListener的监听实现:@OverrideprotectedString[]listensTo(){returnnewString[]{"com.saasovation.identityaccess.domain.model.access.UserAssignedToRole"};}处理逻辑如下:@OverrideprotectedvoidfilteredDispatch(StringaType,StringaTextMessage){NotificationReaderreader=newNotificationReader(aTextMessage);StringroleName=reader.eventStringValue("roleName");Stringusername=reader.eventStringValue("username");StringemailAddress=reader.eventStringValue("emailAddress");StringfirstName=reader.eventStringValue("firstName");...if(roleName.equals("ScrumProductOwner")){this.teamApplicationService().enableProductOwner(newEnableProductOwnerCommand(tenantId,username,firstName,lastName,emailAddress,occurredOn));}...事件监听调用应用服务生成Product所有者。在敏捷管理上下文的领域逻辑中,只理解了ProductOwner的概念,没有理解user的概念。将实体映射到值对象有时使用值对象比使用实体更经济。例如,在协作上下文中,帖子具有作者的概念,但作者只是一个值对象。image.png的作者是一种合作者。除了身份,还有姓名、邮箱等属性。但是在创建帖子时,传递给创建服务的一个参数是用户名,但是帖子上Author的值对象是如何构造的呢?这就需要调用认证上下文的服务来获取用户的更多信息,构建Author。但是,应用层或领域层不能直接调用RPC/REST服务。这里定义了一个CollaboratorService接口,里面有一个authorFrom方法,通过用户名创建一个Author方法。在其实现类中调用了UserInRoleAdapter/HttpUserInRoleAdapter,通过HTTP远程获取用户信息。这里需要注意的是,CollaboratorService和Author领域模型在同一个包下,即在collaboration.domain.model.collaborator包下。其他类都在port/adapter包下,即collaboration.port.adapter.service下。是的,你没看错,这里使用了IoC容器来实现依赖倒置image.png上下文整合的两种技术手段。以上两种映射方式只是使用了技术上常用的两种集成手段——基于消息和基于API。但首先要记住的是,防腐层是关于领域概念的防腐,而不是技术。虽然我们需要实现port/adaper的技术,将应用层/领域层与具体的实现技术隔离开来,但是防腐层并不等于port/adaper。