Benefits of strictly separating View and Model? - c#

A colleague of mine doesn't want to bind from the View directly to the Model. For example, in the Model, he has a ObservableCollection and in the View he wants to use it. Instead of directly using it like I would do it (e.g. {Binding Model.Collection} he has another ObservableCollection in the ViewModel which has exactly the same data as the ObservableCollection in the Model. He is synchronizing both ObservableCollections with each other through events.
What are the benefits of his approach? I, personally, disapprove of his approach because it just adds duplicate code and since you have to synchronize the ObservableCollections yourself it's also more error prone. My colleague says he wants to do it this way because then he can change the Model without changing the View.
EDIT:
Some highly upvoted answers [1][2][3] support my in my thinking that it's really okay to bind directly to the Model.

It all comes down to code separation and reusability. Ideally, the View should be completely separated from the Model. If the View doesn’t rely on a specific implementation of the Model, then it can be reused with a different model to present some other data.
So, suppose you have a AlbumView and your current Model is Album, but in future you have decided to also add Movie or Book to you library. you could still use the same AlbumViewo display your movie and book objects. Furthermore, if you want to create a new project that has something to do with albums, you could simply reuse your Album class, because it’s not dependent on any view. That’s the strength of MVVM or MVC.
So for me, I would say, that your colleague is right, because Model naturally reflect the Data Access Layer Entity, where it will be stored and handled. In addition to that, Model may have more properties related to Access data layer such as created indexing. While you ViewModel is only related to the view and the presentation logic of your application. It only reflect what the user is going to see.

I would say using an ObservableCollection in the Model layer is wrong. By adding that you are basically saying "Model object stores data and notifies when it changes".
The role of the ViewModel is to manipulate the Model and provide an interface to the View for presenting the Model.
I believe your colleague is right because he is enforcing separation of concerns such that manipulating the Model should not impact the View.

Related

Should I implement business logic on a Model or a ViewModel

When I'm processing business logic in an MVVM app. Should I do this on the Model or the ViewModel?
For example, if I want to re-calculate costs after an Asset has been re-valued, should I operate on the Model?
Is there an advantage in doing this on the ViewModel instead?
What happens if I have a list of ViewModels, but I want to translate that into a list of Models so I can do some processing? I could expose the Model as a property of the ViewModel (and use that to build the list of Models). But that means that the View will be able to access properties of the original Model
My suggestion is to put logic in a service layer instead.
This is a middle layer between view model and model (which, in a real object oriented paradigm, should only contains properties).
So the correct life circle may be:
View model -> service -> model handling.
This allows also to reuse business logic code through others view model if needed
The Model's purpose is to represent (or model) your business domain. Therefore, business logic by definition goes in the Model, not the ViewModel.
The job of the ViewModel is to expose properties and fields of the Model, and prepare them for consumption by the View.
For instance, picture a banking application. The Model may represent an account. Perhaps the Model has an account balance. The job of the Model may be to track the balance and make sure certain invariants are maintained (such as not allowing a withdrawal that is larger than the balance). The job of the ViewModel may be to turn the balance into a string that is used as a binding in the View.
You want to keep as much logic out of the ViewModel as possible to keep your code reusable and loosely coupled.
Use the model if you are building a web app; and one level bellow the model i.e. the domain level if you are building a LAN/desk app.
Your problem - re-calculate costs after an asset has been re-valued - might not just be a user interface issue. A back-end application might want to do the same (for example, for automatically importing data). And then you have a choice of either duplicating business logic or rewiring to existing one.
Nothing wrong with using the same model for the back-end too. But models -especially disconnected ones- tend to be large data structures because they need to bring with them all data from reference tables (unless you want to do round trips to server and sacrifice your GUI experience). And that might affect performance if model is used.
if you model contain required data for calculation you can use model.if model does not contain the data means create view-model and get data to do the calculation.(With respect to Business logic )
if you want to pass this data to view create View Model It improves code re-use opportunities

mvvm confustion with the model and business layer connection

