49

Model View View-Model was developed by Microsoft to target UI development platforms which support event-driven programming, specifically Windows Presentation Foundation (WPF) and Silverlight on the .NET platforms using XAML and .NET languages. In the years since, many Javascript frameworks such as Angular, Knockout and ExtJS have adopted the pattern.

enter image description here

Like most software patterns, MVVM has its appropriate uses, and its abuses. Under what conditions is the use of MVVM appropriate? When is it ill-advised?

4
  • 4
    Sadly, the real world has a lot of complexities that can't be precisely defined. Beyond a certain point, it's not possible to say what it depends on - though each special case is rare, the range of possible special cases is infinite, and they can't all be spotted until they happen. At some point, you just have to be aware of the underlying goals for patterns etc, and able to recognise when those goals will not be achieved. There's no perfect scheme for that either, but experience helps.
    – user8709
    Aug 1, 2011 at 5:31
  • 1
    @Steve314 That's arguable. I'd say it depends on this: don't let MVVM get in the way of a beautiful design, and definitely don't let it stop you shipping your product. Mar 18, 2014 at 15:14
  • @Luke - that's true, but my point was also that you shouldn't let a beautiful design stop you shipping your product. A good design pattern is only good so long as you use it appropriately, and so long as the real world behaves itself.
    – user8709
    Mar 18, 2014 at 16:26
  • @Steve314 Roger that. Mar 19, 2014 at 17:49

10 Answers 10

20

MVVM is intended to be used where complex user interactions using high-fidelity UI's are needed (i.e. WPF).

MVVM is targeted at modern UI development platforms (Windows Presentation Foundation, or WPF, and Silverlight) in which there is a user experience (UXi) developer who has requirements different from those of a more “traditional” developer (e.g. oriented toward business logic and back end development). The View-Model of MVVM is “basically a value converter on steroids,” meaning that the View-Model is responsible for exposing the data objects from the Model in such a way that those objects are easily managed and consumed. In this respect, the View-Model is more Model than View, and handles most if not all of the View’s display logic.

MVVM was designed to make use of specific functions in WPF to better facilitate the separation of View layer development from the rest of the pattern by removing virtually all “code-behind” from the View layer. Instead of requiring Interactive Designers to write View code, they can use the native WPF markup language XAML and create bindings to the ViewModel, which is written and maintained by application developers. This separation of roles allows Interactive Designers to focus on UX needs rather than programming or business logic, allowing for the layers of an application to be developed in multiple work streams.

For UI's where this kind of rich interaction is not needed, MVVM may be overkill; MVP may be a more natural choice. For web applications, MVC is a better fit. For very small applications that will never grow any larger (such as small Winforms utilities), code-behind is adequate.

1
  • 1
    Fast forward a few years: how do you feel about Knockout? I used it after coming from WPF and was pleasantly surprised to find out how lightweight it felt compared to WPF and it's taken away a lot of the "overkill" aspect for me.
    – J Trana
    Nov 22, 2014 at 1:24
15

Sometimes MVVM can be a trap. From my experience it favors CRUD-like applications (forms over data) versus more task-oriented UIs. I'm not saying that it implies bad architecture for the back end/others layers in the application but I have seen a lot MVVM applications coming with "DDD light" architecture. I don't know why exactly maybe because the binding is so easy and it's very simple to setup an application with an ORM and MVVM/Binding using POCO/Anemic domain objects.

2
  • 10
    A developer's lack of imagination is not a failing of the pattern. Task-oriented ViewModels are quite easy to create.
    – Sean
    Nov 26, 2012 at 14:44
  • 6
    You might want to expand some of those acronyms. Nov 22, 2014 at 6:56
14

MVVM is a band-aid for poorly designed data binding layers. In particular, it has seen a lot of use in the WPF/silverlight/WP7 world because of limitations in data binding in WPF/XAML.

From now on, I'm going to assume we're talking about WPF/XAML since this will make things more clear. Lets look at some of the shortcomings that MVVM sets out to solve in WPF/XAML.

