
点击上方蓝字,关注灸哥


点击上方蓝字,关注灸哥


大家好,我是灸哥,今天和大家一起胡乱聊聊六边形架构(Hexagonal Architecture)~
在软件开发领域中,架构设计一直是一个重要的话题。
随着业务需求的不断变化和技术的快速发展,如何设计一个既灵活又易于维护的系统架构,成为每个开发者和架构师面临的挑战。
在软件架构的演变历程中,六边形架构(Hexagonal Architecture),又称之为端口与适配器架构(Ports and Adapters Architecture),正是在这样的背景下应运而生的,以其独特的设计哲学,为构建高质量、松耦合的软件系统提供了一种新的架构模式。
关于软件架构演变历程可以参照我前面的文章,链接给到大家:架构设计系列 2 : 软件架构设计演化史
六边形架构是由阿兰·波利(Alistair Cockburn)在 2005 年首次提出的一种软件架构模式,主要目标就是将应用程序的核心逻辑与特定的输入/输出技术解耦,使其能够更加灵活的应对变化和演化。
因此,六边形架构的核心思想就是通过将应用程序的核心业务逻辑与外部基础设施(比如数据库、用户界面、 Web 服务器、消息队列、外部服务等)解耦,形成一个清晰的界限。
这样,应用的业务逻辑不再依赖于任何特定的技术实现,而是通用定义良好的接口(端口)与外部世界通信,以此来达到提高系统灵活性和可维护性的目的。
在传统的分层架构中,业务逻辑通常依赖于数据访问层和用户界面层,这种依赖关系使得业务逻辑难以独立测试和重用。而六边形架构通过引入端口与适配器的概念,使得业务逻辑不再直接依赖于外部系统,从而实现了解耦。
在六边形架构中,明确分离应用程序(Application)、领域(Domain)和基础设施(Infrastructure)是关键的设计原则。
这种分离使开发者将关注点分离开,每一层都可以独立变化而不影响其他层,提高了系统的可维护性、可测试性和可扩展性。
应用程序层主要是包含应用程序的业务逻辑,负责协调领域层和基础设施层的交互,不包含具体的业务规则,而是将请求委托给领域层进行处理。
在实践中,通常由应用服务组成,提供用例的实现,负责接收外部请求、处理输入数据、协调领域层的操作,并调用适当的基础设施服务。
领域层包含系统的核心业务逻辑和领域模型,这是系统的灵魂,包含了问题域的概念、规则和约束。
在实践中,通常由由实体(Entities)、值对象(Value Objects)、聚合(Aggregates)、领域服务(Domain Services)等构成,协调工作,实现业务规则,确保系统的行为符合领域的要求。
基础设施层负责处理与外部系统的通信、数据库访问、日志记录等与具体技术相关的事务,包含所有与技术实现有关的组件。
在实践中,通过包括数据库访问层、外部服务通信层、日志记录、配置等,这些组件对系统的业务逻辑是透明的,通过接口与应用程序层和领域层进行交互。
六边形架构要求确保领域层保持独立性,不依赖于具体的应用程序逻辑或基础设施技术,提高系统的可测试性、可维护性和可扩展性。
技术上,就是 Application 和 Infrastructure 都不能直接互相调用对方的功能或者操作,只有经过 Domain 的接口才能沟通,确保 Domain 部分具有完整的独立性,不受 Application 和 Infrastructure 变更的影响,从而保持稳定,这样的代码结构易读、易管理、易维护。
应用程序层向领域层的依赖:应用程序层包含用例的实现,负责协调系统的操作并调用领域层的服务。
基础设施层向领域层的依赖:基础设施层包含与技术实现相关的组件,领域层不应该直接依赖于这些具体的技术实现,而是通过接口定义领域层所需的服务,并由基础设施层来实现这些接口。
在实践中,一般通过以下三种方式来实现:
领域服务接口:在领域层中定义接口,描述领域服务的行为,这些接口是应用程序层和基础设施层依赖的抽象 → 如果领域层需要使用某种外部服务,可以在领域层定义一个接口,然后在基础设施层中实现这个接口
依赖反转:通过依赖反转原则,应用程序层和基础设施层不直接依赖于领域层的具体实现,而是依赖于领域层定义的接口和抽象,这会让领域层能独立于其他层进行演化,不受具体实现细节的影响
测试驱动开发:将依赖关系的方向设计成从应用程序和基础设施指向领域,有助于采用 TDD,通过在应用程序层和基础设施层编写测试用例,并通过模拟或替代领域层的具体实现,可以更容易进行单元测试,确保领域层的正确性
六边形架构使用端口和适配器模式来隔离系统的边界,以提高系统的可测试性、可维护性和灵活性,目标是将业务逻辑与外部环境解耦,让系统的各个部分更容易替换、测试和理解。
端口:定义系统与外界通信的接口,表示系统的一种能力或服务,通常通过接口来表示,定义系统对外提供的服务,不关心具体的实现,只关注服务的契约
适配器:连接系统内部和外部的组件,负责将系统内的数据结构或接口转换成外部系统期望的形式,是外部环境和系统内部通信的桥梁,确保系统的核心业务逻辑不受业务环境的影响
内部端口和适配器:将应用程序划分为核心业务逻辑(Application)和外部环境(Infrastructure)两部分,内部端口表示系统对外部环境提供的服务,而内部适配器则负责将内部数据结构适应外部环境的需求
外部端口和适配器:外部端口表示系统对外部环境的依赖,而外部适配器则将外部环境的服务适配成系统内部期望的形式,使系统的核心业务逻辑不直接依赖于具体的外部实现,而是通过端口和适配器与外部环境进行通信
对称性:系统的设计围绕着一个中心的应用核心组件,所有的交互都必须通过这个中心
隔离性:应用程序的核心组件被一层薄的适配器包围,使得它对外部环境的变化免疫
可插拔性:系统可以通过改变其适配器来更改接口,并适应不同的上下文
六边形架构主要包括以下几部分:
这是整个架构的心脏,包含应用程序的业务逻辑和领域模型,不依赖任何特定的外部元素,只关注应用程序的核心功能。
业务逻辑的组件,不依赖于任何具体的基础设计,对应到 DDD 设计思想,这里就是领域模型的实现
定义应用核心与外部世界交互的接口,可以是 API、消息传递等方式。
实现端口定义的接口,将外部请求转换为应用核心可以理解的调用,并将应用核心的响应转换为外部可理解的格式。
六边形架构的实现方法可以分为以下几个步骤:
核心业务逻辑是应用程序的中心,包含所有的业务规则和流程。在六边形架构中,核心业务逻辑通常通过领域模型和服务来实现。这部分代码不应该依赖于任何外部系统,只关注业务本身。
端口是核心业务逻辑与外部世界交互的接口。它们定义了应用程序可以执行的操作,但不实现具体的操作细节。端口可以分为输入端口和输出端口。输入端口用于接收外部请求并触发业务逻辑,而输出端口则用于调用外部系统以完成某些任务。
适配器是具体的实现,用于将端口连接到外部系统。输入适配器负责接收来自用户界面、API或消息队列的请求,并将其转换为对核心业务逻辑的调用。输出适配器则负责将核心业务逻辑的调用转换为对数据库、外部服务等的调用。
通过依赖注入或配置文件,将适配器与端口连接起来。这样,核心业务逻辑在运行时可以通过端口调用适配器,从而与外部系统交互。
将适配器与相应的基础设施集成,比如数据库、Web 服务器等。
根据需求变化,不断迭代和优化应用核心和适配器。
六边形架构在实际应用中具有许多优势,以下是其中几个关键点:
由于核心业务逻辑不依赖于任何外部系统,可以轻松进行单元测试。通过为端口创建模拟实现,可以在测试中模拟外部系统的行为,可以很轻松地为业务逻辑编写单元测试和集成测试,从而对业务逻辑进行全面测试。
六边形架构使得应用程序的各个部分之间松散耦合,任何一部分的改变都不会影响到其他部分。例如,可以轻松地更换数据库或用户界面,而不需要修改核心业务逻辑。
六边形架构指导下的系统,业务逻辑和基础设施是解耦的,使得系统更加易于维护和升级。
通过清晰的端口定义和松散耦合的结构,核心业务逻辑可以在不同的应用程序或上下文中重用。例如,可以在不同的项目中使用相同的领域模型和服务,而只需实现不同的适配器。
六边形架构通过明确的端口与适配器的划分,使得系统的结构更加清晰。每个部分都有明确的职责,有助于减少代码的复杂性和维护成本。
允许使用不同的技术来实现适配器,以满足不同场景的需求。
清晰的架构界限有助于团队成员理解各自的职责和工作范围。
虽然六边形架构有很多好处,但是它也存在问题:
设计复杂度高
需要花费更多时间来进行需求分析和设计
学习曲线比较陡峭,需要具备一定的软件设计知识
六边形架构以其优雅的设计哲学,为架构师提供了一种强大的工具,这就决定了六边形架构是一种有效的架构设计方法,通过将应用程序的核心业务逻辑与外部基础设施解耦,提高了系统的灵活性、可测试性和可维护性。
六边形架构通过明确定义的端口与适配器,使得应用核心能够独立于基础设施变化,从而在不断变化的技术环境中保持竞争力。
在实际应用中,六边形架构已经被广泛采用,成为构建高质量软件系统的重要工具。
往期回顾


长按二维码识别关注
关注灸哥
了解更多
你的赞和在看,我统统都要

原文作者:灸哥漫谈;如有侵权,请联系管理员删除。