ticaje/hexagonal

定义基于六边形设计的策略库

1.0.9 2024-03-24 22:08 UTC

This package is auto-updated.

Last update: 2024-09-24 23:24:26 UTC


README

GPLv3 License Latest Version on Packagist Quality Score Total Downloads Blog

安装

您可以使用composer(我唯一推荐的方式)安装此软件包

composer require ticaje/hexagonal

前言

此库为基于六边形设计的解决方案奠定基础。它是一个API,鼓励开发者使用六边形设计方法。我们还希望为在简单方式下向消费者公开隔离服务时提供命令总线方法的空间。

六边形架构

也称为端口和适配器,这种设计模式是在构建可扩展、可测试和维护的应用程序时应用于软件建模的一种思维方式。它代表着将软件解耦为更小的单元/层/API的方式,这些单元/层/API也可以独立部署和测试。每个层都有自己的面向边界的用途,无论是在商业还是基础设施方面。互联网上充满了关于六边形设计的文章和文档。

因此,端口和适配器界定了软件设计的两个重要方面

一方面,有创建上述责任层或API的意图

另一方面,最后但同样重要的是,

这些组件之间的交互方式:这些关系是六边形的核心,因为它们代表了软件的真实价值。

实际上,六边形(就像大多数设计模式一样)是一种抽象概念,没有规则说这个模式被错误地或正确地应用了。

接口的盛行

对我来说,这是一个个人观点,六边形架构和面向对象设计(O.O.D)的关键在于接口。接口对设计良好的决策至关重要,因为,在众多用途中,它们定义了应用程序之间相互交互的方式。

在六边形背景下,接口是接受进入我们应用程序或API的请求/数据的端口。

六边形和S.O.L.I.D原则中的接口

接口是SOLID原则中“D”的关键。依赖倒置原则指出,高层模块不应该依赖于低层模块,两者都应该依赖于抽象;而且,抽象不应该依赖于细节,而应该是相反的,细节应该依赖于抽象。

这听起来有点虚幻,但从六边形的观点来看,这是非常有意义的。我们所有的API定义和向世界展示自己的方式应该是通过使用端口,其入口点是接口,然后可以保证以下内容

  1. 多实现在所有方面,每个模块使用适配器(每个接口的不同实现)。
  2. 封装变化:模块在通过接口(抽象)相关联的情况下,对其他模块的变化保持不可更改。
  3. 迪米特法则:每个模块对其他模块的了解最少,它只知道接口本身在其服务/数据合同中定义的内容。这非常重要,因为它规范了机构之间的通信。
  4. 简化测试:测试具有少量(基本)责任类/API/模块/机构的测试变得简单得多,因此我们的应用程序更容易维护。

本质上,六边形架构是通过使用接口(或等效物)和抽象,以与作家创作小说并在可信的结构中为读者描绘人物/故事/时间线相同的方式,在系统组件之间建立关系。因此,六边形的目的是在实现良好的设计原则的同时,以一个好的故事来传达系统意图。

因此,接口(端口)反映了意图,具体的实现(适配器)提供了流畅/可互换的解决方案。

命令总线方法

这种设计模式也存在于这个库中,因为它可以与六边形设计一起包含在领域模型中。

命令总线的想法是拥有一个命令实体(描述特定行为者想要什么)并将其映射到执行它的处理程序实体。就是这样。

这对于具有由其他模块(无论高级还是低级模块)消费的服务层的场景尤其有用。

对于这个库,我们依靠一个有用的库来处理查找对应命令的处理程序的机械工作:Tactician为我们处理这个问题。

我们创建了一个特定的实现者,它通过构造函数作为ImplementorInterface连接到我们的端口:BusFacadeInterface。然后在DIC中完成连接。

在Laravel中的示例(通过上下文绑定)。

想象一下,我们想在Laravel应用程序中向一个特定的控制器注入我们的总线实现,那么我们只需要在其构造函数中注入ImplementorInterface,并在DIC中定义如下所示的配方

$this->app->when(ConsumerController::class)
          ->needs(ImplementorInterface::class)
          ->give(function ($app) {
              return ($app->make(Tactician::class));
});

Command-Bus在实践中的一个非常好的例子是拥有一个可以被多个上下文消费的服务。

想象一下,我们有一个提供特定业务规则的价格的API。

这个API可以从许多上下文中消费:HTTP调用、CLI命令、另一个API或基于消息队列的应用程序

好吧,正如我们所看到的,必须有一个唯一的地方,所有的调用都可以依赖。应用Command-Buss方法通过定义一个命令使这变得非常简单,该命令本质上是一个DTO,包含服务根据业务政策操作所需的所有必要数据,并将该命令传递给处理程序,该处理程序是封装服务的演员,并启动其逻辑。

总线是负责为特定命令找到处理程序的人。

这简化了消费服务的机制,因为所有消费者只需要准备命令,实例化总线并调用其API(将命令作为参数发送)来消费所需的服务。

鸣谢

许可

GNU通用公共许可证(GPLv3)。请参阅许可文件获取更多信息。