如果业务逻辑要发送电子邮件

时间:2019-06-21 09:52:24

标签: php architecture clean-architecture

我正在尝试实现Bob叔叔的Clean Architecture:

Uncle Bob's Clean Architecture

除UseCases / Interactors之外,一切都很好。我需要注册一个用户,所以我需要RegisterUser UseCase。在具体的 interactor 中,我实现了RegisterUser用例,该用例仅创建User实体并使用PasswordBroker端口对密码进行哈希处理。

创建用户后,我需要发送验证电子邮件。为此,我需要使用框架的组件。主要有两个问题。

  1. 我认为没有必要为Mail服务编写 port ,因为该端口只是框架服务的巨大复制/粘贴抽象
  2. 创建用户后,Interactor无法发送电子邮件,因为最终用户将被存储在控制器中的原则flush()之后。当我们发送电子邮件但没有将用户存储在数据库中时,存在风险。它必须是一致的。

在这种情况下最好的方法是什么?

我认为我们需要某种与具体用例相关的 port ,该端口将在用例的结尾被调用并在 Application Layer 中实现框架的Mailer和Doctrine可用。

2 个答案:

答案 0 :(得分:2)

  
      
  1. 我认为没有必要为Mail服务编写端口,因为该端口只是框架服务的巨大复制/粘贴抽象
  2.   

我将创建一个Notification接口,该接口传递给用例交互器,类似于EntityGatewayEntityRepository

我会设计一种Notification接口,使其从具体的通知机制中抽象出来,例如电子邮件,救护车等。

Notification可能看起来像这样:

public interface Notification {
    public void notifyUserRegistered(User user);
}

该实现将放置在一个外层,通常是接口适配器层。因为这是适应内层接口的层-因此命名。

这样的Notification接口可以在测试中轻松模拟,这可以使您的测试保持快速。因此,我认为通知界面不是一个巨大的复制/粘贴抽象。

  
      
  1. Interactor在用户创建后无法发送电子邮件,因为用户最终将在Doctrine flush()之后存储在控制器中。当我们发送电子邮件但没有将用户存储在数据库中时,存在风险。它必须是一致的。
  2.   

首先,我想您无论如何都不能做到这两者,因为发送电子邮件不参与数据库事务。因此,您仍然会遇到一致性问题。

但是您通常可以向活动的事务进行注册,以便在事务成功完成时得到通知。这意味着Notification实现将只注册一个在事务完成时被调用的回调。然后,您可以发送电子邮件。

我不知道如何在php中完成,也许这是SO上的另一个问题。在Java中,有几种方法取决于您使用的事务api。

对于Spring,请看Transaction bound events或JEE的TransactionSynchronizationRegistry。仅提及一些Java开发人员是否读过这篇文章。

答案 1 :(得分:1)

这是使用框架的优点/缺点。干净的体系结构故意将您与此类依赖关系隔离。这样一来,事情就可以从您的下方改变,而不受更改的影响。它还允许您针对抽象进行测试(针对框架代码编写自动测试始终是可怕的)。

您需要做的是确定是否有必要利用框架的优点来破坏干净的体系结构。这是一种平衡的行为,我们每个人都必须根据具体情况做出决定。框架为我们提供的服务越多,我们得到的控制就越少,并且应用程序最终在架构上“纯净”的程度也越少。但是,如果没有框架,我们必须编写实质上是对现有功能进行重复的浪费的代码。