六边形架构是构建系统结构并将其拆分为不同层的好方法,每个层都有特定的用途。

不要让名称欺骗您认为它包含 6 条逻辑。它更多地代表了六边形的多个边,使其成为与外部系统具有多个连接的应用程序的理想选择。六边形也是 UML 图中常用的组件。

现在让我们谈谈构成 Hexagonal 架构的 3 层。

  1. 适配器

  2. 端口

  3. 域名

[](https://res.cloudinary.com/practicaldev/image/fetch/s--QtSRx_HQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent. com/630705/155397373-918ec18b-e8a4-4f2d-ac97-8e1d8dd12cdb.jpeg)

适配器

我喜欢思考适配器的方式就像我们应用程序的 I/O。数据如何进入我们的应用程序,然后这些数据去哪里了?

这可能是调用我们的应用程序的 HTTP 端点,或者是我们的应用程序正在侦听的 EventBridge 事件。然后在另一端,一旦应用程序执行了它的业务逻辑,它就必须对这些数据做一些事情。

一个非常常见的场景是将该数据存储在 DynamoDB 或 MongoDB 等数据库中,或者向客户发送通知。适配器可以是任何允许我们的应用程序与外部世界进行入站或出站通信的东西。

当需要处理在应用程序中接收到的数据并执行一些业务逻辑时,例如计算、数据重塑和其他应用程序内部流程。这是域层。

隔离域逻辑是构建弹性系统的一个很好的实践,它不仅可以扩展,而且易于使用和修改。后者更多。

端口

在我看来,端口层是在这个架构模式的整个概念中造成最大混乱的部分。让我们看看我们是否可以从中理解。

正如我们已经说过的,Hexagonal 架构的卖点之一是它可以使我们的应用程序域不可知。这意味着我们的业务逻辑应该与我们使用的特定工具和基础设施分离。换句话说,我们的域不应该依赖于我们使用的数据库的细节。

同样,域不应该知道我们正在通过 SQS 队列向它发送数据。端口是将域与适配器连接起来的桥梁,并持有决定哪些信息应该从一个传递到另一个的逻辑。在类型化语言中,端口通常是一个接口,它指定适配器必须传递给域的数据的形状,反之亦然。

一个用例

让我们举一个经典的例子,我们的应用程序是一个 RESTful API,它通过 HTTP POST 端点接收数据并将其存储到 MongoDB。旅程看起来像这样

[](https://res.cloudinary.com/practicaldev/image/fetch/s--4CG8_seC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent. com/630705/155397207-c9248cc5-8e58-4550-ac9c-c44a8e96a6ad.jpeg)

我们的 HTTP 适配器将处理 HTTP POST 请求并将数据发送到端口,该端口将与域通信。这是我们内部逻辑将被执行的地方。内部计算,重塑数据等东西。

然后我们需要反过来遵循相同的逻辑。域有一些数据,想要将其存储在数据库中,并且必须将它们发送到存储库端口,然后再将其发送到数据库适配器。

适配器(输入)

HTTP 处理程序

端口(到域)

HTTPHandler.retrieveData

领域

处理数据并将数据发送到存储库

端口(至适配器)

存储库.storeData

适配器(输出)

与 MongoDB 的连接

六边形架构的优点

您可能想知道“是的,这很酷,但我们为什么要经历所有这些麻烦?”

1\。灵活性符合结构

将 Hexagonal 架构放到业务角度来看,由于采用松散耦合的代码结构方式,当我们想要引入新功能时很容易。我们可以在不造成重大中断的情况下更改应用程序的某些部分。

除此之外,我们未来的自己在调试错误时会非常感谢我们,因为我们会立即知道去哪里寻找。

应用程序是否返回了错误的数据?这听起来像是领域层的一个问题。该请求期间是否存在网络问题?听起来像适配器问题。

2\。隔离测试

Hexagonal 架构中我最喜欢的部分之一是测试我们的代码变得更加简单。我们都经历过非常难以测试的代码库,因为它们缺乏边界,所有的实现都只是扔到一个函数/方法/类/任何你想命名的东西中,即 100 多行。

使用 Hexagonal 架构,每一层都是一个单独的模块,我们可以单独测试。这可以通过模拟它与其他层的通信来完成,这使我们可以灵活地进行更小的测试,这些测试更容易编写和执行得更快。奖励点,然后可以产生更高的测试覆盖率。

3.域无关应用

“即插即用”适配器的整个概念很棒,因为它确保我们的业务逻辑不依赖于我们使用的工具。

我们的业务逻辑对某个基础设施越具体,我们未来离开这个基础设施的难度就越大。

我们有多少次不得不花费数天甚至数周的时间来尝试找出如何从数据库 A 切换到数据库 B,因为我们的代码与数据库 A 的耦合太紧密了。我们需要小心这个工具在我们域内的逻辑泄漏关于。

六边形架构指导我们如何在工具和业务逻辑之间建立清晰的界限。然后,一旦我们决定放弃一个工具,它应该像添加一个新适配器一样简单。

显然,我并不是说从工具中迁移出来会是小菜一碟,但我们应用程序内部的转换可能是我们最关心的问题。

结论

对于我们这些使用无服务器应用程序的人来说,一个已知问题是我们的整个逻辑都在处理程序中。然后慢慢地,一旦我们的应用程序开始变得越来越大,我们要么最终得到巨大的处理程序,要么得到一些奇怪的结构,看起来基础设施逻辑混合在业务逻辑中。这是我们需要引入一些边界的地方,六边形架构可以帮助我们解决这个问题。

我不得不承认,当我第一次尝试使用这种模式编写一些代码时,感觉真的很奇怪。我认为最大的问题是没有真正理解六边形架构试图解决什么样的问题。随着时间的推移,它开始变得更有意义,从那时起,它一直是我一直在从事的结构化项目的第一选择。

点击阅读全文
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