六边形架构(端口适配器)指南 - 8thlight


端口和适配器是一种架构模式,旨在将您的应用程序与细节解耦。
我的经验证实了这一说法。在最近的一个项目中,我们的团队决定从端口和适配器架构开始,随着我们团队的成长,它得到了回报。我们的团队正在构建一些需要集成的服务。端口和适配器让我们可以进行一些集成,并将我们的域模型与我们的数据库模式分离,这为我们的团队提供了灵活性,并将我们的应用程序与这些细节隔离开来。
但这是有代价的。我们的架构选择意味着加入我们项目的人们面临着学习曲线。大多数人不熟悉这种模式。或者可能听说过,但还没有实践经验。
我自己理解端口和适配器的道路是曲折的。我在网上看到很多用六边形来可视化模式的图表,但很难找到一个具体的例子来帮助我形成自己的心智模型。
如果您有类似的经历并放弃了,或者目前正在尝试理解端口和适配器,我提供这篇文章:
 
分层架构
要理解端口和适配器,我认为将其与更常见的 Web 应用程序架构模式(如分层架构)一起查看会很有帮助。MVC模式的控制器与您的业务逻辑交互,而业务逻辑与数据库交互。这是一个很好的模式。它很简单,它可以让您快速启动和运行!但分层架构可能并不总是最合适的。例如,在我们的项目中,分层架构对于新手来说可能更容易上手,但我们会失去敏捷性。

 
端口和适配器
端口和适配器就像一个分层的架构,但是它插入了端口来反转依赖的方向。它在您的控制器和您的应用程序之间插入端口,也就是在您的应用和您的数据库的适配器或称ORM 之间。
一个 端口 是操作系统端口的隐喻。在这个例子中, 一个端口就是一个接口。

图中的端口是红色和黄色框。这里的颜色差异是有意的,因为有两种端口: 传入端口和 传出端口。
传入端口将是您的应用程序实现的接口 。出站端口是您的应用程序所依赖的接口 。“传入”和“传出”是我们团队采用的术语。“驱动端口”和“驱动端口”是您可能会在其他文献中找到的术语。
这给我们留下了适配器。就像端口一样,有两种适配器:传入,用蓝色表示;和外向,以紫色表示。这里的区别是传入适配器 取决于传入端口,传出适配器 实现传出端口。
端口和适配器不仅适用于 Web 框架。传入适配器和传出适配器不限于由控制器和数据库适配器来实现。它们可以通过任何类型的适配器来实现。
例如,命令行接口可以满足您的传入适配器,而 HTTP 客户端可以满足您的传出端口。我的示例仅描述了传入和传出端的一个适配器和端口,但您可以根据需要拥有多个!
 
示例应用
让我们看一个受SmallerWebHexagon启发的具体示例,Alistair Cockburn 关于端口和适配器的博客文章中引用 了该示例 。
假设我们有一个 Web 应用程序,它将接受一个数字并对其应用一个比率。我根据每个组件在端口和适配器图中的作用对组件进行了颜色编码。

组件分解如下:

  • RatingUseCase 是一个传入端口。它是RatingApplication 将实现 的接口, KtorHttpAdapter 将依赖于它。
  •  RatingApplication 图中的对应于“应用程序使用案例”。这是我们关键业务逻辑所在的地方。这可以说是最重要的组件,它不受我们使用的 Web 框架或 ORM 等细节的影响。
  •  RatingProvider 黄色是我们的输出端口。这是应用程序获取正确速率所依赖的抽象,也是传出适配器将实现的接口。
  •  InCodeRater 是即将离任的适配器。它实现 RatingProvider 接口并获取应用程序的费率。想象一下,我们需要从文件或数据库中获取此速率的未来。我们可以添加此行为而无需修改我们的核心应用程序!
  • KtorHttpAdapter 是输入适配器。它取决于传入端口,它将通过其构造函数接受它。这是将驱动我们的应用程序的适配器。
  • 最后,还有 main 配置 RatingApplication with InCodeRater 和 KtorHttpAdapter with RatingApplication 并启动服务器的功能。

源代码可以在这里找到。

最后,如果我们稍微移动一下我们的盒子并在端口和应用程序周围添加一个六边形,我们就会开始看到一个熟悉的图表。

这类似于原始端口和适配器博客文章中的图表以及在图像搜索“六边形架构”时显示的数百张图像。在这篇文章中,我使用“端口和适配器”而不是“六边形架构”,但它们是相同的。它们都是有趣的名字,但模式的本质是通过依赖抽象来反转你的依赖关系。
可在此处找到完整的可运行版本的源代码 。