Data shape vs UI shape

The 'VM' in MVVM creates a set of objects defined in C# that map onto a set of presentation objects defined in XAML. These C# objects are typically connected to XAML via DataContext properties on presentation objects.

As a result, the viewmodel object graph needs to map onto your application's presentation object graph. That's not to say that the mapping needs to be one-to-one, but if a list control is contained by a window control, then there must be a way to get from the window's DataContext object to an object that describes that list's data.

The viewmodel object graph decouples the model object graph from the ui object graph successfully, but at the expense of an additional viewmodel layer that must be built and maintained.

If I want to move some data from screen A to screen B, I need to mess around with viewmodels. In the mind of a business guy, this is a UI change. It should take place purely in the world of XAML. Sadly, it rarely can. Worse, depending on how the viewmodels are structured and how actively the data changes, quite a bit of data re-routing could be required to accomplish this change.

Working around unexpressive data binding

WPF/XAML bindings are insufficiently expressive. You basically get to provide an way to get to an object, a property path to traverse, and binding converters to adapt the data property's value to what the presentation object requires.

If you need to bind a property in C# to anything more complex than that, you're basically out of luck. I've never seen a WPF app without a binding converter that turned true/false into Visible/Collapsed. Many WPF apps also tend to have something called NegatingVisibilityConverter or similar that flips the polarity. This should be setting off alarm bells.

MVVM gives you guidelines for structuring your C# code that can be used to smooth over this limitation. You can expose a property on your viewmodel called SomeButtonVisibility and just bind it to that button's visibility. Your XAML is nice and pretty now...but you've made yourself into a clerk--now you have to expose + update bindings in two places (the UI and the code in C#) when your UI evolves. If you need the same button to be on another screen, you've got to expose a similar property on a viewmodel that that screen can access. Worse, I can't just look at the XAML and see when the button will be visible anymore. As soon as bindings become slightly nontrivial, I have to do detective work in the C# code.

Access to data is aggressively scoped

Since data generally enters the UI via DataContext properties, it's hard to represent global or session data consistently throughout your app.

The idea of the "currently logged in user" is a great example--this is often a truly a global thing within an instance of your app. In WPF/XAML it's very difficult to ensure global access to the current user in a consistent manner.

What I'd like to do is use the word "CurrentUser" in data bindings freely to refer to the currently logged in user. Instead, I have to make sure that every DataContext gives me a way to get to the current user object. MVVM can accomodate this, but the viewmodels are going to be a mess since all of them have to provide access to this global data.

An example where MVVM falls over

Say we have a list of users. Next to each user, we want to display a "delete user" button, but only if the currently logged in user is an admin. Also, users are not allowed to delete themselves.

Your model objects shouldn't know about the currently logged in user--they will just represent user records in your database, but somehow the currently logged in user needs to be exposed to data bindings within your list rows. MVVM dictates that we should create a viewmodel object for each list row that composes the currently logged in user with the user represented by that list row, then expose a property called "DeleteButtonVisibility" or "CanDelete" on that viewmodel object (depending on your feelings about binding converters).

This object is going to look an awful lot like a User object in most other ways--it may need to reflect all of the user model object's properties and forward updates to that data as it changes. This feels really icky--again, MVVM makes you into a clerk by forcing you to maintain this user-workalike object.

Consider--you probably also have to represent your user's properties in a database, the model, and the view. If you have an API between you and your database, then it's worse--they're represented in the database, the API server, the API client, the model, and the view. I'd be really hesitant to adopt a design pattern that added another layer that needs to be touched each time a property is added or changed.

Even worse, this layer scales with the complexity of your UI, not with the complexity of your data model. Often the same data is represented in many places and in your UI--this doesn't only add a layer, it adds layer with a lot of extra surface area!

How things could have been

In the case described above, I'd like to say:

<Button Visibility="{CurrentUser.IsAdmin && CurrentUser.Id != Id}" ... />

