Model View ViewModel

From Wikipedia, the free encyclopedia - View original article

Jump to: navigation, search

The Model View ViewModel (MVVM) is an architectural pattern used in software engineering that originated from Microsoft as a specialization of the Presentation Model design pattern introduced by Martin Fowler.[1] Largely based on the model–view–controller pattern (MVC), MVVM is a specific implementation targeted at UI development platforms which support event-driven programming, specifically Windows Presentation Foundation (WPF) and Silverlight on the .NET platforms using XAML and .NET languages. Technically different, but similar, Presentation Model design patterns are available in HTML5 through AngularJS,[2][3] KnockoutJS, Ext JS,[4] Vue.js,[5] and for Java the ZK framework (Model-View-Binder).

MVVM facilitates a clear separation of the development of the graphical user interface (either as markup language or GUI code) from the development of the business logic or back end logic known as the model (also known as the data model to distinguish it from the view model). The view model of MVVM is a value converter[6] 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 (though the demarcation between what functions are handled by which layer is a subject of ongoing discussion[6] and exploration). The view model may also implement a mediator pattern organising access to the backend logic around the set of use cases supported by the view.

MVVM was designed to make use of data binding functions in WPF to better facilitate the separation of view layer development from the rest of the pattern by removing virtually all GUI code (“code-behind”) from the view layer.[7] Instead of requiring user experience (UX) developers to write GUI code, they can use the framework markup language (e.g., XAML) and create bindings to the view model, which is written and maintained by application developers. This separation of roles allows interactive designers to focus on UX needs rather than programming of business logic, allowing for the layers of an application to be developed in multiple work streams for higher productivity. Even when a single developer works on the entire code base a proper separation of the view from the model is more productive as the user interface typically changes frequently and late in the development cycle based on end-user feedback.

In 2005, John Gossman, currently one of the WPF and Silverlight Architects at Microsoft, unveiled the Model-View-ViewModel (MVVM) pattern on his blog. MVVM is identical to Fowler's Presentation Model, in that both patterns feature an abstraction of a View, which contains a View's state and behavior. Fowler introduced Presentation Model as a means of creating a UI platform-independent abstraction of a View, whereas Gossman introduced MVVM as a standardized way to leverage core features of WPF to simplify the creation of user interfaces. In that sense, I consider MVVM to be a specialization of the more general PM pattern, tailor-made for the WPF and Silverlight platforms.

The MVVM pattern was conceived to support WPF and Silverlight, both pieces that debuted with the .NET Framework 3.0 which was released on 21 November 2006. This pattern is now being more broadly applied in other technology domains, such as happened with the earlier MVC or Model View Presenter (MVP) patterns.

Several Microsoft architects working on WPF have written extensively about MVVM in online media, including creator John Gossman, Microsoft MVP Josh Smith, and Microsoft Program Manager Karl Shifflett.

As the understanding of the pattern disseminates through the industry, discussion continues regarding what tools can be developed to support the pattern, selection of where to place different kinds of supporting code in the pattern, the best methods for data binding, and how to expose data within the view model, how appropriate the pattern is for use within JavaScript, and other topics.

More recently the pattern has been described also as model-view-binder (MVB).[8] This is the first reported implementation of the pattern outside of the Microsoft stack, namely using ZK/Java.

Notable JavaScript implementations of this pattern include Knockout.js, Vue.js, etc.

Pattern description[edit]

Broadly speaking,[7][9][10] the model-view-viewmodel pattern attempts to gain both the advantages of separation of functional development provided by MVC as well as leveraging the advantages of data bindings and the framework by binding data as far back (meaning as close to the pure application model) as possible while using the binder, view model, and any business layer’s inherent data checking features to validate any incoming data. The result is that the model and framework drive as much of the operations as possible, eliminating or minimizing application logic which directly manipulates the view (e.g., code-behind). Whilst the pattern was pioneered at Microsoft, as a pure concept it is independent of any given implementation. As such the pattern can be used in any language and with any presentation framework that provides a declarative data binding capability.

Elements of the MVVM pattern[edit]

Model: the model refers to either (a) a domain model which represents the real state content (an object-oriented approach), or (b) the data access layer that represents that content (a data-centric approach).

View: as in the classic MVC pattern, the view refers to all elements displayed by the GUI such as buttons, labels, and other controls. This is typically called the presentation layer. With Microsoft .NET, this is typically done using cshtml and most recently the Razor syntax.

