Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 1, The Model
Before we can make a user interface for a program, we need to know what the program is going to do. Hopefully, we have some logic we’re going to be exposing to our users. Underneath all of the beautiful user interfaces we build there is something that we’re trying to accomplish, some data we’re editing or information we’re conveying. Before we can discuss how to make an effective user experience, we need to define the core information with which we are working.
When we discuss software architecturally, the core elements of our program are the “Model”. The terminology comes from architectural design patterns, and goes back pretty far. The “Model” is the one thing in most user interface patterns that hasn’t changed, and is the same terminology used all the way back with Smalltalk in the 70’s when Trygve Reenskaug first described the Model-View-Controller pattern.
When we’re talking about the Model, we’re talking about the domain-specific data and logic – the “guts” inside the program itself. In an ideal world, the program should be able to, at least theoretically and architecturally, work without the user interface being present at all, provided it has the appropriate information passed to it. The core business logic, in an ideal world, doesn’t need or want to know anything about how it’s being used – that’s outside of its concern.
Your business logic should know about your business, and nothing else. This is key to maintaining an effective separation of concerns within the design of our program. This is also very useful for maintaining a program over time. Keeping the model separate makes it much easier to extend an application into other realms without duplication of code or breaking a deployed application. For example, if your business logic is completely isolated, you could potentially switch, without changing your business logic, from using a desktop, client-side application to using a command line, script based version of your application. In some situations, you can even take the same logic and host it, accessing it remotely via a web page.
In most cases, its easiest to think of the Model as the data. If you are making an application to edit customer information, the customer information (data) is the Model. The model can also encapsulate logic, however. If you have a service that needs to be called as part of your business logic when data is updated, the service itself can be thought of as part of the model. When you talk about your program, when you discuss what functions the program performs, such as it “works on” this (data) or “performs this task” (logic), you are talking about the model. Any time you discuss how the user interacts with the program, however, you are talking outside of the concern of the Model.
I want to mention, as a side note, one other thing here, that I often see as a point of confusion. If you have an application with a full, multi-tier data access layer, all of the data access and logic layers are part of (or under) the Model. For our purposes, we treat data and logic tiers as an internal, private implementation detail of the Model. Here, the business logic layer acts as the Model’s public API, and we use that as our Model. Presentation is separate from the Model, but the things the user "works on" (the data and domain specific logic to manipulate the data) are part of the Model.
For our series, we’re going to work with a simple program that is just an RSS feed reader. When we’re talking about the feed reader applications, all three versions of our application we will develop use the same Model. The public API of the Model is nothing but 2 classes: a Feed and a FeedItem. The Feed class has some properties (Title, Description, etc), as well as a collection of FeedItem instances. The FeedItem class contains properties for information about each item in the feed, including a Title, a Link to the original item, and a Description of the feed item. The Feed class also has some logic – it has a static method that allows it to create a Feed given a Uri.
There is one important thing to remember about our Feed and FeedItem classes – they just describe data, and provide a means to load it. They do not describe, in any way, how to edit or display the data. Because the Model is all about data, and not about presentation or manipulation of that data by the user, we can use the same assembly, unchanged, in all three versions of our application.