In my latest project I’ve been working with Silverlight (version 4), in conjunction with Microsoft’s Prism framework, and the Managed Extensibility Framework (MEF). Prism was designed by Microsoft's Patterns
& Practices group, and is also sometimes known by the somewhat less catchy title of
“Compososite Application Guidance”. It's a generalised framework for
composing UIs in WPF and Silverlight that are comprised of loosely-coupled parts. It makes use of patterns like Dependency Injection / Inversion of Control to achieve loose coupling between the various constituent components of a solution. This means that those components can be designed by teams working in isolation, and leaves the design open to be extended in the future. Whilst Prism itself isn’t specifically tied to the MVVM pattern, the loose coupling it enables is typically used by developers working in Silverlight or WPF as a mechanism to help implement that pattern, and to thereby leverage the testability and extensibility benefits that MVVM bestows. My current project has also provided some other interesting challenges for me, in the form of technologies that I’ve been encountering for the first time in a live project. Specifically, for reasons related to the product itself, the project I’m working on utilises several Postgres databases running within a Linux environment – not an everyday challenge for a .Net developer by any means. This blog entry provides a brief overview of the above toolsets, and their purpose within the overall design.
MVVM (Model View ViewModel) is a development pattern that was first proposed by John Gossman, and is based on an even earlier pattern by Martin Fowler called the Presentation Model. I wont attempt to describe MVVM in full here (there are a great many other articles available on the web that do that far better than I could, for example this one here, as well as useful training videos that give you an introduction to some actual coding techniques to implement the pattern. More on those later.) For the purposes of this blog, I’ll just summarise by saying that MVVM is a pattern that takes code that would ordinarily reside in code behind files, and pushes that code into separate areas of the application known as ViewModels. The code that resides in these separate ViewModel classes represents the pure business logic of the application. This is where the pattern starts to become useful in ways that have made it the most popular and widely-adopted approach for extensible WPF and Silverlight applications. Separating concerns in this way makes the ViewModels in which the business logic resides independently unit testable, which in turn makes the design more resilient to ongoing development and change. So, any developers that need to alter the design in the future after initial development has been completed and the product is in a care and maintenance phase can have greater confidence that any changes they may implement will not break existing code.
Prism: Not the only option for implementing MVVM |
When implementing MVVM, Prism may be used in a range of discrete ways to facilitate reliable, scalable results in a reasonable amount of time.
I wont go into all of Prism’s more discrete areas that I touched upon above within this blog, but can recommend this excellent guide to Prism in conjunction with this equally-enlightening guide to Silverlight 4 development for further reading. The Prism guide is part-written by the lovely Ward Bell, whose insightful videos on IdeaBlade’s DevForce ORM tool gave me many an enlightening chuckle a few years back. Get ’em on Kindle so that you can read them on your PC instead of lugging heavy books around – you know it makes sense. ;)
Before moving on from this discussion of Prism and MVVM, I'll just lastly note that there's a great little series of instructional videos by Microsoft's Mike Taulty available.
It's a rare individual that can grasp technical concepts clearly, and communicate them to others. Mike manages to do so beautifully over the course of just a few hours. His videos are great for getting a feel not just for what Prism and MVVM can do, but also along the way they give quite a bit of insight into how composite applications can be more complicated to understand than traditional, tightly-coupled designs. And they demonstrate how easy it is to build up an illusion of loose coupling using frameworks like Prism, whilst in realty just turning turning tight coupling that would otherwise cause build errors at design time into breaking functionality at runtime that are harder to track down and eliminate from the design. When you get to the part of the videos where Mike is having to copy DLLs into bin folders by hand to ensure that the project still works as expected you'll see what I mean.
I appreciate that Mike's videos do contain some contrived examples, but still voluntarily immersing yourself back in the Bad Old Days of DLL Hell isn't what any pattern or practice that's meant to make developers’ lives easier should be about. That illusion of loose coupling whilst really still having all the same interdependencies of tight coupling in disguise is also evident when Mike doesn't attempt to type in the XAML configuration files that describe how his Modules should be loaded and what dependencies they will have on one another. He instead stops the video when it gets to those points and gets said config files from a Blue Peter -stylie pre-prepared example, because in his own words typing in such config files by hand is “prone to error”. It's ridiculously easy to get such configuation information wrong in ways that will only become apparent when a user tries to use the components controlled by them at runtime. And it's even easier to get the configs right in the first instance, but for them to become invalidated at some later point during the lifetime of the extensible application involved by later development work. It's a judgement call for the developer/architect to make as to whether the risks vs rewards of using Prism make using it the right decision for a given project.
Getting back to MVVM as a concept in its own right, as I mentioned the last time I wrote about Silverlight, one of the main strengths of and purposes behind the XAML-based design environment that each of these technologies uses is the separation of concerns that XAML facilitates between the related but distinct goals of design and development. Using XAML as a common medium allows designers that are primarily concerned with the look and feel of an application to work hand-in-hand with developers, whose primary responsibility is making sure the application actually does what it was functionally intended to do. MVVM adds a further refinement to that collaborative effort within WPF/Silverlight. It enables developers to protect their work against any unintended behaviour that may be introduced after initial development, by allowing their business logic code to be unit tested in isolation from the purely visual elements of the solution. For designers, MVVM allows the visual elements that they are most interested in (called the Views) to be designed independently from the application state and business logic stored in the ViewModels. In the case of designers, using MVVM is also useful for simulating application state at design time, thereby allowing them to refine the visual representation that the UI will be required to have when it experiences those states when the application actually runs. The final part of MVVM – Models – concerns those parts of the application that are purely concerned with the business of communicating with whichever specific back-end database is being used. This is particularly useful in allowing developers to focus on business logic in isolation, without becoming overly-involved in issues that are more generally within the purview of DBAs.
Some clichés about Web Designers and Developers. And Women. |
By using MVVM, any code that UI Elements use can be separated out into their own classes (called ViewModels). By separating concerns in this way from the outset, it makes it less likely that UI Elements will be fundamentally unable to be rendered in Blend at design time. Most MVVM frameworks will render any constructor logic within a base ViewModel class that utilises the DesignerProperties.IsInDesignTool Property mentioned above within a common base constructor. By solving this problem once and for all, and avoiding rather than dealing with the consequences of designtime / runtime issues of this type, MVVM helps to significantly reduce the number of occasions when design members of the team will have to call on busy developers for help.
Concentrating on the developer-centric benefits of MVVM, by separating out business logic code into ViewModels developers obtain in return greater control over the stability and testability of their functional code. If you’ve worked on a software product of any level of complexity with a moderately-sized team, you’ll know that there is ample scope for code that has been written, debugged and tested to begin experiencing unanticipated behaviour at some later point in the development cycle, through no fault of the original developer or tester. Developers that are starting out (and even some that have been around long enough to know better!) are sometimes misguided enough to believe that their own code is bug-free.
This is usually not the case, but, even if we were living in some mythical Nirvana universe where we were all super-developers that produced error-free code first time every time, there is still ample scope for any developer of any level of ability to have bugs inadvertently introduced into their code by other team members as the collaborative software product you’re building together evolves over the course of the project. This is where the Unit Testing that MVVM facilitates becomes useful. Just to make my position clear on this subject: I’m not an advocate of what I would term ‘fundamentalist’ Test Driven Development. Which is to say that I don’t advocate the approach to TDD that involves writing tests before writing code, or that encourages writing lots of meaningless tests for even the most simplistic parts of the system. I do, however, support the concept of writing tests to protect existing human-tested code against unanticipated bugs being introduced by subsequent development. MVVM allows various frameworks such as the Managed Extensibility Framework (MEF) and Unity to work in conjunction with Unit Testing and Mocking frameworks such as xUnit and Moq to test ViewModels in isolation at design/test time. This allows developers to set up unit tests that automate the process of confirming ‘What should happen if…’ scenarios. [And, in the case of MEF, there is also lots more functionality on offer, including the ability to group loosely-coupled independent components of the solution into a coherent composite application. You can find lots of good info about how to use MEF in conjunction with Silverlight here. ]
This is usually not the case, but, even if we were living in some mythical Nirvana universe where we were all super-developers that produced error-free code first time every time, there is still ample scope for any developer of any level of ability to have bugs inadvertently introduced into their code by other team members as the collaborative software product you’re building together evolves over the course of the project. This is where the Unit Testing that MVVM facilitates becomes useful. Just to make my position clear on this subject: I’m not an advocate of what I would term ‘fundamentalist’ Test Driven Development. Which is to say that I don’t advocate the approach to TDD that involves writing tests before writing code, or that encourages writing lots of meaningless tests for even the most simplistic parts of the system. I do, however, support the concept of writing tests to protect existing human-tested code against unanticipated bugs being introduced by subsequent development. MVVM allows various frameworks such as the Managed Extensibility Framework (MEF) and Unity to work in conjunction with Unit Testing and Mocking frameworks such as xUnit and Moq to test ViewModels in isolation at design/test time. This allows developers to set up unit tests that automate the process of confirming ‘What should happen if…’ scenarios. [And, in the case of MEF, there is also lots more functionality on offer, including the ability to group loosely-coupled independent components of the solution into a coherent composite application. You can find lots of good info about how to use MEF in conjunction with Silverlight here. ]
Well, so much for this overview. I’m enjoying working with Prism, as well as the other tools/environments that I mentioned such as Postgres and Linux for the first time, and thereby evolving into an ever-more-experienced developer with first-hand insight into how a range of technologies are being used on live projects. As the name of this blog suggests, it’s not just the code or the software products that I’ve been involved in building over the years that’s a Work In Progress, it’s myself and my professional experience that are ever-evolving. One of the things that makes that process of learning and personal development possible is having a great team to work with in a positive and forward-thinking environment. I’m very pleased to be working with such a knowledgeable team at this time, who have many strengths in those areas that are newest to me, and are open enough in their outlook to allow my ideas and discrete experience to be part of their already-impressive mix too.