16

I have following layers in my solution:

  1. App.Domain
  2. App.Service
  3. App.Core (maybe you call this one App.DataLayer)
  4. App.Web

Software design pattern is not my question, I have following Model in Domain

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

I want to use this model on the view (for example home page) AND I want to use Id, Name & Value, so if I want to create ViewModel, I'll add following:

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

So, is that good idea? or just use Foo instead of FooViewModel?

Mehdi Dehghani
  • 296
  • 2
  • 11
  • I'm not sure I understand this. Isn't the `Model` usually passed to the `View`? Why exactly do you need to recreate the fields of the `Model` in the `View`? If separation of concerns is a goal of `MVC`, under what circumstances would one want to do the same thing with `Model` and `View`? If `ViewModel` is both, why not by extending / composing both `Model` and `View`? – null Aug 09 '15 at 23:14
  • please read my comments on @svidgen's answer – Mehdi Dehghani Aug 10 '15 at 06:44
  • I have a related issue - where validation (required attribute) on the models (and in the database) state certain values must be entered - but in views, those values don't need to be - so I am forced to copy some fields from the models int the view model - rather than referencing the model directly. However on reflection this probably is fine and indeed doesn't violate DRY as they are for different purposes (not too badly anyway). – niico Sep 21 '16 at 21:11

3 Answers3

20

This may look like a violation of the DRY rule initially, but I'd argue that "similar, and even identical, code" isn't necessarily "repetition" if it does something different or is able to change independently. And in the case of view models, the code is defining what the "client" sees, not necessarily the entities and operations the business talks about. So, you're often revealing models to the client or interface that are sort of "incidentally identical." You may change either the business rules and terms or the end user terminology independently of each other.

So, I'd turn the question back on you. If the domain changes, is it acceptable for the "version 1" clients to continue using the old interfaces? Will you ever reveal terms or operations in the interface that aren't part of the "core business rules?" And vice versa?

Those sort of questions in mind, if your view's "function" is strictly to reveal the underlying domain model, yes, this seems like it violates the DRY rule.

Also bear in mind, exposing a view that changes more naturally with model changes can also be accomplished in some languages with member attributes and reflection. (Or with less repetition through other feats of cleverness... But, "cleverness" often fails to justify the repetition it spares you.)

