我们在Java商店中工作,我们的Web应用程序使用MVP架构模式的实现。我们的经理来自一个.NET世界,在那里他已经接触到了MVVM设计模式。我们的经理提倡在我们的MVP实现中进行更改,包括演示者应该通过观察者设计模式,按照传统的MVVM,与它的视图分离(或松散耦合,取决于您的解释)。我更多的观点是,演讲者和视图共同工作以实现一个共同的目标,因此应该结合起来。
支持这种变化的论点之一是单元测试演示者的能力。如果演示者只将视图视为观察者,那么可以更容易地对它们进行单元测试。但是,与他们的观点紧密结合的演讲者并不一定很难测试。如果视图使用谦逊的视图范式,那么它可以被模仿。最后,可测试性应该是良好设计的一个症状,而不是设计的驱动因素。
我的经理用来支持分层视图和表示者的另一个论点是假定的MVVM成熟度。因此,我们应该遵循MVVM的教义,并适应MVP的实现。如果我错了,请纠正我,但MVVM强制(人为)对视图和表示者进行分层,以便在控件中方便其数据绑定。
你能帮我们看看这里的灯吗?为什么我们要使用一个分离的模型并为此付出代价呢?我没有看到好处。奥卡姆的Razor说,我需要参数来使用去耦,而测试似乎不是其中之一。
澄清:我在这个问题上真正寻找的是那些能够使平衡点偏向于一个不了解其观点并在以太中拍摄事件的演示者的论点,或者偏向于一个通过更直接的耦合了解其观点的演示者的论点,比如一个不起眼的视图接口或直接指向类的观点。请注意,演示者可以通过松耦合和紧耦合轻松地提供多个视图。不同之处在于演示者所说的接口:使用松耦合时,演示者与侦听器类(或事件总线代表)进行对话,而使用紧耦合时,演示者与视图接口进行对话。
更新:
看起来TS并没有询问是否将interface而不是class传递给presenter,但是presenter是否通过另一层(我们称为observable)与view通信。它只是试图反映用于视图管理的WPF中的MVVM模式。如果是这样的话,那么我之前的所有论点都是无效的。
就我个人而言,我认为这种方法是不好的,不会带来很多好处而不是缺点。以下是我想说的要点:
Humble view已经足够维护了。
正如TS所述,谦虚的观点已经足以创建可测试的类和模块化,足以将关注点/责任分离。你可以看到我的回答的修改,说谦虚的观点已经可以维护了。
它增加了复杂性和学习曲线
除非您的方法得到内置分布式库(如WPF)的支持,否则您将注定要学习这种方法。这是不常见的,新开发人员会发现很难学习您的设计。
它降低了代码的可发现性
我对WPF的经验是,如果在文件夹结构上没有适当的协议,您将很难发现演示者(因为它是指可观察的)。WPF有一些关于文件夹结构(称为约定)的指导方针,因此理解WPF的新开发人员将理解它。
更难调试
如果绑定(监听点)声明错误,您将很难找到错误。大多数时候,这个错误给了你错误的例外。即使在WPF中,新用户也很难调试。
更难确保财产更新,无限周期风险更大
在开发WPF的过程中,我发现很难确保视图和演示者(ViewModel)之间的属性更新。MVVM设计听取诸如淘汰和WPF等变化,具有更高的无限循环发生的风险(Prop A中的变化更新Prop B,更新Prop A等)。
您已通过编译器验证
我不喜欢使用WPF或MVVM,因为编译器无法帮助验证您的绑定。这意味着null reference和data type error只能在运行时级别处理。
它不能实现到Web应用程序。
可观察层在事件驱动的应用程序(如桌面应用程序甚至移动应用程序)中可能很有用。然而,在基于Request -> Response结构的Web应用程序中,它只是一个无用的抽象层。我还发现了任何可以在Web和应用程序体系结构中使用的演示者逻辑。如果它无论如何都会被复制,为什么不让它更简单呢?此外,Humble view方法在Web体系结构中也可以使用(不完全,但可以)。
你无论如何都需要BLL
无论您构建什么体系结构,您仍然只处理PL级别的代码。您仍然需要在另一层中使用BLL,以确保业务逻辑可以被重用,不管UI是什么(web/desktop)。
好处只是另一层分离
我不知道你想用Java做什么。但是,在WPF中,我发现修改视图更容易、更安全(就不破坏视图模型/演示者而言)。
总结:
当MVP使用observable时,您违反了KISS/YAGNI。如果不使用分布式库,也会违反Reinvent the Wheel。唯一的好处是支持DRY(用于管理数据绑定),但是由于它不能用于Web结构,因此它的好处是不值得的。
- 好的,但是如果演示者使用观察者模式松散地耦合在一起,那么视图就不需要有接口(除非您谈论的是视图将实现的侦听器接口,这不是我所说的)。如果演示者通过它的接口耦合到视图,我仍然认为它与视图紧密耦合,只要它直接调用该接口上的方法。至少在这个意义上,你似乎同意我的观点,也不同意我的经理。我说的对吗?
- 对于具有多个视图的演示者来说,松耦合和紧耦合都是可能的。对于观察者类的松耦合,演示者持有一组观察者,稍后将通知这些观察者。通过与视图或其蒸馏接口的紧密耦合,演示者持有一组视图对象。在这两种情况下都将使用集合,以便创建从演示者到视图的一对多映射。
- 一个接一个地回答你的观点:(1)用谦虚的观点容易说话。(2)谦逊的观点也是如此。(3)谦虚的观点可以做到这一点。(4)我不认为这是松耦合的论点。使用紧密耦合也可以做到这一点。这是一个简单的问题,我们要对这个观点负多大的责任。(5)不是松耦合的论据。紧密耦合也能做到这一点。
- @Mihaidanila看来我在你的解释中遗漏了一些要点。请你详细解释一下目前/将来的设计方案好吗?在我目前的理解中,您正在将具体的视图类传递给演示者,而不是使用接口。
- 是的,我在讨论这个问题中的一个接口(即"谦虚的观点")。我在问演示者为什么不喜欢调用视图界面,而更喜欢调度视图必须首先注册的事件。无论哪种方式,我都在寻找一个比"MVVM就是这样做"更好的论点。为什么我们要为松套付钱?可测试性,以及您的其他观点,都是以一种谦逊的观点来进行接触的,并且额外的好处是耦合暴露在一个接口中,而不是在整个实现过程中被涂抹。那么,为什么是松耦合呢?
- 我不想把你弄糊涂,所以把这作为我之前澄清的脚注。当然,在实践中,我们不会疯狂使用视图接口,直到有必要这样做为止。如果演示者需要测试,而视图无法测试(顺便说一句,我们使用vaadin,所以我们的大多数视图可能都可以进行单元测试),那么您可以提取一个接口。当然,即使在混合中没有真正的接口,View类仍然有一个接口(即,公共方法),我们仍然保持谦虚(即抽象、高层次),并且我们可以很容易地变成Java接口。
- 请澄清一件事:目前,您已经让演示者直接与Interface对话(在View中实现),然后您的经理要求使用Observable而不是View Interface?
- 正确的,视图注册为演示者的侦听器,演示者使用可见项发送事件。(此外,根据MVVM,视图不直接与模型对话,所有这些都意味着分层情况:模型->演示者->视图),每个层都不知道上面的层。层次感很好,但绝对不是我强迫自己设计的。为什么视图和演示者不应该互相了解?:)
- 好的,我会在得到你的澄清后更新我的答案。
您和/或您的经理可能会混淆依赖方向和耦合紧密性。
MVVM和(被动视图)MVP的本质区别在于前者,由于绑定和命令,视图模型基本上不了解视图。依赖关系从一个视图转到另一个视图模型。在被动视图MVP中,它采用了另一种方式——演示者指向视图,填充视图数据并监听其事件。
不过,它不需要是紧密耦合的——您可以将演示者与一个视图的抽象结合起来,这个视图可以在测试上下文中通过模拟来体现。这是松耦合。
也就是说,我同意您的观点,即两种模式(MVVM和被动/谦虚视图)大致都是可测试的。另外,MVVM在.NET环境中基本上是有效的,您可以利用绑定和命令,这使得特定模式在Java生态系统中是一个奇怪的调用。Java世界中可能存在类似的方法,但它们不被称为MVVM。
- 我认为,改变组件依赖关系的方向会直接影响耦合,从而使两个组件实现协同工作。如果演示者依赖于视图接口(无论是interface还是公共类API),那么它是否与视图紧密耦合?但是,假设你在区分你所做的事情上是正确的,那么你是否也不能说,一个与视图抽象进行对话的演示者与该抽象紧密耦合,而一个将事件发送给监听者的演示者与那些将注册为这些事件的观察者的视图松散耦合?
- 我说的是dispatches事件对象是耦合到在其所有的听众。它有没有他们的存在的概念。有可能是数百个不同的听众,听所有的信息或不关心。被耦合到的东西,你可以运行它依赖均值的变化,这可能影响你的事情中,都是沐浴在维修性术语。通过松散耦合的abstractions removes坚持到实现细节,只留下"on a合同。然后你可以说我们tightly耦合到一个合同,但它是一个最小侵入形式的耦合。
- 好吧,我可以看到这光耦合和依赖关系,但我仍然不能消化你的论点是"有可能是所有的听众或学习不关心它。"但不相同的申请tightly A耦合到它的主持人的视图?它可以保持一个零或收集的许多视图视图,它为所有关心。
- 我觉得在一个耦合必须理解抽象水平比其他组件是否在湖或通过接口实现类的变化:更多的耦合组件冲击你,你看到它。在一个极端,你可能是耦合到低级别的细节往往是变化的。但这可能是真的,没有一个接口或。在其他的,你是非常间接的耦合。不需要的反馈从组件(一个embodiments样给你额外的looseness(观察者)。抽象是正交到接口和它的均值,以"细节。
- 你可以这样做有或没有接口。回到耦合说,I’d the Observer模式的推出一个loosest形式的耦合。一些文本在"观察者观察者同意,stating促进松散耦合"。因此,定义的松/紧/耦合,如在一webopedia suggest是有阴影(灰度之间的长期webopedia.com论文概念/ / T / N _ coupling.html)。
- "但不相同的申请tightly A耦合到它的主持人的视图?它可以保持一个收集的许多视图视图或零烦恼",所有的信息在我的经验,通常只有一个主持人想一景。如果视图是不有在运行时,它会导致a零异常。
- 我同意,有更多的不只是松散的耦合的方式实现abstractions /接口。然而,我相信这是一个问题的具体的例子。I don’t认为依赖determines耦合指南(和可维护性(气密性)——这里的视图,在视图模型取决于A和A是取决于主持人的观点,你能告诉这是更松散的耦合关系是?
- 那是个主持人测试的努力。如果你依赖于演示者视图,那么你必须提供更多或更少的支持,因此模拟视图隐藏自己的interface外部Java类。但如果视图取决于主持人的主持人是decoupled感谢酒店,例如,没有观察者,然后查看mocks是必要的。arguably你更多的国家比单元测试presenters视图。我的问题是:美国著名主持人使用松散耦合(通过强大的抽象视图),或解耦(通过观察)?(你想使用的术语),你会使用吗?
- 在这样的差分测试数据可以被用来作为论据的去耦通过观察测试,但当然不只是为achievable去耦从主持人的视图。这些问题是矿山一个皆伐那里不是A的答案吗?奥卡姆剃刀应该到这里来救援,这在我的脑海里会投票反对使用观察者?
- 奥卡姆剃刀)坦率地说,事实上,我的印象是,你的经理suffers一些孩子从"新扫帚征"。需要有一个模型视图不是足够的福利是席卷到整个A表示层是空白,这是MVVM带来其他问题(MVP mocks担保,测试使用一个主持人pushes视图数据,在保证等效不MVVM视图到视图模型中的变化listens correc地)
- 除非,也就是说,单元测试包括侦听器注册,这使得该方面与观察者模式一样可测试。通过观察器分离的一个更大的问题是,它似乎允许视图中受支持的功能集滑动,迫使演示者提供视图可能需要的超集。似乎实际观点的现实仍然会对陈述者施加类似于直接耦合所施加的力。不管怎样。
- 有趣的是,我经理的模型可以简化某些案例。如果视图需要进入一种模式,包括更改控件的启用状态和更改表中的数据(可能我们正在更改筛选模式),那么在我的模型中,视图必须告诉演示者更新数据并告诉视图更改模式,或者更糟的是,它会更改模式本身,希望演示者更改数据。在他的模型中,视图控制了所有这些,只是向演示者询问新模式的数据。