This post is a bit of a personal rant on whether or not to use MVVM. I’m comparing MVVM with my current architecture and try to look at a few pros and cons. Clearly MVVM is not optimal, but there might be parts to borrow.
At the moment I’m doing some heavy refactoring of the IRC client I’m working on. The main reason for this is that I felt the interface between modules and core was not optimal. It was not bad, but it was scattered over many techniques.
For example GUI modules registered GUI factories directly in core or hooked up to events to create GUI depending on if they provided a well-known service or not. In some cases they hooked up to for example Window Create event to be able to add user controls to the new window. Some events modules had to hook up for (like join/part), while others they would be called for (like channel text).
Also the IRC client was using Nimbus.Module which in itself is a great module loading library. However because the IRC client is just as much a playground for me to learn new technology I wanted to start using .Net MEF (Managed Extensibility Framework).
At the same time I wanted to separate all interfaces into a separate .dll so that we later can load (and limit) modules safely in AppDomains without having to reference the whole client, as well as ensuring that the core of the client don’t have to reference any GUI-library. This will make the client easy to port to other platforms, which is an interesting experiment in itself.
So a friend tipped me off about MVVM (Model-View-ViewModel). To be honest it took me quite some time to grasp this concept, which in retrospect is a bit embarrassing seeing how simple it is. I blame poor internet article writers! (It has to be the person explaining it who is at fault when I don’t understand, right?) However Jeremiah Morrill wrote a couple of great blog posts that were straight to the point and easy to understand: Article 1 and article 2. So finally after 3-4 days of reading, thinking and much thanks to Jeremiah I think I’m starting to understand it. It was a bit though to wrap my head around because I tried to adopt it to the real-life scenario of my IRC client project. Its a lovely experience to struggle through learning something new and then have to re-think the whole architecture… This is why we are programmers, right?
Well, hence we come to the point of this blog post. MVVM seems great, but is it right for my IRC client project?
MVVM simplified is View (GUI), ViewModel (class for GUI to bind to) and Model (where data is). MVVM is just a way of thinking/designing your application. Naming your classes properly and following this model will make it easier to maintain, and easy to change GUI.
Through my countless rewrites of the IRC client I’ve been through many different architectures. My latest design is meant to decouple GUI completely from the core. To achieve this the core of the client is for the most part capable of running alone. It needs a little bit input on where to connect and what to do, but the API is capable of running without a GUI. The GUI and all functionality is loaded through modules.
Before my latest refactoring the GUI was left completely to itself. It had to hook up events for anything it needed. Only a few well-known services were provided by the core such as locating and sending text to a window.
The IRC client is built up in a full hierarchy starting with Client instance which contains multiple Server instances, which in turn contains multiple channel instances, etc.
After the refactoring I’m making the core GUI-aware. This means that the core will keep the (unknown) GUI inside its data structure. It does this by having standard interfaces for different things like IServer, IChannel, IUser, ITextWindow, etc. The thought is that the core will invoke the required functionality when required. To populate the core a module would have to register factories for all the GUI services it is offering.
Now the fun question. Move to MVVM? It’s always fun to use new technology/patterns, but is it right for this project?
First of all, we partially have this functionality already. By offering all data (and commands) in a hierarchy (Client->Server->Channel->etc) all we are missing are a few INotifyPropertyChanged events.
However there are parts of MVVM I don’t agree with. Currently any module in the IRC client will receive a reference to its Client object, as well as any other relevant object such as Channel. This gives the IRC client module a very nice API, being able to access any functionality (including other GUI objects/modules) through the hierarchy. MVVM wants this to be done through commands, which by the way is kind of cool enough. Because the IRC client has a lot of events and commands to send (several hundreds) it would increase the number of interfaces/casting/checking/whatever you need to do to craft and execute the command. To be perfectly honest I don’t see the point.
So I’m thinking about a hybrid approach. First of all I add INotifyPropertyChanged to the hierarchy so that GUI can bind directly to branches of the hierarchy. Second I keep the fact that all modules gets references to the hierarchy via the Client object.
Now the only question that remains open is whether the core/hierarchy should have a direct reference (via interfaces) to GUI objects.
If we don’t then we are still able to access the GUI objects through events, though the GUI objects need to hook up to any event they want to react to. Not much difference there (except that multiple GUI objects can hook up to one event.) I think the code for hooking up will be fairly clean. It is up to the module to hook up and create GUI objects.
If we do have GUI references in the core then we will have direct invoke on well-known functions. This doesn’t give any specific benefit though. We wouldn’t need any code to hook up, but we would need to register GUI factories – which is basically the same as hooking up.
Conclusion: Lets try partial MVVM for the IRC client: “MVVM in spirit, not in calling.” or something.