A Model View Of Controllers

A Model View of Controllers: My Foray into MVC

Hey all!

I wanted to take some time to write up a quick post regarding my personal development work that I actually pay attention to. I’m still excited about the King’s Road idea, but reality often obstructs my motivation to get started on such a thing. The project I’m writing about here has already been started, so it’s easy to hop in and write 50 or 60 lines and put it down for the night. Lately I’ve had a hard time drumming up the motivation to do even this much, so I was determined to examine why. My problem? Crappy architecture.

The project in question is a little application I’ve been writing for my friends to use in our ongoing tabletop campaign. We’re playing Unofficial Elder Scrolls RPG 2nd Edition, whose systems are a bit much for someone new to tabletop RPGs. It’s a useful app that everyone in the game utilizes to keep track of their characters and perform rolls with just a few clicks. There’s an added benefit that, since all of the game rules are already written, I do not need design inspiration to work on such a thing. I can just implement already-existing rules.

Just 8 months ago, the MainWindow was 677 lines of mashed-together stuff like this.
Just 8 months ago, the MainWindow was 677 lines of mashed-together stuff like this.

I sat down and opened up the project with the goal of figuring out why I found it so difficult to pick up again, and the answer was plain to see within minutes. 80% of the logic was in a monolithic “MainWindow” class, so finding the logic I need to edit gets increasingly harder as the project grows. Adding to that, all sorts of game logic is mixed in with the presentation logic with only the barest level of organization. Making a change to some simple game rule ends up being pretty difficult because I can’t even find the function which handles that! Everything was lumped together in a swampy mush of code.

It was clear that the system required some [re-]architecting. At least one thing had to be done: I had to find a more modular approach, preferably one that reduced coupling of game logic with UI logic. I decided to find out what was actually meant by the name “Model View Controller,” and potentially adopt it into my application architecture. For the unfamiliar, “Model View Controller,” or MVC, is an architecture which aims to separate the concerns of data, actions, and representation to the user. The Model component encompasses all data aspects–for the purposes of Character Generator, these are things like Character, Spell, Weapon, etc. The View handles UI concerns, with a general rule that it should treat Model components as read-only. Finally, the Controller serves as a layer between the other two, and handles actions which the user may undertake, among other non-data concerns that may be required.

By separating these layers, a software team can work in parallel on all of the necessary pieces. This structure is also nicely organized. In an MVC (Model-View-Controller) application, I know that to make a change to the game’s equipment handling, I should first seek out the Model objects related to equipment, then update Views as necessary. I decided that to combat my mushy software problem, I had to restructure the app and adopt the MVC pattern, or else the mush would only get worse. In the process, I learned a good deal about the C# ComponentModel which facilitates such structures.

The ComponentModel, in summary, allows for the creation of Events which can be subscribed/responded to. If you have worked with Windows Forms at all, you have been exposed to Events already. This structure is nice because one can have a number of events throughout code–for example, an event which fires when the Character name is changed–and Views can subscribe to these events in order to update UI representations whenever necessary. This scales nicely: if I want to add an extra View which requires the Character’s name, I simply hook it up to the “name changed” event, and neither the Character nor the existing Views need to care. Super modular!

Each of these GroupBoxes has been turned into a modular UserControl
Each of these GroupBoxes has been turned into a modular UserControl

Speaking of modularity, that MainWindow class had to be broken up. Had I ever gotten any formal teaching or training on Windows Forms, I’m sure this next part would have been obvious. Alas, I did not and it was not, but I have learned now. Windows Forms applications are very easy to build because there are many pre-made UserControl building blocks to fit together. It has NumericUpDowns and TextBoxes and ComboBoxes and Buttons galore, all ready to be dragged-and-dropped and given behaviors rapidly. However, these can get way out of hand in an application of any complexity. In these cases, it can be useful to break off components of larger Forms into custom UserControls, thus allowing developers to create modular building blocks of their own. Utilizing the ComponentModel features, it becomes intuitive to split off these blocks and make them completely standalone, since each one is able to hook itself up to the Events it cares about. We are left with several “mini-windows” which, if desired, could be placed in their own Form and function just fine. These blocks are an excellent analogue to the Views in MVC. I find the app much easier to navigate now that all of the fun dice-rolling and equipment-managing portions are split into their own UserControl classes.

Finally, I am pleased to note that the MVC structure has incredible benefit in testing. It allows one to define clear rules for the components of the app: when the Character name is changed in the Model layer, the MainWindow view (which displays the active Character’s name) must change its name field in kind. These tests are easy to write in most cases, and if they fail, we know that some aspect of the app was not updated. I have found testing so easy with my shiny new MVC structure that I am tearing through the test backlog much faster than anticipated.

Moving forward, new features should be simple to slot in and test, and my players should be much happier when each new test snapshot doesn’t break some fundamental functionality! If you’d like to keep an eye on the project, you can follow it here. Please note, at the time of this writing, the stable branch is trailing quite a lot. Merges have been put on hold until the MVC update can be verified with a little more confidence. The exciting stuff is in latest, so be sure to take a look!

With this, I leave you once more. I hope to be writing more frequent updates about my gallivanting. I hope you all have a happy New Year!

(Title inspired by Kazuo Ishiguro’s A Pale View of Hills)

Comments