Sunday, 27 December 2009

Prism Sample: Resources

An area of Prism development that often gets overlooked is the management of resources.  I mentioned in a previous blog that View reuse is unlikely, but that doesn't mean you should create unnecessary dependencies to a resource assembly.

Similar to modules, resource assemblies can have an accompanying interface assembly.  This is done by defining ComponentResourceKeys in your interface assembly and using them as resource keys in your resource dictionary and in your Views.

public static class Styles
    public static ComponentResourceKey LargeTextStyleKey
        get { return new ComponentResourceKey(typeof (Styles), "LargeTextStyle"); }

and in your Xaml...

<textblock text="My Sample TextBlock Style"
           Style="{StaticResource {ComponentResourceKey TypeInTargetAssembly={x:Type Interfaces:Styles}, ResourceId=LargeTextStyleKey}}" />

Taking this approach decouples your modules from the resource assembly.  The advantage to do this is not so much in the area of reuse, but more in the implementation of themes.  Any Views that require the use of a resource can simply refer to it by its ComponentResourceKey.

Additionally, I would only have the Shell load the external resources, since the View modules are now unaware of the external resource.  The only draw back in doing this is you will lose your Visual Designer when editing your Xaml, because the designer cannot resolve the resource to render it.

It is also worth setting up default styles based on control types, by using the control type as the resource key (e.g. {x:Type TextBlock}).  This does not require the use of ComponentResourceKeys.

The area of theming WPF applications is a common one and there are a number of resources on CodePlex which address this area.  One example is the Razre WPF Framework, or you can build your own ThemeManager.

I think this pretty much concludes the PrismSample articles.  This was meant as an introduction for developers starting out with Prism and to provide some guidelines in setting up a Prism solution.  I hope this was of some use.  I'm certain others will have differing opinions, and that's okay too.  I'm always on the hunt for new approaches and new ideas.

I think Prism has a real future in WPF development.  Once you get into it and see the benefits, it changes how you think about and view WPF development; afterwards it is difficult not to think and develop that way, which is a good thing.

As always, comments/feedback welcome...

Saturday, 26 December 2009

Prism Sample: Services

In addition to Views and ViewModels, your Prism application will likely have one or more Services.  Per the CAL documentation, a service is defined as:

A service is an object that provides functionality to other components in a loosely coupled way through an interface and is often a singleton.

This is a fitting definition, but doesn't indicate belongs in a service or when something should be service.  Services reside outside the View-ViewModel pattern and provide functionality to anything that needs it.  In practice a service should address an area of business logic and have an appropriate name which describes the functionality it contains, like CustomerService or DataService, etc.
Avoid making a service a dumping ground for functionality you don't know where to put.  I tend to view services as static libraries of functionality, generally consisting of methods (think WCF Service Contracts).  My personal preference is to avoid storing state or exposing properties in services.  I don't use services to control workflow.  Instead I would implement a Controller to govern the workflow, and have the Controller consume the service.
On one Prism project, we would have regular design meetings where we would discuss where a given piece of functionality should reside.  The governing rule that came about, was that the ViewModel is directly concerned with the View and servicing the View; code that belongs in the ViewModel is there because of some requirement dictated by the View.  If that wasn't the case, we were probably looking at a general piece of business logic which likely belonged in a service (or Controller, if one existed).
Following this line of thinking, we found more and more of our code moving to services, until we had a robust services layer, and a lean ViewModel which simply became a consumer of the services.  This approach prevented business logic getting lost or hidden in ViewModels.  It also supported our decision to separate out our services into their own assemblies, which I would highly recommend.

Sunday, 20 December 2009

Prism Sample: Modules

Central to Prism is the concept of modules and modular design, therefore it's worth spending some time defining exactly what a module is, what it contains and what it shouldn't contain.  Per the Prism documentation:

A module in the Composite Application Library is a logical unit in your application. Modules assist in implementing a modular design. These modules are defined in such a way that they can be discovered and loaded by the application at run time. Because modules are self-contained, they promote separation of concerns in your application. Modules can communicate with other modules and access services in a loosely coupled fashion. They reduce the friction of maintaining, adding, and removing system functionality. Modules also aid in testing and deployment.

Having worked on a number of Prism projects with a wide range of developers, each interpreting this from their own perspective and experience.

Two of the guiding principles behind this are:
Single Responsibility Principle
Separation of Concerns

While most can agree on these principles, views differ on the depth and extent to which they are applied.  On one end of the spectrum we have the theorist, whose motivation may be to strictly adhere to these (some times with religious fervor).  And on the other end we have the realist, who simply wants to build a working piece of software that meets the business requirements.

The theorist looks beyond the business requirement, while the realist may argue that strict allegiance to these principles is outside the scope of the requirements.  Somewhere, somehow these views are resolved, usually by an architect or team lead; and the result usually falls somewhere in the middle.

Personally, I fall in the middle, and maybe lean towards the realist.  I don't feel software development should be an academic exercise.  If someone entertains the idea of using a certain design pattern, I'm always interested in "what problem does this solve?" and "what does it buy me?"  Unacceptable answers are "because Fowler said so" or "because that's what the Prism team does".

Enough of this, let's talk about modules...

In an earlier post, I talked about creating an Advertising module for Blogger and said I would create the following modules:


Some developers would be tempted to bundle these up into two assemblies:

storing their Views, ViewModels and Services in a single assembly.

