|
In a previous article, I discussed how I felt that Interface Builder and Xcode were far more conducive to creating an application that conforms to the MVC pattern than Visual Studio 2005. The comment appeared that the code-behind for a particular view (e.g. the .xaml.cs file) was actually not the controller, but the view itself.
This makes sense from a technical standpoint, considering the .xaml file and the .xaml.cs file are both partial classes that combine to form a single class. So, if the code-behind is not the controller (an assertion I agree with completely), then where the hell is the controller?
I originally had a screenshot to show you, but my blog software is flaking out. Picture if you will, a screenshot of the Solution Explorer wherein you have three folders: Views, Models, and Controllers. I have placed App.xaml/App.xaml.cs in Controllers, I've placed a file called Customer.cs in the Models folder, and I've placed MainWindow.xaml/MainWindow.xaml.cs in the Views folder.
What does this get me? Not much at the moment. What it initially does is help remind the developer that the .cs partial portion of MainWindow is just that, a portion of the view class. As such, it should only do view-related things. In other words, if the view needs a method to transform something or trigger an animation, I fully expect that to be in the "code behind" (.xaml.cs) file. However, when you push a button on the view, the action taken should be taken by the controller.
In other words, you might have the following in your view:
InsertButton_Click(object sender, RoutedEventArgs e)
{
_controller.InsertRow(param, param, param, param);
}
In Cocoa terms, the act of forwarding the button click event to the controller is taken care of when you control-drag from your button to your controller (Outlets and Actions are one of my favorite features of Cocoa, btw).
So, you've got your button rigged up, but... how did you get a reference to the controller stored in _controller ? The answer is that, in order to link the controller and the view without using code-behind/partial classes, we need to instantiate the controller from inside the view's constructor:
public MainWindow()
{
InitializeComponent();
_controller = new MainWindowController(this);
}
After this point, the controller and the view can communicate through properly exposed public properties and methods. What I don't like about this implementation is:
What I do like about this implementation:
If any of you have built MVC or MVP pattern implementations in WPF, please post a comment here. I'm sure that I'm missing something. The .NET Framework is an extremely flexible platform, and given enough time and resources, I'm sure someone could have abstracted a layer inside WPF apps that properly emulates MVC. My analysis in this blog post was based purely on what you get "out of the box" without doing much extra work.
One possibility to increase flexibility here would be to make it so that
the controller expects an instance of a particular Interface rather than a
concrete class. This would allow a controller to operate on more than one
view, and potentially make it more re-usable or more testable. Admittedly
I've never used that in a production app, so I don't know how practical it
is.
If you leverage Dependency Injection or the Inversion of Control pattern,
you would inject the controller into the view from an outside factory. You
can leverage an interface if you want, but the main point is that the view
delegates to the model for operations. How it gets that reference to the
model is external to the view itself. This is the foundation for something
like the Spring Framework.
It totally helps, but also helps me make my point - I can't do a really
good job of implementing MVC unless I use some other framework on top of
.NET like Spring, which lets me visually inject stuff like the linkage
between view and controller. While it lets me not have to see the code that
makes that link, it also means I am still without a decent "out of the box"
way of implementing MVC in WPF.
absolutely. .net was not geared towards MVC like other frameworks such as
rails et al. it is one of the biggest complaints of ASP.NET developers.
webforms are horrible for testability, which is why alot of new development
is looking towards things like MonoRail and the like.
There was a post on this blog yesterday that basically said MVC was a waste
of time if it wasn't about automated testing of controllers. Comments today
about MVC focus on automated testing.
"There was a post on this blog yesterday that basically said MVC was a
waste of time if it wasn't about automated testing of controllers" I don't
know whose blog you're reading, but I personally don't think MVC has
anything to do with automated testability. It's a damn fine side effect,
but the real benefit of MVC implementations are in the architecture, the
re-use, the maintainability, the scalability..and it just works really
well. As you said, getting testability out of MVC is a nice side effect.
Kevin,
Ah yes, well.. standard rule of blogging applies here: The opinions of
people who comment on my blog posts are not necessarily my own. I am in
your camp - testability is a nice secondary effect of properly separated
MVC, but getting a really good MVC going provides the developer with other
more important benefits above and beyond testability.
"I must wholeheartedly disagree with the sentiment that MVC is primarily
about automated testing. MVC is primarily about keeping your design modular
and therefore keeping it extensible and maintainable. Automated testability
is just a nice side-effect"
" but i for one would not voluntarily work on a project that did not hold
automated tests in high regard."
sure, no problem. i would describe it as large. my current client is
making enterprise-scale software. and my consulting company employs 2000
developers nationwide.
I'm also a fan of TDD. I think situationally, it becomes useful. For my
home hobby-use (which is the development I'm currently doing with the Mac),
I don't need to worry about TDD. But, if I was working on
production-quality stuff for a mission critical application, you can bet
that I'd want a really good MVC separation and testability of my
controllers and my models and my views.
keith,
Have you taken a look at this?:
james:
keith,
then i encourage you to look into those topics.
keith,
I have to say I usually use a ViewModel / View approach, where the
ViewModel is simply an object within your view, defined as a resource
within your XAML page. Just like the presenter pattern in asp.net, the idea
is to write modelling code the xaml page binds to, and let the code execute
in reaction to logical commands from the view. The cleaner and more wpf
like you write your model wrappers, the better the separation, to the point
where your xaml page / control and your viewmodel know nothing about each
others, and only leverage the model and commands. This is inherently
extremely testable.