View model: the view model is a “model of the view” meaning it is an abstraction of the view that also serves in mediating between the view and the model which is the target of the view data bindings. It could be seen as a specialized aspect of what would be a controller (in the MVC pattern) that acts as a converter that changes model information into view information and passes commands from the view into the model. The view model exposes public properties, commands, and abstractions. The view model has been likened to a conceptual state of the data as opposed to the real state of the data in the model.[11] The term "View model" is a major cause of confusion in understanding the pattern when compared to the more widely implemented MVC or MVP patterns. The role of the controller or presenter of the other patterns has been substituted with the framework binder (e.g., XAML) and view model as mediator and/or converter of the model to the binder.

Binder: the use of a declarative databinding and command bind technology is an implicit part of the pattern. Within the Microsoft stack this is the XAML technology.[12] Essentially this architectural component frees the developer from being obliged to write boiler plate logic to synchronise the view model and view. It is the organisation of code to make best use of this capability which distinguishes the pattern from both MVC and MVP. When implemented outside of the Microsoft stack the presence of a declarative databinding technology is a key enabler of the pattern.[8][13]

An implementation of the view model[edit]

Snippet: here is a simple implementation of the pattern realized using TDD (test-driven development) on WPF How to implement MVVM (Model-View-ViewModel) in TDD, on Code MSDN.

An implementation of the view model in C#.

 public class CustomerViewModel : ViewModelBase<CustomerViewModel> {     private readonly IDialogService dialogService;     private Customer currentCustomer;     private int i;       public ObservableCollection<Customer> CustomerList { get; private set; }     public ICommand AddNewCustomer { get; private set; }       public CustomerViewModel()     {         CustomerList = new ObservableCollection<Customer>();         AddNewCustomer = new RelayCommand(PerformAddNewCustomer);     }       public CustomerViewModel(IDialogService dialogService) : this()     {         this.dialogService = dialogService;     }       public Customer CurrentCustomer     {         get { return currentCustomer; }           set { SetProperty(ref currentCustomer, value, x => x.CurrentCustomer); }     }       private void PerformAddNewCustomer()     {         CustomerList.Add(new Customer { Name = "Name" + i });         i++;           if (dialogService != null)         {             dialogService.Show("Customer added");         }     } } 

Snippet: here is a simple implementation of the pattern realized in Java using the ZK framework from the ZK ToDo2 patterns demo application:

 public class ZkToDoViewModel {       protected ReminderService reminderService;       public void setReminderService(ReminderService reminderService) {         this.reminderService = reminderService;     }       protected ListModelList<Reminder> reminders = new ListModelList<Reminder>();       public ListModelList<Reminder> getReminders() {         List<Reminder> rs = this.reminderService.findAll();         this.reminders.clear();         this.reminders.addAll(rs);         return this.reminders;     }       protected Reminder selectedReminder = new Reminder();       public Reminder getSelectedReminder() {         return this.selectedReminder;     }       @NotifyChange     public void setSelectedReminder(Reminder reminder) {         this.selectedReminder = reminder;     }       @Command     @NotifyChange({"reminders","selectedReminder"})     public void delete() {         if (this.selectedReminder.getId() != null) {             try {                 this.reminderService.delete(selectedReminder);                 this.selectedReminder = new Reminder();             } catch (EntityNotFoundException e) {                 // no doubt someone else deleted it at the same time. nothing to do.              }         }     }       @Command     @NotifyChange({"reminders","selectedReminder"})     public void save() {         if (this.selectedReminder.getId() != null) {             try {                 this.reminderService.merge(selectedReminder);             } catch (EntityNotFoundException e) {                 // hum. some else deleted this. should really send this                 // up to the user and ask them to reload the page.                  e.printStackTrace();             }         } else {             this.reminderService.persist(this.selectedReminder);         }     }       @Command     @NotifyChange({"reminders","selectedReminder"})     public void create() {         this.selectedReminder = new Reminder();     } } 

Snippet:It is perhaps easier to understand the MVVM pattern in languages that are already event driven, like Javascript.[14]


A criticism of the pattern comes from MVVM creator John Gossman himself,[15] who points out that the overhead in implementing MVVM is "overkill" for simple UI operations. He also states that for larger applications, generalizing the View layer becomes more difficult. Moreover, he illustrates that data binding in very large applications can result in considerable memory consumption.