【问题标题】:Clean architecture Controller have access to the ViewModel干净的架构控制器可以访问 ViewModel
【发布时间】:2021-01-22 00:42:17
【问题描述】:

我有以下问题,根据这张图片

控制器不应访问 Presenter 或 ViewModel,但是,我如何通过单击更新视图,即用户单击增加 ViewModel 中的计数器的按钮(因为这是持有的类视图的状态),然后相应地更新视图。 但是,如果 Controller 可以访问 Presenter,我可以绕过 UseCase 并直接调用 Presenter,然后这个类会相应地更新 ViewModel。 我已经阅读了许多文章和方法来做到这一点,并将控制器与演示者混合在我看来,我将打破单一职责,因为控制器不仅负责创建 InputData,而且负责添加逻辑并调用演示者. 使用图片中的架构如何做到这一点_

【问题讨论】:

    标签: android ios flutter clean-architecture


    【解决方案1】:

    当您应该偏离特定原则/架构时,遵循它比不遵循它变得更加不便。这是因为无论我们谈论软件还是实际建筑物,项目需求都会塑造架构。一开始可以尝试让架构适用于每种情况,但这主要是为了让您可以了解它何时不适合特定情况。

    不幸的是,我不知道该图像来自何处的完整背景,但从您提到的 SRP 来看,它看起来像是 Bob 叔叔的作品,或者是受到密切启发的东西。我想你可能犯了我和其他几千名开发人员在 SRP 上犯的同样的错误。引用 Clean Architecture(鲍勃叔叔的书):

    在所有 SOLID 原则中,单一职责原则 (SRP)可能是最不被理解的。这很可能是因为它有 一个特别不恰当的名字。程序员太容易了 听到这个名字,然后假设它意味着一个模块应该做 一件事。

    就上下文而言,模块一词并不意味着 Gradle 模块,Bob 大叔继续将这个词定义为源文件(在 OO 中我们可以将类视为 Controller)。我将让您研究 Bob 叔叔对 SRP 的真正含义,因为我不再使用该术语,也不想解释它。这些都不是对鲍勃叔叔的不尊重。我很喜欢他的作品。

    回到这个问题,如果不了解有关控制器的更多上下文,我很难回答(它只是处理点击并将它们转发给适当的交互器吗?)。我假设这是一个 Android 应用程序,在这种情况下,我只需将 Controller 和 Presenter 组合成一个类。在我看来,这既不违反鲍勃叔叔的 SRP(关于分离因不同原因而改变的事物),也不会导致类的内聚度低(这涉及到什么是模块/class/function/source 确实)。我意识到这部分是主观的,但在我看来,处理 UI 交互和为 ViewModel 准备返回的后端数据都适合特定 GUI 功能的表示逻辑的角色。

    如果做不到这一点,请忽略我所说的以及图表告诉您的内容,只需查看代码即可。把它们分开真的比分开能解决更多的问题吗?采取相应的行动。

    考虑到您提到的要求,我认为没有任何明智的方法可以完全遵循此图,但如果我真的必须将 Controller 和 Presenter 分开,我会这样做: 在控制器和演示者之间使用观察者(发布者 - 订阅者)模式(或者可能是演示者和交互者......不是我会做的,但这张图也没有反映我通常如何使用交互者)。您可以让所有内容保持松散耦合并避免它们之间的具体引用(即绘制箭头)。

    你可以有一个 Usecase,它的唯一目的是处理鼠标点击并回调它发生的 Presenter。老实说,这似乎是一个荒谬的解决方案。拥有一个封装了在 UI 中递增计数器的业务逻辑的交互器有什么意义?除非您每次都保存该计数器,否则它甚至不适合从术语业务逻辑开始。

    希望对您有所帮助;只是想分享我过去的经验,以防万一。

    【讨论】:

      【解决方案2】:

      ViewModel 的目的是以方便 UI 的形式保存数据。

      如果点击次数是 UI 需要的 - 确实如此,但如果我理解正确,您想要的是使此数据有状态,例如将其保存到数据库并在每次需要增加它时获取。

      从这个角度来看,您应该为您的数据库(存储库)定义一个接口,当然还有一个适当的实现(可能是一个繁重的数据库或只是一个文本文件)。

      最后,您的演示者应该只将最新值(由输出数据介导)投影到 ViewModel。

      【讨论】:

      • 我要问的是例如我们不需要从数据库中获取任何东西,或者在后端或某些逻辑中完成的任何事情,控制器可以直接调用演示者吗?跨度>
      • 从技术上讲,一切皆有可能,包括调用演示者的控制器。但这将违反您要求遵循的图像中表达的架构。
      • 如果我不需要用例,那么正确的方法是什么?
      • 基本上当你没有用例时你就没有架构,所以让控制器创建 ViewModel,仅此而已。
      【解决方案3】:

      遵循鲍勃叔叔的定义。 点击事件应该是控制器的一部分。 视图不应更新 ViewModel,它只能在演示者更新后才能读取。

      所有事件都应该转到控制器,然后控制器应该通过将演示者对象传递给用例来访问用例,并且用例应该调用演示者,后者更新了 ViewModel。

      视图可以同时访问 Controller 和 Presenter。

      或者控制器可以拥有将传递给用例的presenter对象

      【讨论】:

        猜你喜欢
        • 2019-11-01
        • 2018-09-16
        • 2019-03-28
        • 1970-01-01
        • 2016-06-24
        • 2013-05-24
        • 1970-01-01
        • 2019-04-08
        • 2022-01-09
        相关资源
        最近更新 更多