一、传统分层架构

分层架构的一个重要原则是:每层只能与位于其下方的层发生耦合。

分层架构分两种:一种是严格分层架构,规定某层只能与直接位于其下方的层发生耦合;另一种是松散分层架构,允许任意上方层与任意下方层发生耦合。

下图是一个典型的DDD传统分层架构。

以上分层架构中各层都有自己的职责:

用户接口层负责处理用户请求和用户显示;

应用层实现不同业务场景下的用例或业务流程。其中应用服务通常接收来自用户接口层的请求,然后通过资源库获取聚合实例,最后执行相应的命令操作,如下示例:

// 应用层的用例
public void cancelOrder(Long orderId) {
Order order = orderRepository.findById(orderId);
// 领域层的业务逻辑
order.cancel()
orderRepository.save(order);
}

领域层实现系统的核心业务逻辑,主要包含基于DDD业务建模产生的领域模型,这里的业务逻辑不同于应用层中的业务流程,如上代码示例;

基础设施层为其它各层提供通用的技术和基础服务,比如数据持久化功能。

二、传统分层架构的问题

DDD中资源库(Repository)用来获取或持久化聚合,每个聚合都拥有一个对应的资源库。由此可见资源库应该和聚合位于同一层,资源库接口定义应该位于领域层,而资源库接口实现需要依赖基础设施层的持久化机制,此时资源库接口实现放在哪一层对传统分层架构来说是个问题。

如果把资源库接口实现放在基础设施层,那么基础设施层就会向上依赖领域层,这样就违反了分层架构的原则:每层只能与位于其下方的层发生耦合。

或者可以放在领域层,但是这样会使领域层依赖数据持久化的实现细节,导致领域层不再是一个稳定层。

也可以放在应用层,不过和放在领域层会有同样的问题。

那有没有更好的方式呢?

有,采用依赖倒置,打破分层架构原则。

三、依赖倒置原则

依赖倒置(或依赖反转)原则(Dependency inversion principle,DIP),由Bob大叔提出,其定义如下:

高层模块不应该依赖于低层模块,两者都应该依赖于抽象。 抽象不应该依赖于细节,细节应该依赖于抽象。

我们把资源库接口实现放在基础设施层,让基础设施层向上依赖领域层。虽然这样违背了分层架构原则,但是却符合依赖倒置原则:领域层(高层模块)不依赖基础设施层(低层模块),两者都依赖于资源库接口(抽象)。采用了依赖倒置后,同时调整下基础设施层位置,此时分层架构如下图:

四、六边形架构

分层架构采用依赖倒置原则后,实际上已经不存在分层的概念了。无论是高层还是低层,都只依赖于抽象,好像把整个分层架构给推平了一样。推平后的分层架构如下图:

给推平的分层架构补上左侧对称的另一半,其结果就类似六边形架构,如下图是六边形架构。

六边形架构也叫端口和适配器。在这种架构中,针对系统输入输出的不同交互方式,比如http、rpc、mq、数据持久化等,都有与之对应的适配器,适配器又通过应用层API与内部进行交互。

六边形架构让应用程序能够以一致的方式被用户、程序、自动化测试、批处理脚本所驱动,而且能够让应用程序的边界更加清晰。有关六边形架构的详细信息可以查看 六边形架构原文翻译

五、为什么不选择整洁架构?

整洁架构是Bob大叔在其《架构整洁之道》一书中,对六边形架构和其他类似架构做了总结和抽象之后,提出的一种架构设计理念。

书中总结出,六边形架构和其他类似架构设计出来的系统,都具有相同的特点:

独立于框架:这些系统的架构并不依赖某个功能丰富的框架之中的某个函数。框架可以被当成工具来使用,但不需要让系统来适应框架。 可被测试:这些系统的业务逻辑可以脱离UI、数据库、Web服务以及其他的外部元素来进行测试。 独立于UI:这些系统的UI变更起来很容易,不需要修改其他的系统部分。 独立于数据库:我们可以轻易将这些系统使用的Oracle、SQL Server替换成Mongo、BigTable、CouchDB之类的数据库。因 为业务逻辑与数据库之间已经完成了解耦。 独立于任何外部机构:这些系统的业务逻辑并不需要知道任何其他外部接口的存在。

综合以上所有架构的设计理念,Bob大叔提出了整洁架构设计理念,如下图。

以上图中同心圆分别代表了软件系统的不同层次,通常越靠近中心,其所在的软件层次就越高。

整洁架构规定了层之间的依赖关系规则:内层(高层)不依赖外层(低层),六边形架构层之间的依赖关系也遵从此规则。

至此可以认为整洁架构是一种架构设计的指导思想,六边形架构是整洁架构的一种具体的架构设计。

六、总结

采用依赖倒置原则后的分层架构和六边形架构,实际上都符合整洁架构设计理念。但是六边形架构中使用端口与适配器,让应用程序能够以一致的方式被用户、程序、自动化测试、批处理脚本所驱动,同时能够让应用程序边界更加清晰,从而能更好地防止领域层和应用层逻辑泄露到外层。

七、参考

1.《实现领域驱动设计》

2.《架构整洁之道》

作者:京东零售 加文雄

来源:京东云开发者社区

