I recently was asked an intriguing question via email. A gentleman was considering enrolling in Back End Web Development with Rails at General Assembly. He appealed to me for advice. He learned to code PHP two years ago, has read a couple of books about OOP, and is a regular GitHub contributor. He knows nothing about Ruby or Rails, the subjects of my course. The question, then: This course looks cool, but is it worth it?
As the instructor for the course in question, I’m aware of my personal leanings. That said, I understand the substantial financial, temporal, and even psychological costs involved. I expect to answer this question often, so I put some thought into my response.
My first course starts in a couple of weeks (last I checked, seats were still available). So I put together an answer having never taught the course before. I’m interested to see if and how my answer changes. I present my current response here for anyone that’s interested in General Assembly and is faced with a similar choice. But if you’re looking for more information, please contact me! I’m always happy to chat.
I’m big on mocking. I create loads of interfaces and I test up against my interfaces. That’s how I define unit tests. I understand there are plenty of other definitions out there, and many of them have merit. This one helps me to stay organized.
This also leads to loads of setup in my MSpec files:
This class is my setup. My other specs extend this class, reducing some of the noise:
internal class when_setting_current_scenario : ScenarioWindowViewModelSpecs
const string CurrentScenario = "current scenario";
Because of = () => ScenarioWindowViewModel.CurrentScenario = CurrentScenario;
It will_set_the_current_scenario = () =>
So, nightmare setup but a pretty concise spec. The problem is compounded, of course, anytime I add, remove, or change my dependencies. I always have to change them in both production and test code.
Now enter automocking, an intelligent mix of unit testing and dependency injection. Using MSpec’s automocking capabilities, we declare our Subject Under Test (SUT) and get right to business:
internal class when_getting_setting : WithSubject<ScenarioWindowViewModel>
private const string CurrentScenario = "current scenario";
private Because of = () => Subject.CurrentScenario = CurrentScenario;
private It will_set_the_current_scenario = () =>
Where did the setup go? Using this method, it’s all done for us. MSpec knows from the class declaration that ScenarioWindowViewModel is our SUT and that there are four interface dependencies. So we don’t need to go through the trouble of declaring and intitializing each one.
We don’t even have to decare our SUT. We use the subject keyword in place of ScenarioWindowViewModel.
This helps tremendously with reducing setup and headaches as a result of churn in the production code. It even provides a nicer syntax for when we need those dependencies. For example, our SUT has a dependency on an IGridSettingsViewModel. Here’s how to set an expectation:
It will_register_a_column_manager = () => The<IGridSettingsViewModel>.WasToldTo(
x => x.SetColumnStyleManager(Arg<IColumnStyleManager>.Is.Anything));
Last week I discovered that I’ve been lying to myself. I told myself for almost a year that I was making my application conform to the MVVM framework. I was not. Not by a wide margin. I suspected this, then had StackOverflow confirm it.
After dusting myself off, I decided change was needed. It’s one thing to decide against using an MVVM framework, a decision my team made a long time before things got so big and complicated.(My friend and former colleague, Moss Collum, had the best words of wisdom for me when I lamented my architectural state on Twitter:
But in our case we’ve transgressed against known effective patterns of .NET development. Reparations must be made. So I started looking into ways to change. I watched an excellent talk by Rob Eisenberg called “Build Your Own MVVM Framework”. I read, and I experimented. Then I came up with a plan.
The first problem comes with our windows. We have three types of windows that the user can load, each with its own nested WinForms grid. One of the views is a “master” view. The other two views can be launched from the master view. One is a detail view and the other is a scenario view. We use AutoFac for dependency injection, but we overloaded our code-behinds with dependencies - mostly ViewModels - instead of using one ViewModel to rule them all.
I know that a code-behind with lots of dependencies and logic is probably the most egregious of our sins. I also know that moving away from this will give us two advantages: first, it will allow us to have a proper ViewModel per view which can control everything. This sets us up for MVVM retrofitting. Second, extracting this mess by hand will help me to see the common functionality being duplicated across my three windows.