CurrentUser would be exposed globally to all XAML in my app. Id would refer to a property on the DataContext for my list row. Visibility would convert from boolean automatically. Any updates to Id, CurrentUser.IsAdmin, CurrentUser, or CurrentUser.Id would trigger an update to this button's visibility. Easy-peasy.

Instead, WPF/XAML forces its users to create a complete mess. As far as I can tell, some creative bloggers slapped a name on that mess and that name was MVVM. Don't be fooled--it is not in the same class as the GoF design patterns. This is an ugly hack to work around an ugly data binding system.

(This approach is sometimes referred to as "Functional Reactive Programming" in case you're looking for further reading).

In Conclusion

If you must work in WPF/XAML, I still don't recommend MVVM.

You want your code to be structured like the "how things could have been" example above would have it--model exposed directly to view, with complex data binding expressions + flexible value coercions. It's way better--more readable, more writable, and more maintainable.

MVVM tells you to structure your code in a more verbose, less maintainable way.

Instead of MVVM, build some stuff to help you approximate the good experience: Develop a convention for exposing global state to your UI consistently. Build yourself some tooling out of binding converters, MultiBinding, etc that allows you to express more complex binding expressions. Build yourself a library of binding converters to help make common coercion cases less painful.

Even better--replace XAML with something more expressive. XAML is a very simple XML format for instantiating C# objects--it wouldn't be hard to come up with a more expressive variant.

My other recommendation: don't use toolkits that force these kinds of compromises. They will hurt the quality of your end product by pushing you towards crap like MVVM instead of focusing on your problem domain.

19
  • 24
    -1: Most of these points are shallow, and most of the problems can be overcome by using certain WPF features. I think you have totally missed the point of the MVP pattern.
    – Falcon
    Aug 1, 2011 at 7:42
  • 14
    Example: "Herein lies a huge drawback--data often doesn't work that way. The shape of your data may be very different from the shape of your ui." Right - that's why you have a ViewModel in the first place.
    – Falcon
    Aug 1, 2011 at 7:47
  • 8
    This is a little bit too much FUD tbh. I mean, for starters, there is a BooleanToVisibilityConverter in the WPF assemblies, so no need to create one. Then you could use x:Static if you really wanted to bind to static information coming e.g. from the Session. More likely you use things like RelativeSource to access some higher-up VM info. Then many things you'd do with templates and styles solve the issues you're describing. Then you can do multi-bindings. The list goes on...
    – flq
    Aug 1, 2011 at 16:41
  • 8
    I think some of the purpose of the question was lost in this answer and it became a rant on WPF/SL. That answer is mostly made up of difficulties creating a specific implementation not about debating the roles and principles said pattern offers. Also to be honest a lot of things mentioned in this answer just requires more knowledge in the underlining technology that MVVM was attempted. There are solutions for many of the issues mentioned. The role of the ViewModel seems forgotten in this answer. Aug 1, 2011 at 20:03
  • 8
    This seems a bit like a democracy is the worst form of government (except of course for all the previous forms), kind of statement. Of course WPF has issues, but it sure the hell beats winforms. An WPF with MVVM is definitely an easier go than not using MVVM, for anything bigger than a trivial app. Aug 1, 2011 at 20:03
10

I've been a WPF/Silverlight programmer for years building huge applications, such as trading systems, on MVVM.

For me, as the years have gone by, I've learned that strict MVVM eats time and costs money. By strict, I mean rules such as "no code behind".

It's impossible in anything but the most basic form/database app, not to have code-behind.

Your designer will spec something on day one that is not possible with the standard controls, so you must build a series of custom controls, or wrap existing controls, to support the interaction paradigm while working with MVVM.

I've written all kinds of swish UI controls using math, inertia, gestures etc. and its hard work.

But this is all code-behind, it's just not in the view. You have to handle button clicks, scrolling, dragging etc. but its all nicely wrapped up in a set of controls, which somehow makes this code-behind okay.

Its often easier simply to just write the code-behind and clever UI stuff in the view, instead of building up a set of controls just for the sake of it.

The goal of MVVM is to separate application/business logic from UI logic. The binding system and MVVM is a nice way to do this.

The other goals touted, such as XAML designer on one desk, C# programmer on the other, one working in Blend the other in VS, is a fallacy.

Being able to rapidly redesign a UI is another fallacy. It's never happens, its premature optimisation; any major rework needs a lot of work doing to the view models. Tweaking is one thing but quick UI overhauls aren't possible; the view models must fit the interaction paradigm, so the coupling is tighter than you may realise.

For me, I use MVVM to keep my application logic separate (I usually use a testable controller and a set of logicless view models) but whatever code and tricks are needed to make my UI look and act in a sexy way, I don't sweat it.

Else you end up reigning-in your designs, cool animations, etc. just because the idea of how to MVVM-arize it all becomes too mind-boggling.

MVVM, like most things in life, has a sweet spot somewhere between two extremes.

The most important thing in software design is shipping your product early, finding out what features are used, what UI works well, and not writing beautiful code for a product no one uses.

8

I really like MVVM and I find its challenges motivating and see the many benefits, but...

  1. For application or games that require a lot of UI/interaction code to add a lot of custom behaviors while keeping perf up - it is often better to use a bit dirty MVVM - use it when it is useful or in more data centric as opposed to interaction centric areas of the code. Say you want to create a control and move it between different parent controls or otherwise cache it...

  2. It has a pretty steep learning curve, so unless you have time, plan to develop a lot in WPF/SL, have designers skilled in Blend, feel the need to write test code for your UI or otherwise expect to do years of maintenance for your project - it might not pay off.

  3. Not so many designers know Blend, not all project are worth focusing the automated testing on the presentation layer, since it needs to be tested manually anyway and that is how you'll find most important bugs, not by testing your VMs.

  4. It really is an investment. You have to get a grasp of the basics of WPF/SL and XAML first, then figure out the ways to do the bindings right, hook up vs to vms in some order, get your commanding right, pick a framework in most cases which could be problematic due to licensing, build a sippets library to code efficiently, only to find that the platform does not always work well with bindings and needing to build up a library of behaviors that get you what you need.

Overall though - if you overcome all the hurdles and become fairly profficient in the pattern - it all pays back in clarity, maintainability and ... Bragging rights? :)

