干净的体系结构:组合交互器

2022-09-01 08:39:56

我最近偶然发现了鲍勃叔叔的Clean Architecture,我很好奇 Interactors 是否可以执行其他 Interactors。

例如,这些是我现在的交互器:getEmptyAlbums,getOtherAlbums。两者都有回调,分别返回专辑列表(专辑模型的数组列表)。

我是否允许有一个名为getAllAlbums的交互器,它在它的运行块中执行前两个交互器?

@Override
public void run() {
    getEmptyAlbums.execute();       
}

void onEmptyAlbumsReceived(ArrayList<Album albums){
     getOtherAlbums.execute;
}
void onOtherAlbumsReceived(ArrayList<Album albums){
         mMainThread.post(new Runnable() {
         callback.onAlbumsReceived(albums);
     }
});

答案 1

我一直在思考同样的事情,在对这个问题知之甚少之后,我得出的结论是“是的”,这可能是最好的选择。

我的理由如下:

  1. 单一责任:如果你不能聚合用例,那么每个用例就不可能真正成为单一的责任。如果没有聚合,这意味着域逻辑最终会进入表示层,从而破坏了目的。
  2. DRY:用例可以共享,并且应该在有意义的地方。只要用例的意图是相同的。显然,在完成之前应该仔细考虑这一点。根据我的经验,在下一点之外,很少需要这样做。
  3. 业务流程协调程序类:例如,如果您需要获取多个数据源并保存到存储库中。需要一个将运行所有这些子用例的用例,以确保正确实现操作顺序和并发性等内容。我认为这是调用其他用例的最令人信服的理由。

为了保持单一责任,我会考虑将聚合用例限制为仅执行此操作,即执行这些用例并进行任何最终转换。

鉴于这个问题的年龄,我很想知道你采取了哪种方式以及你遇到的问题。


答案 2

我的答案是否定的。让我解释一下原因:

  1. 这将打破界限

Clean Architecture最重要的概念之一是边界。每个用例都定义了一个边界,即系统的垂直层。因此,没有理由让一个用例知道另一个用例的存在。这种垂直层允许获得用例的独立开发能力和可部署性。想象一下,我们作为一个团队工作,你开发GetEmptyAlbums用例,而我则研究GetAllAlbums用例。如果我用我自己的用例来称呼你的用例,我们并不是独立开发的。我们都没有实现独立的可部署性。垂直边界断开。有关更多详细信息,请参阅《清洁体系结构》一书的第 152 页和一般第 16 章。

  1. SRP也会被破坏

假设 GetEmptyAlbums 业务规则因任何原因而更改。您将需要重构该用例。现在也许你需要接受一些输入。如果 GetAllAlbums 调用 GetEmptyAlbums,则此用例也必须重构。换句话说,通过耦合用例,您可以增加更多的责任。因此,SRP 中断。

  1. 干燥仍可投诉

有两种重复:真正的重复和意外的重复。通过定义 2 个或更多彼此非常相似的用例,您将获得意外的重复。这是偶然的,因为将来可能会因为不同的原因而变得不同(这很重要)。有关此概念,请参阅第 154 页。

  1. 测试变得更加脆弱

与战略调整计划非常相关。如果你在用例A上更改了一些东西,而C调用了A,不仅A测试会中断,C测试也会中断。

总之,答案是否定的,您不能从另一个用例交互器调用用例交互器。但是,如果您想实现纯粹的 Clean Architecture 方法,则此规则适用,这并不总是正确的决定。

需要指出的另一件事是,用例必须声明输入和输出数据结构。我不确定你的 Album 类是否是实体,但如果是这样,那就有问题了。正如鲍勃叔叔所说:“我们不想在边界之间作弊和传递实体对象”(第207页)。


推荐