clean-architecture - Clean Architecture:编写应用业务规则时如何降低复杂度?
问题描述
假设我们有以下“创建用户”场景:
- 用户可以使用 Facebook、Google+ 或 LinkedIn 注册该应用程序;
- 后端应该检索一些基本的个人资料信息以注册用户(电子邮件、名字和姓氏);
- 用户使用“客户 ID”注册(只是增加了业务规则的复杂性);
- 注册过程完成后,应将数据发送到通知主题。
我可以想象一个具有以下结构的创建用户请求:
{
"clientId": "someClientId",
"authProvider": "FACEBOOK | GOOGLE | LINKEDIN",
"accessToken": "someAccessToken"
}
因此,考虑一下我们将拥有的注册/验证流程:
- 检查创建用户请求是否有效;
- 检查clientId是否有效;
- 尝试从社交网络 api 中检索个人资料信息;
- 检查是否填写了所有必需的个人资料信息;
- 检查用户是否存在于数据库中;
- 注册用户;
- 将数据发送到通知主题;
- 将数据传递给演示者。
直接跳到用例,我们将有一个构造函数,如:
CreateUserUseCase(
ApplicationClientGateway applicationClientGateway,
SocialNetworkGateway socialNetworkGateway,
UserGateway userGateway,
NotificationGateway notificationGateway,
Presenter presenter
)
和一个执行方法:
execute(CreateUserRequest request)
// validates the payload
// something like
if (request == null)
presenter.setError(someError);
// validates the clientId
applicationClientGateway.findById(request.getClientId())
// retrieves the profile information
// how to inject dinamically the implementation for
// Facebook, Google or LinkeIn based on a request parameter?
profile = socialNetworkGateway.findByAccessToken(request.getAccessToken());
// checks if the user exists
userGateway.findByEmailAndAuthProvider(profile.getEmail(), request.getAuthProvider());
//register the user
userGateway.insert(user);
//sends the notification
notificationGateway.send(user);
// sets the result
presenter.setResult(user);
现在,我们有一个带有很多参数(代码味道?)的构造函数,并且在执行方法中至少有 5 个验证步骤。
它看起来违反了 SRP,那么,我们如何分解这段代码以降低交互器的复杂性?
解决方案
首先,让我们分几个小步骤来打破这个:
1) 与演示者相关,看起来您有兴趣为工作流提供一些输出,对吧?假设这一点,也许最好从用例返回你想要的东西并处理上面的这一层。(构造函数中的-1参数)
2)就像其他答案所说的那样,看起来您的用例现在有很多责任。我会建议你在一个以上的用例中打破这个。就像是:
... Your first gateway (API)
..... ValidateClientId.execute();
..... profile = RetrieveProfile.execute();
..... InsertUser.execute(...)
3.1)与基于正确的社交网络注入正确的bean相关,您可以在网关内部处理此逻辑,而不是在调用它之前。记住一个网关可以调用另一个网关(它们在同一层)。所以,我建议你使用类似的东西。
在 usercase -> socialNetworkGateway.findByAccessToken(...) 在网关内部,您可以进行“切换”并调用诸如 FacebookGateway、GoogleGateway 等之类的东西。
推荐阅读
- html - css/Boostrap 4 - 视口居中
- amazon-ec2 - “错误:/run/airflow 不存在。无法创建 pidfile。” 将 systemd 用于 Airflow 网络服务器时
- r - 为什么在 rollapply 窗口中将值转换为字符串?
- azure - 如何为文档生成序列号?
- php - 获取 3 个模型之间的相关记录
- python-3.x - 如何从 PDF 嵌入 HTML 的 URL 下载 PDF 文件?
- javascript - Selenium Webdriver Javascript - 使用 sendKeys 键入法语
- html - div内图像的边距和垂直对齐
- heroku - 免费 Heroku Postgres 数据库的 4 小时停机时间是什么时候?
- python - 如何通过请求抓取具有不变 URL 的特定页面