DDD架构为什么应该首选六边形架构?的更多相关文章

  1. 【DDD】领域驱动设计实践 —— 架构风格及架构实例

    概述 DDD为复杂软件的设计提供了指导思想,其将易发生变化的业务核心域放置在限定上下文中,在确保核心域一致性和内聚性的基础上,DDD可以被多种语言和多种技术框架实现,具体的框架实现需要根据实际的业务场 ...

  2. IDDD 实现领域驱动设计-SOA、REST 和六边形架构

    上一篇:<IDDD 实现领域驱动设计-架构之经典分层> 阅读目录: SOA-面向服务架构 REST 与 RESTful 资源(Resources) 状态(State) 六边形架构 DDD ...

  3. SOA、REST 和六边形架构

    SOA.REST 和六边形架构 上一篇:<IDDD 实现领域驱动设计-架构之经典分层> 阅读目录: SOA-面向服务架构 REST 与 RESTful 资源(Resources) 状态(S ...

  4. WeText项目:一个基于.NET实现的DDD、CQRS与微服务架构的演示案例

    最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间的努力,凭着自己对微服务架构的理解,从无到有,基于.NET打造了一个演示微服务架 ...

  5. NET实现的DDD、CQRS与微服务架构

    WeText项目:一个基于.NET实现的DDD.CQRS与微服务架构的演示案例 最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间 ...

  6. 在 .NET Core 中应用六边形架构

    在本文中,您会看到一个Web API应用的模板,在.NET Core 中应用了六边形架构,并且里面包含了一些基础功能. 介绍 这是一个模板项目,里面集成了一些必备的基础功能,当我们需要开发一个新项目时 ...

  7. .NET应用架构设计—重新认识分层架构(现代企业级应用分层架构核心设计要素)

    阅读目录: 1.背景介绍 2.简要回顾下传统三层架构 3.企业级应用分层架构(现代分层架构的基本演变过程) 3.1.服务层中应用契约式设计来解决动态条件不匹配错误(通过契约式设计模式来将问题在线下暴露 ...

  8. WEB架构师成长之路-架构师都要懂哪些知识 转

    Web架构师究竟都要学些什么?具备哪些能力呢?先网上查查架构师的大概的定义,参见架构师修炼之道这篇文章,写的还不错,再查查公司招聘Web架构师的要求. 总结起来大概有下面几点技能要求: 一. 架构师有 ...

  9. 基于LAMP平台的网站架构(或Web系统架构)

    1.网站架构的前提(或者说需求) 我们公司是一电子商务的网站,因为线下家具建材项目的推广需求,从而有了我们公司的这个线上网站,在这里我贴一张公司的网站架构图. 总体来说网站规模不是太大,注册人数在15 ...

  10. 向架构师进军---&gt;系统架构设计基础知识

    假设你对项目管理.系统架构有兴趣,请加微信订阅号“softjg”,增加这个PM.架构师的大家庭 在解说系统架构设计之前,有必要补充一下架构相关的概念,因此本博文主要讲述架构.架构师和架构设计等相关的概 ...

随机推荐

  1. ChatCLM部署随笔

    ChatCLM 博客 ChatGLM Github ChatGLM-webui 介绍 ChatGLM-6B 是一个开源的.支持中英双语的对话语言模型,基于 General Language Model ...

  2. If选择语句的用法

    今天我们学习下If判断语句. 首先了解下它有几种用法: If单选择语句 If双选择语句 If多选择语句 我们一个一个用,每一个用法都给一个运用的过程演练一下. If单选择语句:我们很多需要判断一个东西 ...

  3. javasec(五)URLDNS反序列化分析

    这篇文章介绍 URLDNS 就是ysoserial中⼀个利⽤链的名字,但准确来说,这个其实不能称作"利⽤链".因为其参数不是⼀个可以"利⽤"的命令,⽽仅为⼀个U ...

  4. 深度相机:结构光、TOF、双目相机

    随着人工智能与机器人.无人驾驶的火热,深度相机的技术和应用也受到关注,何谓深度相机? 顾名思义,就是可以测量物体到相机的距离(深度) 传统的RGB彩色普通相机称为2D相机,只能拍摄相机视角内的物体,没 ...

  5. [Pytorch框架] 4.5 多GPU并行训练

    文章目录 4.5 多GPU并行训练 4.5.1 torch.nn.DataParalle 4.5.2 torch.distributed 4.5.3 torch.utils.checkpoint im ...

  6. Centos7.x 更换Jenkins构建目录

    原由:最近因为原来的Jenkins构建目录,已经要满了,想着更换下构建目录,此篇文件简单介绍下更换过程. 注:此文章可能仅适用于我个人,仅供参考.如有其他办法,欢迎评论指教. 查了几种方法,最终选为使 ...

  7. ☆常用的Sql语句汇总(DDL/DML)

    常用的sql语句汇总 1.获取所有表名.表信息 里面有表注释 数据库种类 sql 备注 mysql -- 获取所有表名.视图名show tables-- 获取 dev_test_data数据库 所有表 ...

  8. Spring AOP 分享

    初级篇 AOP是什么? Aspect-oriented Programming (AOP) 即面向切面编程.简单来说,AOP 是一种编程范式,允许我们模块化地定义横跨多个对象的行为.AOP 可以帮助我 ...

  9. Rocky 9 Linux 软件安装 neovim 和 git

    目录 编辑器 Neovim 版本控制工具 Git RHEL 系列软件安装介绍 软件安装包简介 源码包安装 rpm包安装 yum & dnf 在线安装 脚本安装包 rockyLinux 介绍软件 ...

  10. 沁恒 CH32V208(四): CH32V208 网络DHCP示例代码分析

    目录 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置 沁恒 CH32V208(二): CH32V208的储存结构, 启动模式和时钟 沁恒 CH32V208 ...