I’ve noticed a strong trend of using a ViewModel suffix for classes in the ViewModel of Silverlight and WPF applications.
In practice, I discourage people from using the ViewModel suffix because it’s not logical, and tends to lend to more confusion than understanding. I’ve been trying to track down the source of the suffix to figure out if it’s an official naming guideline or just used in examples to clarify to which set or layer a class belongs. I saw this mentioned a few times as the “John Gossman” naming pattern, and I wondered if that were the case. When I contacted John, he expressed that it was, in fact, just a convention used to clarify an example and not intended as a recommendation.
The ViewModel is really a layer containing a set of classes, no one class can really be “the” model (ignoring façades for now). The problem I’ve run into is that people get confused as to whether the ViewModel is a class or is a set of classes, and when I talk about “the ViewModel” invariably people think I’m talking about a particular class, I have to un-train them a bit in order to clarify what we’re talking about. The other side-effect I have seen is that people tend to overlook things like the built-in converters that are often a better alternative than adding a dedicated class in the ViewModel layer.
A class is in a ViewModel (or Model) in the same way that a person is in a Group. You wouldn’t call a particular person in the group a MaxxGroup though, because a member of the set isn’t the set. It might be a little pedantic, but then I don’t think I’d be a software architect if I weren’t a little pedantic…
I also generally put my ViewModel classes in a folder/assembly/namespace, but tend to name them with a suffix that indicates the pattern they are generally following. ViewModel classes tend to actually be bridges, wrappers, façades, and adapters (much like Collection has a CollectionView in the ViewModel which adds viewstate to the Collection) but the point is that it’s more important to describe what the class actually is, not where it is.
Without this understanding, there is a de facto assumption that “ViewModel” classes should be created for every class in the model, an idea that the ViewModel layer is a necessary abstration rather than an optional layer to adapt classes that are unfriendly to the View. In many cases, that’s exactly the wrong thing to do. My approach to explaining how, in practical terms, to approach the MVVM model with WPF/Silverlight goes something like this:
- Bind to the object in the model. Some objects will bind just fine. But, If the object isn’t binding friendly…
- Use a built-in converter to convert the object to and from something more binding friendly,
- If you just need to get past a method call to something with properties, use an ObjectDataProvider,
- Write a class in the ViewModel and use a converter or custom provider class to adapt the class between the layers.
As an example, in a recent WPF application I wrote, I created two classes in the ViewModel: a DirectoryView and a FileView. I found that I wanted these classes to adapt the binding-unfriendly (because of method calls, primarily) DirectoryInfo and FileInfo classes. (If the binding system handled methods, I could have used the Info classes directly and not added classes to the ViewModel.)
The pattern goes something like this:
public class DirectoryView ///Convert GetFiles() to Files enumerable on DirectoryInfo ///and return bindable FileViews from FileInfo instances. public IEnumerable Files { get { return dirInfo.GetFiles().Select(file => new FileView(file)); } }
With this approach, you can write a FileSystemProvider that generally follows the XmlDataProvider/ObjectDataProvider patterns, which allows the developer to create and set up a static resource in XAML to browse a filesystem in XAML-friendly DirectoryView and FileView classes.
So in terms of a pattern, I would say this, “If you have a set of hierarchical classes in the domain that are method-heavy, write a view adapter that converts property calls to method calls, and wrap the results in further view adapters. If there is no hierarchical force in play, just use a ValueConverter to wrap and unwrap the class.”
At this point, we need to advance the discussion beyond the basics of the MVVM pattern and start creating a set of patterns and vocabulary for the types of classes in the ViewModel (adapter, bridge, provider, view), and guidance like the above on when and how to create them. Sort of a “Design Patterns for MVVM” for developers to draw from, and to identify which forces are observed to guide the solution.