2
  • I disagree that it has a steep learning curve. One can learn enough about MMVM in an afternoon to be productive with it. Also, knowing Blend is not a requirement for MVVM.
    – Sean
    Nov 26, 2012 at 14:50
  • 6
    @Sean, sorry, I'm on my third day, and still struggling :( Maybe it's because I'm trying to do 'complicated' stuff like opening dialog boxes, or setting the selected item in a treeview from my model...
    – Benjol
    Mar 8, 2013 at 12:53
7

If your application requires that you bind to excessive amounts of data in real time, then MVVM can actually get in the way because it's introducing abstractions that slow the process down and, assuming we are talking about WPF/Silverlight/WP7 right now, the binding engine is currently not that efficient; although enhancements are on the way.

MVVM, as it stands, is also not the only part of the equation you need to consider. Pure MVVM needs to be supported with infrastructure such as the Mediator pattern to allow you to communicate across disconnected ViewModels.

Despite the opinion of blucz above, MVVM is in the line of the GoF patterns. If you take a look at the patterns, MVVM is the equivalent of the Model View Passive Presenter pattern, which appeared at roughly the same time as MVVM. You will often here people complain about the complexity of MVVM purely because they don't understand how to design using it.

Another area I have found problems with MVVM is where you need to incorporate a third party technology that isn't designed to support it (such as the UII framework for MS Dynamics). At times you have to ask yourself whether or not it's worth the pain of "hacking" around the other tech just to work with MVVM.

If you are mixing and matching something like Win Forms into your WPF solution, then that part of the solution is probably not going to be suitable for MVVM as well. I hope this gives you some idea of some areas as to where MVVM isn't applicable.

4

Using MVVM does not make sense when:

  • You are not working with WPF or Silverlight
  • You are testing a concept

