The Model-View-View-ViewModel (MVVM) template is common in many XAML applications. (MVVM is very similar to Fowler’s description of the Model-View-View-ViewModel template, but it is adapted to XAML.) The problem with the MVVM pattern is that it can inadvertently lead to applications that have too many layers and too many selections. These motivations for MVVM are.
- Clear division of areas of responsibility. It’s always a good idea to divide a problem into smaller parts, and a pattern like MVVM or MVC is a way to divide an application (or even a single control) into smaller parts: the actual view, the logical model of the view (the view model), and the application logic independent of the view (the model). Specifically, it is a popular workflow for designers to own the view using one tool, developers own the model using another tool, and development integrators own the view model using both tools;
- Modular Testing. Modular testing of the view model (and therefore the model) is independent of the view, thus not relying on creating windows, input data, etc. By keeping the view small, you can test most of the application without creating a window;
- Flexibility to change user interaction. A view tends to show the most frequent changes and the most recent changes, as user interaction is customized based on end-user feedback. By keeping the view separate, these changes can be deployed faster and with less processing in the application.
There are several specific definitions of the MVVM pattern and third-party platforms that help implement it. But strict adherence to any variant of the pattern can lead to applications with far more overhead than can be justified.
- XAML data binding (an extension of {Binding} markup) was designed in part to enable model or view templates. But {Binding} brings with it a non-trivial working set and CPU overhead. Creating a {Binding} leads to a series of selections and updating the target binding object can lead to reflection and boxing. These problems are eliminated with the {x:Bind} markup extension, which compiles bindings at build time. Recommendation. Use {x:Bind};
- It is popular in MVVM for connecting Button.Click to a view model using ICommand such as the common DelegateCommand or RelayCommand helper elements. These commands are optional selections, however, including the CanExecuteChanged event listener, adding to the working set, and adding during launch or navigation for a page. Recommendation. As an alternative to using the ICommand convenience interface, it is recommended that event handlers be placed in code and attached to view events and invoke the command in the view model when these events occur. In addition, additional code should be added to disable the button if the command is not available;
- It is popular in MVVM to create a page with all possible UI configurations and then collapse parts of the tree by binding the Visibility property to properties in the virtual machine. This adds unnecessary startup time and possibly to the working set (since some parts of the tree never become visible). Recommendations: Use the x:Load attribute function or the x:DeferLoadStrategy attribute to defer unnecessary parts of the tree out of startup. Also, create separate custom controls for different page modes and use code to store only the controls you need.
C++/CX recommendations
- Use the latest version. There are ongoing performance improvements to the C++/CX compiler. Make sure your application is built with the latest toolkit;
- Disable RTTI (/GR-). RTTI is enabled by default in the compiler, so if your build environment doesn’t toggle it, you’re probably using it. RTTI has significant overhead, and unless your code has a deep dependency on it, you should disable it. The XAML platform does not require code to use RTTI;
- Avoid heavy use of ppltasks. Ppltasks are very handy when calling WinRT’s asynchronous APIs, but they have a significant code size overhead. The C++/CX team is working on a language function, wait, which will provide much better performance. At the same time, balance the use of ppltasks in hot code paths;
- Avoid using C++/CX in the business logic of the application. C++/CX is designed for easy access to the WinRT APIs from C++ applications. It uses shells that have overhead. You should avoid C++/CX inside the business logic or class model and reserve it for use within code boundaries and WinRT.