Monday, April 20, 2009

PRISM: Your guide to a well-structured UI layer in WPF/SilverLight

I’ve had the opportunity to work with Composite Application Guidance for WPF and SilverLight (codenamed “PRISM”) for a couple of months now, and I’m really impressed with what the Patterns & Practices team has shipped this time. The forefather of Prism is in many senses the CAB framework (Composite UI Application Block) and even though I never worked with the CAB Framework myself, I’ve heard that it is a quite large and not that easy to grasp. Prism on the other hand, is quite light weight and the documentation is very concise and well written.

imageThe feedback from CAB has also been that it’s too intrusive; it’s an all or nothing application block and it’s hard to take advantage of the UI composition patterns in existing applications. CAB is from what I have found, meant to be built upon – not with (remember, I haven’t worked with CAB myself, so if you’d like to correct me, please feel free to do so in the comments below). With Prism P&P has taken quite another approach; you’re free to use (or not use) any part of the Composite Application Library in Prism. And you can switch out whatever part that doesn’t suite your needs. For instance, a core principle in Prism is to use an IoC container to make the application highly testable and loosely coupled. And since P&P has developed an IoC container themselves, namely the Microsoft Unity, the examples and the reference application in Prism uses Unity. But if you’d rather use Windsor, StructureMap, Ninject, Autofac, or any other IoC you’re definitely free to do so.

The big difference here’s that where CAB is an application block, Prism is an application guidance. And it guides you towards building applications that are testable, maintainable, multi-targeted and modularized. I’ll dive into these concepts in more details, so let’s start with;

Testability

Everybody tests their code and there are two ways to do it;

a) Manually; set some breakpoints, fire up the app, input some data and push some buttons, let the debugger hit the breakpoints, inspect some variables, and check that everything works as expected (or more often; try to find out why it doesn’t work as expected)

b) Automated; use a testing framework like NUnit, xUnit, or MSTest, write some tests, and then let the machines do the tedious work of verifying that you didn’t break anything you didn’t mean to

If you enjoy your time with the debugger, I won’t try to convince you that automation is good. But I consider myself a pretty lazy programmer and whenever I see an opportunity to automate boring, repetitive tasks, I always try to do so. I prefer to code, not debug, and therefore I automate my testing. Therefore I write unit, integration and UI tests that can be run by an unattended build machine whenever I check in some code changes. I’m a coder, not a debugger.

imageBut writing unit tests can be hard if you haven’t architected you’re classes and methods in a way that opens up for testing. If you instantiate objects inside your classes or in other ways are tightly coupled to other classes, mocking out those classes that are not in the scope of the current unit test will be hard. It’s not impossible, it’s just hard. One of the areas that are notoriously hard to unit test is the “code behind” of graphical components. Because when you instantiate a GUI component, it makes you dependent on a GUI thread when you run the test. On a build machine that’s going to run your tests without any interactive user logged in, this is just not the case; there’s no GUI thread available. And besides; it is bloody annoying and time consuming to have those forms and windows pop up whenever you run your test suite.

Opening your class for dependency injection and using an IoC container to manage the wiring of dependent objects is a well-proven and easy way to solve this problem. Prism explains and shows you how to write your application using an IoC container for the hot-wiring. And as I’ve already mentioned; if you prefer any other IoC Container, it’s totally up to you. But if you choose to not use Unity, you’ll have to be prepared to write some wiring code when initializing your application. Prism comes with the wiring code in form of a class called UnityBootstrapper. And there’s no surprise to the naming here; this class takes care of booting up your application with the Unity IoC container. So if you want to use any other container, you’ll need to rewrite the UnityBootstrapper to suite your choice. Or if you’re lucky; use the source code from someone who’s already done it (like the Castle Windsor adapter and bootstrapper that you can find in the Composite WPF Contrib project over at CodePlex).

 

All right! I think that’s enough for one post. I promised to write about maintainability, multi-targeting and modularity as well, so these will be the subjects for my next post.