将ViewModel与Model完全相同是个好主意吗


16

我的解决方案中包含以下几层:

  1. 应用域
  2. 应用服务
  3. App.Core(也许您将此称为App.DataLayer)
  4. App.Web

软件设计模式不是我的问题,我有以下模型 Domain

public class Foo {
    public int Id {get;set;}
    public int Name {get;set;}
    public int Value {get;set;}
}

我想在视图(例如主页)上使用此模型,并且要使用Id, Name & Value,因此,如果要创建ViewModel,我将添加以下内容:

public class FooViewModel {
    public int Id {get;set;}
    public int Name {get;set;}
    public int Value {get;set;}
}

那么,这是个好主意吗?或只是使用Foo代替FooViewModel


我不确定我是否理解这一点。Model通常不是传递给View吗?到底为什么你需要重新创建的领域ModelView?如果关注点分离是一个目标MVC,下一个会想要做同样的事情用什么情况下 ModelView?如果ViewModel是两个,为什么不通过扩展/合成都ModelView
空值

请阅读我对@svidgen答案的评论
Mehdi Dehghani

我有一个相关的问题-在模型(和数据库)中的验证(必需属性)状态中,必须输入某些值-但在视图中,这些值不需要输入-因此我被迫从中复制一些字段将模型转换为视图模型-而不是直接引用模型。但是,经过反思,这可能很好,并且确实没有违反DRY,因为它们用于不同的目的(无论如何也不算太糟)。
niico

Answers:


20

最初看起来似乎违反了DRY规则,但我认为,“相似甚至相同的代码”如果执行不同的操作或能够独立更改,则不一定是“重复”。在视图模型的情况下,代码定义的是“客户”所看到的内容,而不一定是企业所谈论的实体和操作。因此,您经常向客户端或接口揭示“偶然相同”的模型。您可以彼此独立地更改业务规则和条款或最终用户术语。

所以,我将把这个问题再次转给您。如果域发生更改,“版本1”客户端继续使用旧接口是否可以接受?您是否会在界面中显示不属于“核心业务规则”的条款或操作?反之亦然?

考虑到这些问题,如果您的视图的“功能”严格是为了揭示底层域模型,是的,这似乎违反了DRY规则。

还要记住,在某些具有成员属性和反映的语言中,也可以公开通过模型更改更自然地进行更改的视图。(或者通过其他聪明事而减少重复……但是,“聪明”常常无法证明重复是合理的,它可以为您省去很多时间。)


尼斯提到了笔记(为此投票),正如我在对先前答案的评论中所说的那样,我谈论的是通用图像,也许是几天后,我决定向中添加新字段/属性Foo,因此如果我用作FooViewModel客户端也将获得新属性,因此,如果此新属性是某个安全字段(对于权限可能为true / false或类似的东西),该怎么办?
Mehdi Dehghani

@mehdi您需要更加具体地考虑要添加的字段以及为什么认为该字段属于或不属于视图。或总的来说,这里有什么问题。
svidgen

@mehdi要清楚,如果您担心最终用户更改安全值,则您的域仅不应该允许用户保存他们无权保存的内容
svidgen

为什么我们使用ViewModels?我们知道有一些原因,其中一个是出于安全性考虑,例如在中User edit form,我们不需要将IsAdmin字段传递给客户端以保持该字段的安全,所以这就是我担心的问题。对不起,我的英语不好。
Mehdi Dehghani 2015年

1
换句话说,我认为原来的问题是一个完整的问题。您要在此处的注释中找出的问题是另一个完整的问题。而且,评论并不是获得优质优质答案的好方法。
svidgen

2

我将拥有仅包含一个属性(一个Foo实例)的视图模型。这样,您就不会违反DRY的任何定义,如果Foo发生更改,则视图模型会自动看到更改,并使自己不受视图模型与模型的直接联系。

如果明天需要视图和Foo一起显示其他内容,则可以添加一个新属性,并且视图模型的意图仍然很清楚,它包含一个Foo和其他内容,您将不需要Foo的属性与其他不相关的属性的混合物。

我不会将您的视图模型认为是FooViewModel,而是根据视图应该显示的内容来考虑。如果仅显示一个Foo,则视图模型包含一个属性,一个Foo。

不知道我是否清楚地解释了这一点。如果没有,请告诉我,我会在醒着时尝试重新命名!


-2

我会说FooViewModel以这种方式使用违反了DRY主体。当您需要进行更改时,Foo还必须对进行更改FooViewModel。我认为将其Foo用作视图模型会更好。如果您需要显示Foo中的内容以及其他内容,我将考虑使用视图模型。例如,假设您需要同时从Foo和渲染一些信息Bar


请告诉我,如果我决定在上添加另一个字段/属性Foo,那么因为我也曾经使用Foo过ViewModel,所以我也必须将此新字段也传递给视图,我认为这并不是一件好事,您认为呢? ?
Mehdi Dehghani 2015年

我不认为让View仅使用模型公开的数据的一部分没有任何问题。我认为Foo和之间的耦合程度更大FooViewModel。通常,对单个逻辑更改必须修改多个文件不是一个好主意。
zero_dev 2015年

如果添加的字段是安全字段,如true/false许可值或类似的值,该怎么办。
Mehdi Dehghani 2015年

您不必在View本身中公开此类字段,但仍应确保其余代码不允许用户更改其安全级别,以防万一恶意用户尝试发布此类更改。
格雷厄姆

听起来可能会受到大规模任务攻击
詹姆斯(James)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.