And I could be convinced of this.  It's certainly easier to maintain.  But I would argue that Views/ViewModels and Services are logically separate and warrant their own assemblies.  It's not inconceivable that another module or system could be a consumer of these services, without the need for Views or ViewModels.

So, why separate out Views from ViewModels?

I think it is somewhat idealistic to expect Views designed for Product A to be simply dropped into Product B (two different implementations).  In theory this is possible, but in practice I've never seen it happen.  Here we get into areas of look and feel and layouts.  While we can do a lot to make a view generic and use themes and skins to alter its appearance, at the end of the day there is always going to be something different or required which makes the view unusable.  So why bother?

I always assume my views are not going to be reusable; that they're part and parcel to a specific implementation.  My ViewModels, however, are completely reusable.  I would also argue that mocking up Views is far less time consuming than the creation of ViewModels.

Regardless of what I think, your design decisions are going to be driven by a number of factors.  I think its important to consider all views and options, and decide which is suitable.

Thursday, 17 December 2009

Prism Sample: Basic Concepts

As stated in my earlier post, this model solution attempts to illustrate how Prism and Unity are used, what is a module, what belongs in one and what doesn’t, the use of interfaces and design patterns.
One of the most basic aspects of code organisation is knowing “what goes where”.  This is especially true with Prism projects.  Given you will likely have a dozen or more projects in your solution, it’s pretty important to sort out early on where things belong.
I always try to minimise dependencies between my assemblies; and from time-to-time work-out what would be required to take a module and drop it into another application.  I’m always looking for ways to remove a dependency or decouple.  Even if I don’t have an immediate requirement to do that, as a general rule it’s a good idea.

Picking the right naming convention for your projects and namespaces is pretty important.  I would spend ample time on this before embarking on any serious coding.  Maybe start with a prototype solution and put in some basic modules, a shell, some services, and their accompanying interfaces.  Play around with it and massage it into something you're comfortable with.  I think there is a natural order and organisation for these various projects and components.

Microsoft's recommended namespace convention is:

for example, if I were creating an advertising module for Blogger, I would see something like...


Microsoft has an excellent guideline for create .Net components at:

Implementation vs Interface
It's important to understand the difference between implementation and interface as it applies to modular development.  An interface is simply a public contract that defines an exposed surface.  Whereas, implementation deals with the deploy or realisation of the interface.  Interfaces do not contain business logic,  simply a definition of what something will look like once it is implemented.
Prism and Unity makes heavy use of interfaces.  Interfaces are mapped to your implementation classes, either in code or in a configuration file.

The following tips may be obvious to some, but I felt it was worth mentioning:

Tip #1 - Do not create strong references to implementation assemblies.
The exception to this are assemblies which comprise your Model.

Tip #2 - Do not place anything in your implementation assemblies which forces other assemblies to create a strong reference.
An example of this are Event classes.  You may have a module which publishes events, presumably to be subscribed to by other modules.  Do not include the Event class in your module assembly, instead place it in your module's interface assembly.  This makes it available to other assemblies though the interface reference.  Another common example are enumerations.

Tip #3 - Do not register your implementation classes in the Module Initialize method.
Registering classes in the Initialize method implies a specific implementation, but not all implementations.  Instead map your classes in a Unity configuration file.

Tip #4 - Do not inject views into regions in the Module Initialize method.
I never understood why anyone would want to do this, as it pretty much ruins any chance of reusing the module.  Instead, delegate view orchestration to another module, layer or layout manager.

In fact, I can't think of good reason to put any code in the Module Initialize method.

These tips address some hidden or covert implementation that commonly occurs in Prism development.

Wednesday, 16 December 2009

Prism Sample: Introduction

I had a request to post some sample code illustrating the use of Model-View-ViewModel pattern, Controllers and DelegateCommands.  This lead to the creation of a sample Prism solution.  An interesting exercise, since it gave me a chance to incorporate many of what I consider to be Prism best practices.
I consider proper solution setup and organisation to be critical in working with Prism.  Mistakes made in this area often come back to haunt you.  There are many ways to organise your projects and code.  What is probably more important is pick a solution structure that everyone can agree with and stick with it.  A lack of agreement or ignorance of architecture can make team development a nightmare.

I intend to write a series of postings detailing out what I consider to be areas of interest, and why I've organised things as I did.
You can download the solution here (408kb).  You will require Visual Studio 2008 SP1.  I've stripped out all XML documentation and PDBs to keep the file size down.

Please let me know if you run into any problems loading and running this solution.

Thursday, 3 December 2009

Some Agile thoughts...

Is it me, or have others found Agile development projects to be chaotic?  I will not profess to be an expert in this area.  I've been a developer on about four Agile-based projects, ranging from a handful of developers to a team of 20.  And, on the larger projects, the more Agile is pushed the more chaos seems to result.

At worst it feels like a mad coding free-for-all, in an effort to meet development targets, while abandoning or ignoring coding conventions and best practices.  The idea being, "if we just get the cards done...the project will get done".

I don't know how many times I've coded up a piece of functionality, written tests, etc., only to find weeks later, that someone else on the team "refactored" it, rendering it unusable.  One step forward, two steps back.  I've only really experienced this on Agile projects.

Don't get me wrong, when I first encountered Agile I felt it had merit; and I still do.  But somewhere  between theory and execution the plot can get lost.

I've always consider myself to be self-managing.  You give me a spec and I will methodically design, develop, test and document it to a finished product.  Maybe that's a bit old-school, but it got the job done.

I would be interested in what others think about this.