标签: hexagonal-architecture

端口和适配器/六边形体系结构 - 术语和实现的说明

在阅读了有关Ports和Adapters架构的不同来源(包括Alistair Cockburn的原始文章)后,我仍然不确定术语"端口"和"适配器"的确切含义 - 特别是在将这些概念映射到实现工件时.

几个来源(例如这篇文章)暗示这种体系结构模式中的端口是外部的工件,其次是中间层中的适配器,它们在端口和处于核心的应用程序之间进行转换.

但是,在Cockburn的原始文章中,端口出现在适配器层的外部和内部,具体取决于通信方向:

  • 入站通信:" 当事件从外部世界到达端口时,特定于技术的适配器会将其转换为可用的过程调用或消息,并将其传递给应用程序. "
  • 出站通信:" 当应用程序发送内容时,它会通过端口将其发送到适配器,从而创建接收技术所需的适当信号(人工或自动). "

实际上对我来说,"全部外部"方法和"内部和外部"方法都没有意义 - 我会将端口看作始终放在应用程序旁边的工件,而不管通信方向如何.Imo这也与端口适配器的比喻一致:E.g.有一个带有串行端口的设备,要连接另一台没有串口的设备,我需要一个适配器,从我的设备的角度来调整入站和出站通信.

来到这个体系结构的实现,我会看到端口的定义,而不是作为我的应用程序的一部分,我会看到不同的适配器是我的应用程序的"外部".E. g.单个端口的实现可以包括facade(由适配器调用以进行入站通信)和interface(由适配器实现用于出站通信).

术语端口适配器的正确含义是什么?如何将这些概念映射到实现工件?

更新:

发现这篇文章类似于我的理解.如果存在某种共同协议,问题仍然存在.

architecture hexagonal-architecture

28
推荐指数
3
解决办法
9817
查看次数

洋葱建筑与六角形相比

它们之间有什么区别(洋葱|六角形),从我的理解它们是相同的,它们关注的是应用程序核心的领域,应该是技术/框架不可知的.

它们之间有什么区别?

另外我认为使用一个优于另一个甚至是针对N层架构没有真正的优势,如果做得不好只是跟随其中任何一个都没有任何区别

使用一个优于另一个以及为什么要使用它有什么好处?什么时候用?

谢谢

architecture software-design hexagonal-architecture onion-architecture

16
推荐指数
2
解决办法
5401
查看次数

Python 中的工厂方法与注入框架 - 什么更干净?

我通常在我的应用程序中做的是使用工厂方法创建我所有的服务/dao/repo/clients

class Service:
    def init(self, db):
        self._db = db

    @classmethod
    def from_env(cls):
        return cls(db=PostgresDatabase.from_env())
Run Code Online (Sandbox Code Playgroud)

当我创建应用程序时

service = Service.from_env()
Run Code Online (Sandbox Code Playgroud)

什么创建了所有依赖项

在我不想使用真实数据库的测试中,我只做 DI

service = Service(db=InMemoryDatabse())
Run Code Online (Sandbox Code Playgroud)

我想这与干净/十六进制架构相去甚远,因为 Service 知道如何创建数据库并知道它创建的数据库类型(也可能是 InMemoryDatabse 或 MongoDatabase)

我想在干净/十六进制架构中我会有

class DatabaseInterface(ABC):
    @abstractmethod
    def get_user(self, user_id: int) -> User:
        pass

import inject
class Service:
    @inject.autoparams()
    def __init__(self, db: DatabaseInterface):
        self._db = db
Run Code Online (Sandbox Code Playgroud)

我会设置注入器框架来做

# in app
inject.clear_and_configure(lambda binder: binder
                           .bind(DatabaseInterface, PostgresDatabase()))

# in test
inject.clear_and_configure(lambda binder: binder
                           .bind(DatabaseInterface, InMemoryDatabse()))
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • 我的方式真的很糟糕吗?它不再是一个干净的架构了吗?
  • 使用注入有什么好处?
  • 是否值得打扰并使用注入框架?
  • 还有其他更好的方法可以将域与外部分开吗?

python architecture dependency-injection hexagonal-architecture clean-architecture

10
推荐指数
2
解决办法
1617
查看次数

六边形架构和交易概念

我正在努力适应六边形架构,但不知道如何实现已经用不同方法实现的常见实际问题。我认为我的核心问题是了解提取到适配器和端口的责任级别。

在网络上阅读文章,使用简单的示例就可以了,例如:

我们有RepositoryInterface,可以在mysql/txt/s3/nosql存储中实现

或者

我们有NotificationSendingInterface并且有电子邮件/短信/网络推送实现

但这些都是非常精致的示例,并且只是接口/实现细节的分离。

然而在实践中,我们通常知道的接口+实现领域模型中的编码服务保证了更深入。

为了说明目的,我决定询问存储+交易对。

在十六进制架构中应该如何实现存储的事务概念?假设我们在域级别有简单的 CRUD 服务接口

StorageRepoInterface
   save(...)
   update(...)
   delete(...)
   get(...)