So I have been searching for a while and all my searches on the model portion are just confusing me.
I have been seeing many examples where the view model has a direct reference to the model and then sets the model's member variables. However isn't the model supposed to be a business object so that the business layer can do calculations with that data?
So...
1) Should I share the model between both UI and the Business layer so both are referencing the exact same objects (shouldn't each layer "hide" their contents from each other in which case this wouldnt be the best).
http://blog.trivadis.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-01-50/1856.distributed_5F00_domain.png
2) Or should the model be in the business layer. Then the UI makes calls from the view model using provided business interfaces to access model info? This way the model itself is hidden from the UI. Similar to option 1's image except there would be some interface accessing the models and services.
3) Or UI does have the model. BUT I can see many occasions where the business layer would need this information resulting in multiple models which look relatively the exact same are made. Imagine that the entire picture below resides in the UI. Then there is a business layer below the model which the model accesses.
http://rarcher.azurewebsites.net/Images/mvvm00.png
The View never has direct access to the Model. The View is connected to the ViewModel via its DataContext.
The ViewModel has direct access to the Model and is able to recover values from the Model and set values into it as well as call methods so that actions occur. But the ViewModel does not have direct access to the View, there could 0, 1 or many View instances all looking at the same ViewModel and it would never know.
The Model does not know about the existence of the ViewModel or View. Therefore you could reuse the Model class in a different project without any dependency on WPF or even a user interface.
How you attach the Model to the ViewModel is up to you. You could pass a reference to the Model into the constructor of the ViewModel. Or provide a separate method or property that is called after the ViewModel is constructed.
For complete separation you would expose the same list of properties on the ViewModel as are present on the Model itself (or just the subset actually needed). The ViewModel can hook into the PropertyChanged event of the INotifyPropertyChanged interface that should be exposed from the Model. As it sees changes it can pass the change onto any watching View via its own properties and its own implementation of the INotifyPropertyChanged interface.
As #Phil Wright states in his answer, the Model should have no knowledge of the ViewModel or the View, so you are free to reuse your Models between different layers. In my experience, Models are generally simple POCOs with no dependencies on other layers.
Whether you reuse your Models between your layers is up to you. If you're using an ORM such as Entity Framework, your Models might be your entity classes. Your business layer might decide to use these entity classes, or you may want to abstract them or aggregate them or do something else with them. At the end of the day what goes in your Models is driven by what you want to store in them and how you want to use them, and SO can't really provide guidance on that because the question is so open-ended.
As far as WPF and MVVM are concerned, I like to think of the ViewModel as being an aggregator of sorts for one or more Models. You generally pass the Model(s) to the ViewModel somehow (through its constructor or whatever): the ViewModel then provides properties and commands that are used by the View (via binding) in order to read and/or change the state of the ViewModel. At some later point, the ViewModel may need to change the state of the Models that it was supplied with, to reflect the changes initiated by the View.
You may find that the Models needed by your business layer are slightly different to the Models used by your ViewModels, and unfortunately you can end-up writing a lot of very similar-looking Model code when this happens. In such cases, Model interfaces may help: there's nothing to say that the Models used by a ViewModel have to be concrete classes. So you could have a single "sort of complex" Model that has all the properties needed by both your ViewModels and your business layer, then expose that Model through two different interfaces (one for each layer) so that properties irrelevant to a particular layer are not visible to it (if that makes sense!).

What to do when Model is exactly the same as ViewModel?

I want to know what is best practice. I have been told to always create ViewModels and never use core Model classes for passing data to Views.
That makes sense.
Lets me separate the things out. But what is Model is exactly the same as ViewModel. Should I recreate another class or just use it.
I feel that I should recreate. Just want to know what the experts say..
You should definitely still create a separate view model, even if it is identical to your domain entity. The view model and the domain entity should be completely independent, i.e. you should be able to change one without the other needing to know or care about the change. Your view model should represent your view and your domain entity should... well... represent your domain entity. They might be identical now but, if either changes, the change in one should not affect the other.
What if your domain model suddenly changes and now has fields that are no longer relevant to your view model? If they aren't separate, you have a problem. Or, worse (and probably more likely), what if your view model suddenly needs more information, from a totally distinct entity? Are you going to break the encapsulation of classes in your domain model with this totally irrelevant information, just to make it accessible in your view?
Keep your solution decoupled and flexible. Use view models.
I would suggest to create a ModelView, by the way. So in this, particular case it would be the same, it would work like a "bridge" between UI and a model, on which data trasmittes.
But it's good for scallability, cause, it's very likely that you would like to add something UI specific to your view model, so it will defer from the model itself more and more.
So general advice: create it by the way, even if now they are the same, cause it helps you scale when you will need it after.
But what is Model is exactly the same as ViewModel. Should I recreate
another class or just use it.
If it's exactly the same you don't need a view model of course. But that is a pretty rare situation.

Passing data to the data layer