svidgen
  • 13,414
  • 2
  • 34
  • 60
  • Nice mentioned notes (vote up for this), as I said as comment on previous answer, I'm talking about general purpose, imaging, maybe some days later, I decided to add new field/property to `Foo`, so if I used `Foo` as ViewModel too, client will get new property too, so what about if this new one was some security field, (maybe true/false for permission, or something like that), what should I do? – Mehdi Dehghani Aug 09 '15 at 17:09
  • @mehdi you'll need to be more specific about what field you're thinking of adding and why you think it does or doesn't belong in the view. Or in general, what the concern is there. – svidgen Aug 09 '15 at 17:12
  • @mehdi to be clear, if you're worried about end users changing a security value, your domain simply shouldn't allow users to save things they're not authorized to save – svidgen Aug 09 '15 at 17:13
  • Why we using ViewModels? there is some reasons, as we know, one of them is for security, for example, in `User edit form`, we don't need to pass `IsAdmin` field to the client, for keeping this field secure, so this is what I'm worry about. sorry for my bad English. – Mehdi Dehghani Aug 09 '15 at 17:15
  • @MehdiDehghani: Security isn't really a good reason to separate the two objects. The best reason is that the model as viewed in the UI (possibly in multiple formats) is not necessarily the same as the model stored in the database (never in multiple formats and more likely to "model" the business). Even if they look the same now, they are likely to diverge as an application scales; it's better to handle them separately, so there's no temptation to force one model into the other when that time comes. – pdr Aug 09 '15 at 17:21
  • I am confused !, because one of important reason for using ViewModel is security, that's what I read on some articles about using ViewModels. what is your answer to the question, `yes or no`? – Mehdi Dehghani Aug 09 '15 at 17:32
  • @MehdiDehghani: It's not as simple as yes or no, it's more that the security issues with direct access to data model are rare and easily coded around. If security were the only reason to use a View Model, I would suggest other solutions (server-side validation, for example). But I'd recommend a ViewModel for decoupling and it will, almost incidentally, help you protect your data model. – pdr Aug 10 '15 at 00:33
  • @MehdiDehghani could you please share some of those articles? I'd like to understand how a `ViewModel` that has the exact same get/set methods as the `Model` is more secure. – null Aug 10 '15 at 13:10
  • @MehdiDehghani Sure, there can be security advantages. But, it's hard to know what security advantages the author was referring to. For instance, if you have a `User` class in your domain with a `PasswordHash` on it, your `UserView` probably wouldn't contain that field. Exposing it at *any* time could cause to you inadvertently expose it *at any time* -- in a search result, for instance. And that could be pretty bad. – svidgen Aug 10 '15 at 14:20
  • @svidgen so, overall, the answer is yes? – Mehdi Dehghani Aug 10 '15 at 17:12
  • @MehdiDehghani Based on the length of this comment discussion, it sounds like the full detail of what you want to know isn't present in the question body, which is pretty much absent of the security concern. If you want a full answer for the question you didn't ask, I think you need to **ask** the question *in full.* I.e., pose a new P.SE question with a specific focus on whether a View's purpose is security related (e.g., by hiding private fields.). – svidgen Aug 10 '15 at 17:18
  • 1
    Put another way, I think the original question is a full question. The question you're trying to figure out in the comments here is another full question. And comments aren't a good way to get good, quality answers. – svidgen Aug 10 '15 at 17:20
  • You right bro :) our conversation plus your answer give me enough info, I keep the question open for 1 or 2 more days, for probably other answers and ideas, then check your answer as answer. – Mehdi Dehghani Aug 10 '15 at 21:50
2

I would have a view model that contained just one property, a Foo instance. That way, you are not violating DRY according to any definition of it, if Foo changes, your view model automatically sees the change, and you leave yourself free of a direct tie of the view model to the model.

If tomorrow there is a need for the view to show something else as well as the Foo, you can just add a new property, and your view model's intent will still be clear, it contains a Foo and something else, you won't have a mixture of properties from Foo with unrelated other properties.

I wouldn't think of your view model as a FooViewModel, I would think of it in terms of what the view is supposed to display. If it just displays one Foo, then the view model contains one property, a Foo.

Not sure if I explained that clearly. If not, let me know and I'll try and reword it when I'm awake!

Avrohom Yisroel
  • 1,027
  • 10
  • 22
-2

I would say using FooViewModel in this way violates the DRY principal. When you need to make a change to Foo you also have to make a change to FooViewModel. I think you would be better served simply using Foo as the model for your view. I would consider a view model if you need to display things from Foo and something other things. For example, say you need to render some information from Foo and also from Bar.

zero_dev
  • 105
  • 1
  • Please tell me, if I decided to add another field/property to the `Foo`, so because I used `Foo` as ViewModel too, so I have to pass this new field to the view too, I think this is not really good deal, what do you think? – Mehdi Dehghani Aug 09 '15 at 15:35
  • I don't see anything wrong with having the View use only a subset of the data exposed by the model. I think the greater foul is the coupling between `Foo` and `FooViewModel`. Generally, it is not a good idea to have to modify multiple files for a single logical change. – zero_dev Aug 09 '15 at 15:44
  • What about If that added field was a security field, such as some `true/false` value for permission or something like that. – Mehdi Dehghani Aug 09 '15 at 15:47
  • You don't have to expose such fields in the View itself, but you should still make sure the rest of your code does not allow the user to change their security level, just in case a malicious user tries to POST such a change. – Graham Aug 10 '15 at 12:31
  • Sounds like it would be open to mass assignment attacks – Lotok Aug 10 '15 at 14:20