首页 > 解决方案 > 如果业务逻辑要发送电子邮件

问题描述

我正在尝试实现鲍勃叔叔的清洁架构:

鲍勃叔叔的清洁架构

除了用例/交互器之外,一切都很好。我需要注册一个用户,所以我需要RegisterUserUseCase。在具体的交互器中,我实现了RegisterUser只创建实体并使用端口User散列其密码的用例。PasswordBroker

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

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

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

我认为我们需要某种与具体用例相关的端口,该端口将在用例结束时调用,并在框架的 Mailer 和 Doctrine 可用的应用层中实现。

标签: phparchitectureclean-architecture

解决方案


  1. 我认为为邮件服务编写端口是没有意义的,因为这个端口只是框架服务的巨大复制/粘贴抽象

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

我会Notification以一种从具体通知机制中抽象出来的方式来设计界面,例如电子邮件、信使等。

然后Notification可能看起来像这样:

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

实现将放置在外层,通常是接口适配器层。因为这是适应内层接口的层——因此得名。

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

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

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

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

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

对于 Spring,请查看Transaction 绑定事件或 JEE 的TransactionSynchronizationRegistry。如果 Java 开发人员读过这篇文章,请提及一些。


推荐阅读