【问题标题】:Loose Coupling Presenter to View in MVP在 MVP 中查看的松散耦合演示者
【发布时间】:2014-01-17 03:31:59
【问题描述】:

我们在这里的一家 Java 商店工作,我们的 Web 应用程序使用 MVP 架构模式的实现。我们的经理来自 .NET 世界,在那里他接触过MVVM 设计模式。我们的经理提倡改变我们的 MVP 实现,包括按照 MVVM 的传统,通过观察者设计模式将 Presenter 与其视图解耦(或松散耦合,取决于您的解释)。我更认为 Presenter 和 View 一起工作以实现一个共同的目标,因此应该耦合。

支持更改的参数之一是对演示者进行单元测试的能力。如果 Presenters 只将视图视为观察者,那么争论就可以了,那么它们可以更容易地进行单元测试。但是与他们的观点强烈耦合的演讲者并不一定难以测试。如果 View 使用Humble View 范式,那么它可以被模拟。最后,可测试性应该是良好设计的标志,而不是设计的驱动力。

我的经理用来支持视图和演示者分层的另一个论点是 MVVM 的假定成熟度。因此,我们应该遵循 MVVM 的教义并适应其对 MVP 的实现。如果我错了,请纠正我,但 MVVM 强加了视图和演示者的(人工)分层,以促进其在控件中的数据绑定。

你能帮我们看看这里的光吗?为什么要使用解耦模型并为此付出代价?我没有看到好处。奥卡姆剃刀说我需要使用解耦的论据,而测试似乎不是其中之一。


澄清:我在这个问题中真正要寻找的是可以打破平衡的论点,支持不了解其观点并在以太中拍摄事件的演示者或有利于通过更直接的耦合了解其视图的演示者,例如简陋的视图接口或直接到类。请注意,演示者可以轻松地通过松耦合和紧耦合来提供多个视图。区别在于 Presenter 与之对话的接口:松耦合时,Presenter 与侦听器类(或事件总线代表)对话,而紧耦合时,Presenter 与视图接口对话。