Run Code Online (Sandbox Code Playgroud)

我们希望在使用这些方法时得到某种事务保证,例如在一个事务中删除+保存。

按照hex的构思应该如何设计和实现呢?

是否应该通过TransactionalOperation的某些外部协调接口来实现?如果是,那么一般来说,TransactionalOperation必须知道如何与StorageRepoInterface的所有实现一起实现事务保证(mb 在附加面向事务的操作接口中)

如果不是,那么域级别(十六进制内部)的StorageRepoInterface似乎应该通过其他方法提供显式事务保证?

不管怎样,它看起来并不像所说的那样“隔离和基于接口”。

有人可以指出我如何在这种情况下正确改变心态或在哪里阅读?

提前致谢。

architecture interface hexagonal-architecture

9
推荐指数
1
解决办法
4258
查看次数

六边形架构中的层

我读了很多关于六边形架构的文章,但在我正在寻找的所有示例中,所有文件夹和类的泛化都是不同的,这对我来说看起来有点令人困惑。

包组织

我已经完成了一个简单的 Spring Boot 应用程序,其文件夹结构如下。适配器文件夹包含存储库接口和其余控制器的实现。

在域文件夹中,我有模型,它是一个简单的 POJO,端口,它们是服务类的接口,其中包含产品的所有业务逻辑,以及存储库的接口,它公开要在存储库中实现的方法。

在另一个文件夹中,我有服务实现,正如我之前所说,具有产品的业务逻辑。

这是为简单用例实现六边形架构的正确方法吗?如果没有,为什么?我应该把每门课放在哪里,为什么?这个就不清楚了...

非常感谢!

architecture domain-driven-design hexagonal-architecture spring-boot clean-architecture

9
推荐指数
1
解决办法
1万
查看次数

DDD 流程管理器:它们是业务逻辑的一部分吗?

一些消息来源声称流程管理器不包含任何业务逻辑。例如,微软的一篇文章是这样说的:

\n
\n

您不应使用流程管理器在您的域中实现任何业务逻辑。业务逻辑属于聚合类型。

\n
\n

再往上他们还这么说(强调我的):

\n
\n

需要注意的是,流程管理器不执行任何业务逻辑。它仅路由消息,并且在某些情况下在消息类型之间进行转换

\n
\n

但是,我不明白为什么消息之间的转换(例如从域事件到命令)不是业务逻辑的一部分。您需要领域专家才能知道正确的步骤顺序以及步骤之间的转换。在某些情况下,您还需要在步骤之间保留状态,甚至可能根据某些(业务)条件选择后续步骤。因此,并非所有内容都是给定步骤的静态列表(尽管\xe2\x80\x99d 也调用业务逻辑)。

\n

在我看来,在很多方面,流程管理器(或就此而言的传奇)只是另一种持久状态的聚合类型,并且可能具有一些业务不变量。

\n

假设我们用六边形架构实现 DDD,I\xe2\x80\x98d 将进程管理器放置在应用程序层(不是适配器!!),以便它可以对消息做出反应或由计时器触发。它将通过存储库加载相应的流程管理器聚合,并调用其上的方法来设置其(业务)状态或要求其发送下一个命令(当然,实际发送是由应用程序层完成的)。该聚合位于领域层,因为它负责业务逻辑。

\n

我真的不明白为什么人们要区分业务规则和工作流规则。如果删除除领域层之外的所有内容,您应该能够重建工作应用程序,而无需再次咨询领域专家。

\n

我\xe2\x80\x98d 很高兴从你们那里得到一些我可能缺少的进一步见解。

\n

workflow domain-driven-design business-process-management hexagonal-architecture

9
推荐指数
1
解决办法
1672
查看次数

六边形架构和微服务:它们如何结合在一起?

我想知道六边形架构如何与微服务相关联。微服务都进入六边形的核心了吗?还是每个微服务都有一个六边形架构?或者两者都是(分形)?

hexagonal-architecture microservices

8
推荐指数
2
解决办法
2993
查看次数

六角形结构与弹簧数据

我将开始一个新项目来学习弹簧靴,弹簧数据和六边形结构.根据我的理解,六边形体系结构旨在将核心或域层与数据库操作(Infrastructure Layer)分开.我已经看到了这个架构的以下项目结构.

核心层有:

服务 - >逻辑走向(接口及其实现).

实体 - >这些将在整个应用程序中使用.

存储库 - >基础结构层必须实现的接口.

Infrastructure Layer具有Repository接口,JPA实体,对数据库的调用(hibernate)以及将JPA实体转换为Core Entities(mappers?)的某种函数的实现.

Spring数据有一种非常有用的方法来实现CRUD操作:

public interface UserRepository extends JpaRepository<User, Integer> {
}
Run Code Online (Sandbox Code Playgroud)

不过,我觉得如果我用春天的数据,JPA的实体将不会是基础设施层的一部分,如果UserRepository是核心层的一部分.这意味着核心实体将毫无用处.我应该创建另一个属于核心层的UserRepository接口还是我缺少的东西?

更新:

我对使用spring数据的关注来自于我必须在域内包含JPA实体,理论上它会违反六边形体系结构.

所以我想将域实体与JPA实体分开.但是,如果我这样做,我不知道Spring Data的存储库应该去哪里,也找到了将JPA实体转换为Domain实体的方法.

为了更好地说明一点,我将假设我需要从我的应用程序连接到数据库以读取用户表.

这可能是域实体:

public class UserDomain{
  private String name;
  ....//More fields, getters, and setters.
Run Code Online (Sandbox Code Playgroud)

根据我的理解,服务应包括逻辑并操作域实体.

public interface UserService{
  public void create(UserDomain user);
  ...
Run Code Online (Sandbox Code Playgroud)

实施:

public class UserServiceImpl implements UserService{
  public void create(UserDomain user) {
     ... //Calling the repository(Spring Data Repository?)
Run Code Online (Sandbox Code Playgroud)

以上与存储库接口是我认为的域(如果我错了请纠正我).接下来,基础架构由JPA实体组成

@Entity
@Table(name="users")
public class User{
  @Column(name="name")
  private String name;
  ... // …
Run Code Online (Sandbox Code Playgroud)

java spring hexagonal-architecture spring-data-jpa

7
推荐指数
2
解决办法
3281
查看次数

洋葱架构的 DDD 端口和适配器,什么去了哪里?

试图弄清楚一些概念但无法理解

端口和适配器架构中的用例是什么?

用例的实现会是什么样子?

什么是用例问题?

它适合基础设施或域中的什么位置,它说它适合应用程序,还有应用程序核心和应用程序服务,根据我的理解,它们是不同的?

在左侧,适配器依赖于端口并注入端口的具体实现,其中包含用例。在这一侧,端口及其具体实现(用例)都属于应用程序内部;

https://herbertograca.com/2017/09/14/ports-adapters-architecture/#what-is-a-port

这句话让我感到困惑......因为据我了解,主适配器可以是任何需要您的业务逻辑的东西(它对您提供的内容感兴趣)WebAPI、MVC、测试、ConsoleApp。

在左侧,适配器依赖于端口并注入包含用例的端口的具体实现。

所以我假设它指的是您的业务逻辑被注入到WebApiController构造函数中

在这一侧,端口及其具体实现(用例)都属于应用程序内部;

所以呢 ?这是谁

应用

是WebApi吗?或者是域?据我了解,用例也是我的业务逻辑的实现,所以例如设计会是这样的?

Client :
WebApiController(IMyBusinessServicePort service)

Infrastructure :
ImplementingPrimaryAdapter : IMyBusinessServicePort { }
ImplementingSecondaryAdapter : ILoggingPort { }

Domain :
ImplementMyBusinessLogicService : IMyBusinessLogicService 
Run Code Online (Sandbox Code Playgroud)

那么 WebApiController 将使用 ImplementingPrimaryAdapter 提供的实现而不是我的域中的东西?我不明白

请解释 。

architecture design-patterns domain-driven-design software-design hexagonal-architecture

7
推荐指数
1
解决办法
6886
查看次数

周期性后台任务适合六边形架构中的什么位置?

我正在 golang 中开发一个程序,该程序是基于六角形架构构建的。我想我的脑子主要围绕着这个想法,但有些东西我就是想不通。

该程序的功能是监控多个IP摄像机的警报事件,接收器可以通过HTTP2.0 PUSH REQUEST接收警报事件的实时流。(以防万一这不是技术术语,我的服务根据 GET 请求建立 TCP/HTTP 连接并保持打开状态,当摄像机触发警报事件时,摄像机将其推送回服务)

架构层次

适配器

  • HTTP处理程序
  • 内存中 JSON 存储

港口

  • 设备服务接口
  • 事件服务接口
  • 设备库接口
  • 事件存储库接口

服务

  • 设备服务
  • 事件服务

领域

  • 设备域
  • 事件域

用户通过 API 将设备添加到系统,请求包括所需的监控计划(接收器每天应启动和停止的时间)和 url。

调度程序负责定期检查接收器是否应根据其时间表启动。如果它要为某个设备运行,它将启动该设备的接收器。

接收器建立与 IP 摄像机的连接,并循环处理警报事件流并将其传递给EventService

EventService 接收事件,并负责根据域逻辑处理该事件,并决定发送电子邮件或忽略它。它还将所有事件保存到 eventrepo。

我不确定代码的两部分是调度程序和接收器。他们也应该如此;A。两者在同一个包中并放置在Adapters 层 b.适配器层的接收器和服务层的调度器 c.服务层的调度程序和接收器?

我只是很困惑,因为接收器不是由用户直接启动的,而是由不断检查条件的运行循环启动的。但我也可能为不同品牌的相机配备不同的接收器。这是一个实现细节,这意味着接收者应该位于适配器层。这让我认为选项 b 是最好的。

我可能想得太多了,但请让我知道你们认为最好的选择是什么,或者建议一个更好的选择。

architecture domain-driven-design go hexagonal-architecture clean-architecture

7
推荐指数
1
解决办法
1881
查看次数