雷顿圆顶 MVC- 为什么在 MVC 中只有一个模型?

8

当Jeremy和Chad发布他们的FubuMvc项目时,他们提到了一个不同的特点,即他们的“Thunderdome原则”:

“Thunderdome原则” - 所有控制器方法都接收一个ViewModel对象(在某些情况下为零个对象),并返回一个单独的ViewModel对象(一个对象进入,一个对象离开)。控制器类永远不会直接暴露给任何与HttpContext相关的内容。看到人们试图编写模拟或存根新的IHttpContextWrapper接口的测试会让我哭泣。同样,控制器方法不返回ViewResult对象,并且通常与所有MVC基础设施解耦。我们早期采用这种策略作为使控制器测试在机械上更简单的方式。它肯定实现了这个目标,但也使控制器代码非常简洁和易于阅读。我们将在KaizenConf上解释这是如何工作的。

他们采用“一个ViewModel(或零)”的方法有什么优势?
3个回答

9
它的主要优点是它是一种约定,并使我们所有的控制器保持一致。这使得我们更容易设置测试"上下文"/固定装置,以在集成测试场景中初始化环境。在大多数情况下,约定等于迅速,因为它从您的设计考虑中消除了许多"如果"情况。
由于我们所有的控制器操作都遵循相同的模式,我们可以假设很多事情,并加速和简化我们的控制器集成测试工作。
不一定有什么问题,将多个参数传递给控制器操作,但我们发现使用实际的模型对象可以为我们提供一些额外的功能,因为模型可以包含简单的逻辑并公开便利属性,这些属性可以简化其自身状态的某些更复杂的方面,等等--基本上,这是拥有任何丰富模型的论据,而不是Thunderdome/OMIOMO模式所特有的。

好的,我肯定可以理解它只是一种惯例所带来的好处。我会在即将到来的项目中尝试这个模型。 - Troy
所有控制器都有16个参数也是一种惯例。惯例本身并不一定是好事。 - liammclennan
@liamclennan 没错。聪明的约定可能是更好的描述方式。幸运的是,没有人提倡愚蠢的约定,但感谢您指出 :) - chadmyers
@chadmyers 我并不是在卖弄学问。你的第一段话说Thunderdome很好,因为它是一个惯例。我只是指出这不是一个有效的论点。 - liammclennan
是的,你有点过于追求细节了。我并不是因为它是一种惯例就说它好,而是因为它是一种好的惯例,所以我认为它很好。追求细节。每个人都知道,你可以遵循惯例做得好或者不好。这是一种好的惯例,使用OMIOMO的东西也因此变得很好。 - chadmyers
@liammclennan - 在否认你之前的吹毛求疵时再次吹毛求疵并不是一个有效的论点。 - nathanchere

0

优点在于您不需要依赖控制器方法外部的任何上下文(例如会话状态)。这使得测试它们变得更容易,因为您不必使用模拟来“模拟”该上下文,但也使其不太实用,因为您必须通过参数传递所有内容。


我完全理解在测试控制器时需要模拟上下文等内容是很痛苦的,但我认为使用 DI 可以缓解这种痛苦。我仍然不明白每个操作都只带一个参数有何帮助。这样做不是把相同的测试问题转移到了模型上吗? - Troy
我认为拥有“一个ViewModel(或零个)”并不意味着你只能有一个参数。我认为你可以有两个,甚至更多。我的理解是Action方法不会从Controller类外部获取任何东西,比如Http上下文。这就是我的理解。 - Dave Van den Eynde
@Dave:不,Thunderdome/OMIOMO 的意图是使方法只有一个或零个输入参数,其中一个参数是丰富的模型(而不是原始类型),它丰富地表示了操作请求。 - chadmyers
还有一件事:那个模型不应该是来自主域模型的实体。 - chadmyers
有何不同之处?该对象遵循与包含所有事件参数的EventArgs对象相同的模式,将所有事件参数保存在单个对象中。 - Dave Van den Eynde
@Dave:也许我们在说同样的事情?我认为方法具有0..1个参数很重要。在这1个参数(即模型内)中,您可以收集从查询字符串、URL、会话、表单提交等获取的其他信息。 - chadmyers

0
“雷区原则”的好处在于简化了控制器。由于将HTTP值映射到对象的工作是在控制器之外完成的,这意味着控制器只做它们应该做的事情。”

模型绑定器将HTTP值映射到控制器之外的操作参数,不是吗? - Troy
我真的不认为它会简化你的设计。它可能会简化控制器,但你仍需要在某处处理它。 - Dave Van den Eynde
特洛伊说Modelbinders会代劳,但它们不能处理一些需要逻辑的情况,这通常由控制器负责。在Thunderdome/OMIOMO中,这在输入模型中实现。 - chadmyers
@Dave Van den Eynde,我简化了设计,因为这样可以让控制器具有单一职责。 - liammclennan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接