【问题讨论】:

    标签: design-patterns mvvm architecture mvp


    【解决方案1】:

    更新:

    看起来 TS 并没有询问是否将 interface 而不是 class 传递给 presenter,但 presenter 是否正在通过另一层与 view 通信(我们称之为 observable)。它只是尝试反映WPF 中用于视图管理的MVVM 模式。如果是这样,那么我之前的所有论点都是无效的。

    就个人而言,我认为这种方法很糟糕,并且没有带来很多好处而不是缺点。以下是我想提的几点:

    1. Humble view 已经足够可维护了

      正如 TS 所述,谦虚的观点已经足以创建可测试的类,并且模块化足以分离关注点/责任。您可以看到我的答案的修订表明谦虚的观点已经可以维护。

    2. 它增加了复杂性和学习曲线

      除非您的方法得到 WPF 等内置分布式库的支持,否则您将无法学习该方法。这并不常见,新开发人员会发现很难学习您的设计。

    3. 它降低了代码的可发现性

      我对 WPF 的经验是,如果文件夹结构没有适当的一致,您会发现很难发现演示者(因为它将引用 observable)。 WPF 有一些关于文件夹结构的指南(称为约定),因此了解 WPF 的新开发人员会理解它。

    4. 更难调试

      如果绑定(监听点)被错误地声明,您将很难找到错误。大多数时候,这个错误会给你错误的例外。即使在 WPF 中,新手也很难调试。

    5. 属性更新更难确保无限循环风险更大

      在开发 WPF 期间,我发现很难确保视图和演示者(视图模型)之间的属性更新。 MVVM 监听 Knockout 和 WPF 等变化的设计有更高的发生无限循环的风险(prop A 的变化更新 prop B 的变化,它更新 prop A 等等)。

    6. 您通过了编译器验证

      我不喜欢WPF / MVVM 是编译器无法帮助验证您的绑定。这意味着null referencedata type error只能在运行时级别处理。

    7. 它不适用于 Web 应用程序。

      可观察层在事件驱动的应用程序(例如桌面应用程序甚至移动应用程序)中可能很有用。然而,在基于Request -> Response 结构的网络应用程序中,它只是一个无用的抽象层。我还没有找到任何可以在 Web 和应用程序架构中使用的演示者逻辑。如果它无论如何都会被复制,为什么不让它更简单呢?此外,Humble View 方法可以(不完美,但可以)在 Web 架构中使用。

    8. 无论如何你都需要 BLL

      无论你构建什么架构,你仍然只处理PL级别的代码。您仍然需要在另一层使用BLL,以确保无论 UI 是什么(Web/桌面)都可以重用业务逻辑。

    9. 好处只是又多了一层分离

      我不知道你想在 java 中处理什么。然而,在 WPF 中,我发现修改视图更容易、更安全(就不破坏视图模型/演示者而言)。

    总结:

    使用MVP 使用observable,您违反了KISS / YAGNI。如果你不使用分布式库,你也违反了Reinvent the Wheel。唯一的好处是支持DRY(管理数据绑定),但由于它不能用于Web结构,所以不值得。

    【讨论】:

    • 好的,但是如果演示者使用观察者模式松散耦合,则视图不需要具有接口(除非您正在谈论视图将实现的侦听器接口,这不是我要说的)。如果 Presenter 通过其接口耦合到视图,我仍然认为它与视图紧密耦合,只要它直接调用该接口上的方法。至少在这个意义上,你似乎同意我的观点,不同意我的经理。我说的对吗?
    • 对于具有多个视图的演示者而言,松耦合和紧耦合都是可能的。通过观察者类型的松散耦合,演示者拥有一组稍后将通知的观察者。通过与视图或其提炼界面的紧密耦合,演示者拥有一组视图对象。然后,在这两种情况下都将使用一个集合,以便创建从演示者到视图的一对多映射。
    • 一一回答您的观点:(1)简单易懂,见仁见智。 (2) 卑微的观点也是如此。 (3) 卑微的观点达到了这一点。 (4) 我不认为这是松耦合的论据。这可以通过紧耦合来完成。这是一个简单的问题,我们希望赋予视图多少责任。 (5) 不是松散耦合的论据。紧耦合也可以实现这一点。
    • @MihaiDanila 看起来我在您的解释中遗漏了一些要点。你能解释一下设计电流/将是吗?在我目前的理解中,您将具体的视图类传递给演示者,而不是使用接口。
    • 是的,我说的是问题中的一个界面(即“卑微的观点”)。我在问为什么演示者不应该调用视图接口,而是应该更愿意调度视图必须首先注册的事件。无论哪种方式,我都在寻找一个论点,一个比“MVVM 正在这样做”更好的论点)。为什么我们要为松散耦合付出代价?可测试性和您的其他观点都可以通过谦虚的观点来触摸,并且好处是耦合暴露在接口中,而不是在整个实现中涂抹。那么,为什么要松耦合呢?
    【解决方案2】:

    您和/或您的经理可能会混淆依赖方向和耦合紧密度

    MVVM 和(Passive View)MVP 的本质区别在于,在前者中,由于绑定和命令,ViewModel 基本上不知道 View。依赖关系从 View 到 ViewModel。在 Passive View MVP 中,它采用了另一种方式 - Presenter 指向 View,填充其数据并监听其事件。

    虽然它不需要紧密耦合 - 您可以将 Presenter 耦合到 View 的 抽象,该 View 可以在测试上下文中通过 mock 来体现。这是松耦合。

    话虽如此,我同意你的观点,这两种模式(MVVM 和被动/谦虚视图)大致同样可测试。此外,MVVM 在您可以利用绑定和命令的 .Net 环境中基本上是有效的,这使得该特定模式在 Java 生态系统中成为一种奇怪的调用。 Java 世界中可能存在类似的方法,但它们不称为 MVVM。

    【讨论】:

    • 我认为耦合是通过改变组件依赖的方向来直接影响的,使两者相辅相成。如果演示者依赖于一个视图接口(无论是interface 还是公共类API),那么它不是紧密耦合到它的视图吗?但是假设您在做出区分时是正确的,难道不能说与视图抽象对话的演示者与该抽象紧密耦合,而将事件分派给侦听器的演示者与将要执行的视图松散耦合注册为这些事件的观察者?
    • 我想说一个调度事件的对象根本不耦合到它的侦听器。它不知道它们的存在。可能有数百个不同的听众,或者没有一个人在听它关心的一切。与某物耦合意味着您依赖它来运行,并且该事物的更改可能会影响您,这通常在可维护性方面很糟糕。通过抽象实现的松散耦合消除了对实现细节的坚持,只剩下对契约的依赖。那么你可以说我们与合约紧密耦合,但它是一种侵入性最小的耦合形式。
    • 好的,我可以从这个角度看到耦合和依赖关系,但我仍然无法理解你的论点“可能有数百个听众,或者根本就没有听众”。但是对于与视图紧密耦合的演示者来说,这不是同样的吗?它可以保存零个视图的集合或多个视图中的一个,不管它关心什么。
    • 我觉得耦合必须在比我们通过接口或实现类看到其他组件更抽象的层次上解释:对组件的更改对您的影响越大,您就越耦合它。在一种极端情况下,您可能会耦合到经常变化的低级细节。但这可能适用于接口或没有接口。另一方面,你们之间的耦合非常间接。不需要来自组件的反馈(就像大多数 Observer 实施例一样)会给您额外的松散性。抽象与接口是正交的,它意味着取出细节。
    • 您可以在有或没有界面的情况下执行此操作。回到耦合,我想说观察者模式促进了最松散的耦合形式之一。 Observer 上的一些文本表示同意,称“Observer 促进松散耦合”。此外,关于去/松/紧耦合的定义,例如 Webopedia 上的定义,表明这些概念之间存在灰色阴影 (webopedia.com/TERM/T/tight_coupling.html)。
    猜你喜欢
    • 2013-05-06
    • 2020-10-26
    • 2017-06-05
    • 2011-02-22
    • 1970-01-01
    • 2019-04-17
    • 2013-10-11
    • 2010-10-22
    • 1970-01-01
    相关资源
    最近更新 更多