That's it. I can't really think of why you would NOT use MVVM when working with WPF/Silverlight, unless you're testing or debugging something in a separate project. I find the design pattern ideal for WPF/Silverlight development because of the way the XAML Bindings work.

The whole point of MVVM is that your entire application is run in your ViewModels, and your Views are simply a pretty layer that users can use to interact with your ViewModels. You want to click a button, you're actually running a ViewModel method. You want to change the page, you're actually changing the CurrentPage property in the ViewModel.

I use MVVM for all WPF/Silverlight development, even small, simple single-page projects, although how I use MVVM is different based on the size of the project and what I need. The one time I did a small app without MVVM, I ended up regretting it (it later got refactored to use MVVM while adding an update)

3

I did some work for a client on a project that was code-behind with an attempt to convert to MVVM tossed in and it was a giant mess. That's not to say all code-behind projects are a mess. The views would error or crash Blend which caused problems for the designers.

I've dabbled with RoR and pretty much skipped doing anything with ASP.NET Webforms but when ASP.NET MVC came out I tried to learn as much as I could, often using the ASP.NET MVC In Action books and codecampserver as a reference. Although it's a different pattern I use many of the things I learned from the In Action books in SL/MVVM development.

When I started working with Silverlight I was surprised at how naked it was and it felt like a requirement to choose one of the many frameworks available to dress it up. I see this as a problem with people giving up on learning MVVM.

I started with the excellent MVVM-Light which helped me get a sold grasp of the pattern. I later started working with Caliburn Micro and then lights went on. To me Caliburn Micro is like using ASP.NET MVC over ASP.NET Webforms. So, even for small sample applications I create the project, NuGet CM, and I'm off and running. I follow the ViewModel first approach and keep my Views dumb and easy to work with in Blend. My VM's are testable if you're in to that and with CM it's pretty easy to sling around complex screen layouts.

2

You may enjoy checking out this alternative. This option sidesteps the WPF way of databinding, datatemplates, and MVVM. This option is more like the old, simple, dependable WinForms designer.cs approach.

WPF Composites

http://wpfcomposites.codeplex.com/

Here, concise C# code-behind for WPF is produced by overlaying a simple matrix on top of the UI via grid-based composites. If a modern XAML UI only contains a few text labels and a listbox of photos, why can't this be defined by the simple line of code: grid.AddText( guid, x coordinate, y coordinate) ? Note, this isn't on a canvas, but still within the WPF containers: grid, dockpanel, etc. WPF is hugely powerful. This approach merely leverages this.

Developers don't typically mind matrices and indices. Start with a coarse-grained container level defined by the GUID's of data transfer objects (DTOs) or POCO's, then compliment these keyed containers by a finer-grained matrix of potential rows and columns within?

The above codeplex project introduces this approach by starting with the ListBox control but is expanding to cover all WPF composite controls. For instance, each listboxitem is a composite added with a GUID (a composite ties one-to-one to a class), then inside of this item there is a Grid on which child UI elements (children tie one-to-one to properties in a class) may be added at will via code-behind. Children might be textblocks or images.

The idea is to leverage indices and a well-defined UI Element structure (it forces a PresentationFramework.Aero themed ListBox as the base to start from) instead of datatemplates. This new approach purposely limits what can be done but by so doing yields concise, robust C# code-behind that is intuitive. No need to hunt for control template solutions for styling a scrollbar or to clutter a solution with multiple data templates for simple tasks.

-2

MVVM is based mostly around the UI framework that I'm using. So with something like WPF or Silverlight that has a paradigm based around binding to a datacontext, that datacontext could always be called a view model.

So the question to me is when do you build a big fat separate class that is the view model for this control/window/application and when can you get away with using the objects that are already built.

So we've got a classic question about adding a layer of abstraction. the VM is going to add weight, inertia and structure to a project. It'll make it easier to build off of, but harder to change and longer to build. None of those things readily quantifiable.

For a cheap answer, MVVM is not appropriate for command line apps or web services :)

Not the answer you're looking for? Browse other questions tagged or ask your own question.