My model consists of a single main object that the user can add various other objects too. The added objects are stored in List<object> contained within the main object and it's associated child objects.
So if the project is a house. The user can add a number of Room objects to the house which are stored in List<Room> RoomList. Then each Room can have a number of Furnishings added again stored in each Room List<Furnishing> FurnishingsList
The question is how to implement this in the MVVM approach? When the user adds a new object do i add it to the ObservableCollection in the ViewModel so the view is updated and at the same time add it to the model which is hooked into the VM? Or do i store it in the VM until a save or commit commmand and then pass it to the Model?
In my example i have various editors (each is a user control). So the user can edit the house at a high level, using one editor to add, edit and remove rooms from the house. And, at a lower level, using a different editor to edit each room, adding and removing Furnishings.
So when the user 'Edits' a room say. I produce an EditRoomModelView containing said Room. The user adds, edits and otherwise manipulates the furnishings in that room.
At each command is it best to sync the data in the Model and the ModelViee as above. Or do i shove the changes straight into the Model and have the ViewModel provide only getters on the injected Model properties. This way however adding objects to the Model Lists does not update the view. i would really have to add the data to both the ModelView and the Model at the same time so everything is at the same state.
Appologies for rambling, struggling to find a nice approach to this, anyone uderstand what i'm getting at?
I'm not sure there's a single, good answer. It sounds as though you're debating as to how to maintain coherence - do you have a simple pass-through scheme from the presentation layer, or do you interpose on user requests and have logic in there.
If that is, in fact, the question, there are various factors at play. Do you prefer to do validation in the presentation layer? How complex is the application and how scaleable does it need to be? Do your view models need to be accessed in multiple places?
So, with all that in mind, I can tell you how I personally prefer approaching this problem (specifically, the issue of adding that you mention). I typically like to create view models that describe user concerns with generics such as EditItemViewModel<T> or ListViewModel<T>. So, in the GUI, there would be some kind of listbox of rooms bound to a ListViewModel<Room>. This VM would obviously expose an observable collection, but also commands for Add, Delete, Edit.
So, from my perspective, the presentation layer, view-modelly stuff that this VM is going to do is route requests for other GUI concerns. If you click "Add" to add a room, this VM is responsible for initiating a request, via a command, for whatever screen/window/whatever is necessary for room adding, which will have its own VM. This VM, upon receiving an add request, will pass the generated data transfer object down to the domain where validation will occur and whatever domain operations are necessary. I usually handle this via a service layer. Now, if the domain operation was successful, the service layer will raise some kind of even or callback to let the list VM know that there is a change. When that happens, the list VM re-queries its service and updates its observable collection accordingly. Now, your GUI is consistent with the domain across the board.
The reason I favor this type of layered approach is that all of the business logic occurs in a place 'below' the GUI, and the GUI need not concern itself with this occurrence. Conceptually, GUI just says "here, domain layer, user wants to add this - do all that, and let any interested GUI components know when you're done so that they can refresh themselves".
What I'm describing here will naturally incur some overhead as compared to a simple, pass-through scheme or a scheme in which the VMs just re-expose properties on some model object. But, personally, I think the advantage gained from a decoupling perspective is worth it, especially as you scale up the application. It gives you the ability to fundamentally alter the domain model's internal interactions without changing the presentation layer code a lick.
First: View is a mirror of your DataModel, so always add first to the Model and only after think if it push on Vm or on View.
Second: ViewModel is a bridge that connects your Model with View, but doesn't mean that it has to be structured in a same way Model was made. If you want to show to the user all child collections, you have to expose them like a properties and construct their parent-child relationship internaly in VM or in VM have just "raw" collections and have effective relationship between them in DataModel.
From the application you describe it sounds like your view-model layer does not modify or shape your model significantly. So, I would make the various view-model property setters / getters simple adapters on the wrapped model objects. That way your model will be updated immediately when the view model changes.
However ... if you need to provide 'cancel' functionality, i.e. the user opens a modal form for editing some view model, but then cancels rather than OK's the edit, this simple approach will not work.
The timing of when you commit to the model layer rarely makes much difference because this is typically not a time consuming process. What is more significant is when the model state is persisted. This is often triggered by the explicit invocation of a save command which send the model to a persistence service (file / cloud etc ...)

Master-Detail Split Between Two View Models: Where to put cancel command logic?

Master section of window contains a DataGrid. Details section displays a form allowing editing of record currently selected in master's DataGrid. Grid's SelectedItem is bound to the master vm. When that property changes, the master vm creates a new EditViewModel, exposing it via a property. The details section of the view uses this property as its DataContext.
When implementing commands like cancel, would you put them in the master or details view model?
The details view model is responsible for the user's interactions with a record. One could argue that this responsibility includes deletion. On the other hand, one could argue that the master view is responsible for user interactions with the collection, and, since deletion is modifying the collection, delete functionality should be placed in it.
Thank you,
Ben
Edit: Clarification--by "implementing commands," I mean implementing the code that asks the service layer to perform the requested action.
I think your second argument is much stronger than your first.
Just a personal opinion, but it seems to me like deletion is a concern of the collection, not an individual record.
I agree with Ian's answer but would add that I personally think the distinction between UI logic and model logic is important.
So if the deletion is at this point primarily from the UI list then putting the deletion in the collection VM makes a lot of sense.
As soon as you start to talk about working with the model (deletes of records from a database for example) then the records are probably the correct place for this logic.
Additionally I'd say that this sort of logic affecting the model should then be moved into the Domain Model and out of the View Model, leaving the VMs only responsible for UI logic as much as possible, while the Domain Model grows into a rich expression of the business logic.
Each record only knows of itself. It shouldn't even realize that it's part of a collection, it's an entity in itself. The master VM has a collection of records, so it should be in charge of modifications.
I also agree with David on separating UI logic and business logic, stay away from spaghetti code because if your business model changes, it will break your view model code, plus it keeps with the DRY principle.

Categories