Prism: Review, Part I

These are my thoughts about drop 03-25-2008 of Prism, patterns & practices’ composite WPF application guidance. I understand that this is only a preview release, and it is likely the code will change in the future, rendering these thoughts obsolete.

Before I get into the code, I want to prefix this post with thoughts on how I approach patterns & practices code. Glenn Block, who drives the team, had this to say on ALT.NET:

Smart Client - We first shipped the Smart client guide. Then customers asked us for code, so we built CAB.

Like CAB, Prism is described as a reference implementation of guidance. The guidance (articles, white papers, videos) is the key deliverable; the code is just there to help explain it. If you’ve used any P&P code, or any code meant as a reference, and you haven’t understood the original guidance, you’ve missed the whole point.

So when looking at the Prism drop, the questions I’ll be asking are:

  • Is it a good demonstration of the patterns that relate to composite applications?
  • Is it complicated?
  • Can I easily separate the general patterns from the reference implementation by reading the code?

This is part one of a two part post. In this post I’ll describe what it seems Prism is solving, how modules and communication between modules are handled, and summarize my likes and concerns so far. In the next part, I’ll discuss the UI-specific parts of the Prism guidance.

Taking Delivery

When I downloaded the ZIP file, I was expecting to find:

  1. Source code for the Prism components in one folder
  2. A sample application referencing Prism in another

Instead, the sample application and the Prism code are combined into one solution. I think this is a smart move. It’s a reminder that although you can use the code as-is, it is meant as a reference, and you should think about it that way.

The solution has 9 projects, ignoring the additional 6 unit test projects (tests are obviously important, but only as suggestions about how to test composite applications). Two of them, the Prism projects, contain the core code that enables the composite application. The rest are examples of how an application would be written within this structure.

image

If it were up to me, the two Prism projects wouldn’t even be called Prism. They’d be bundled into StockTraderRI.Infrastructure. After all, this is an example of how you could design a composite application, not how to use Prism. I expect this is done because people will undoubtedly want to use Prism directly, and it’s nice that they don’t have to pull the code out themselves.

Expanding the two Prism projects also made me very pleased. This is the entirety of the core of what they suggest a composite smart client application should provide:

image

That’s a healthily small amount of code. The cyclomatic-complexity of both projects is very, very low, and the combined logical lines of code comes to a measly 69 lines. That is a good.

What does it solve?

After a birds-eye-view of the package, it was time to understand what it is here to do. Put simply, Prism is here to:

  1. Guide how you might build composite applications
  2. …using WPF

A lot of stuff has been written about what composite applications are, but not so much about how to apply the patterns in the context of WPF. Wikipedia defines composite applications as:

the term composite application expresses a perspective of software engineering that defines an application built by combining multiple existing functions into a new application.

I see composite applications as Conway’s Law in practice:

Any piece of software reflects the organizational structure that produced it. If you have four groups working on a compiler, you’ll get a 4-pass compiler.

The goal is you want to have multiple teams building separate but integrated components, with different delivery cycles, software rules or even internal architectures. These components are described as Modules. The teams can work in isolation, and modules can communicate, but without major dependencies on each other. A Shell figures out what components are available, loads them, and provides a common look and feel. A composite application framework, like the one Prism suggests, gives you a structure to enable this without tight coupling.

What goes into a module?

The short answer is: whatever you want!

If you’re familiar with modules in other systems, like DotNetNuke, or Web Parts in SharePoint, they’re usually UI things backed up by code. Going by the Prism code, the suggestion seems to be that modules can be anything you want. They might provide multiple UI’s, or none at all. Prism suggests that you should provide a basic interface that all modules should implement:

public interface IModule
{
    void Initialize();
    void RegisterViewsAndServices();
}

The RegisterViewsAndServices() method does seem to make the assumption that the module may provide views (UI) and services (code that does stuff), but it’s probably a better name than RegisterStuff(). Since views and services probably comprise 90% of the modules your teams might build, Prism seems to suggest you use conventions to help developers.

There’s two pieces of guidance that I like right there:

  1. All modules should implement a basic interface that enforces no constraints on what a module can do
  2. But use conventions, so developers can figure things out quicker

A module is typically contained within a project, though they could easily be solutions on their own, or have multiple modules in a single project. Prism doesn’t seem to make any assumptions in that regard. The Prism sample is a stock monitoring application, and comes with four modules:

image

Although the IModule interface might have made you think modules are just classes, that’s not quite true. Prism suggests the IModule interface is just the way the core composite framework can load up and initialize a module.

In fact, that is all IModule is used for: 

image

I like this guidance: just because I’m building the applications in modules, that decision shouldn’t permeate every nook and cranny of my code.

Initializing Modules

When the application loads up, it’s time to find and initialize the modules. There are many ways you might do this. In the sample application, the modules are called directly as part of the application startup (or Main(), for you Windows Forms people :) ).

IModule newsModule = new NewsModule(container);
IModule watchListModule = new WatchListModule(container);
IModule marketModule = new MarketModule(container);
IModule positionModule = new PositionModule(container);

newsModule.Initialize();
marketModule.Initialize();
watchListModule.Initialize();
positionModule.Initialize();

Since the authors of this application are aware of each of the modules they’re building (think about an internal corporate application), this isn’t so bad. If your application needs the ability to add modules dynamically - either via configuration or discoverability - you might need to do some extra work. I expect these strategies may be covered in the guidance that will accompany Prism, but I think it is a good thing that the sample application keeps it simple. How you find and initialize modules isn’t that important.

In the constructor for each of the example modules, they take a reference to an IOC container. This container lets them resolve any other modules they need to use. I like this approach - instead of passing around some kind of ModuleRepository, they use something a bit more generic. The module is barely aware that it is being used in a composite application, which is nice.

The sample application uses Unity for the IOC container, and although the concrete modules are aware of it, the core of the composite application framework isn’t. In fact, the Prism project doesn’t mention an IOC container at all. Prism seems to coexist with any IOC container you choose, or even none at all, though the guidance appears to be that you should use one. Good.

Why am I registering stuff?

In other words, what is the need for a RegisterViewsAndServices() (or similar) method on your modules, and how exactly do you register things?

When two teams build two modules in isolation, and those modules are supposed to communicate, it can be tricky. The suggestion Prism makes is that you use an Inversion of Control container to publish interfaces for the things your module can do. Other modules can query the IOC container for your interface, and it’s resolved in a nice, decoupled way.

The Position module, which provides information about how much money you’ve made or lost, uses the News and Market modules. Both of these modules are functional by themselves, and you could reuse them elsewhere in the application, but the Position module is aware of the services they provide and is able to make use of them.

The Prism sample suggests we do this by:

image

Thus, the News module looks like this:

public void Initialize()
{
    RegisterViewsAndServices();
}

public void RegisterViewsAndServices()
{
    _container.RegisterType<INewsFeedService, NewsFeedService>();
    _container.RegisterType<INewsService, NewsService>();
    _container.RegisterType<INewsView, NewsView>();
    _container.RegisterType<INewsViewPresenter, NewsViewPresenter>();
}

And the Position module looks like this:

public void Initialize()
{
    RegisterViewsAndServices();

    PositionSummaryPresenter presenter = _container.Resolve<PositionSummaryPresenter>();
    presenter.ShowViews();
}

public void RegisterViewsAndServices()
{
    _container.RegisterType<IAccountPositionService, AccountPositionService>();
    _container.RegisterType<IPositionSummaryView, PositionSummaryView>();
}

Note how the PositionSummaryPresenter is created via the IOC container’s Resolve method? Let’s look at the constructor of PositionSummaryPresenter:

public PositionSummaryPresenter(
    IPositionSummaryView view,
    IAccountPositionService accountPositionService,
    IMarketFeedService marketFeedSvc,
    INewsFeedService newsFeedSvc,
    IMarketHistoryService marketHistorySvc,
    IUnityContainer container,
    INewsService newsSvc,
    IRegionManagerService regionManagerService
    ) 

That’s a lot of constructor arguments, which is why we don’t call it ourselves. Any decent IOC container will look at all those arguments, resolve the interfaces, and create the object. Having resolved all the dependencies, the constructor then initializes everything needed to display the position summary using those services, and displays it.

I have two questions so far:

  1. Since in each module Initialize calls RegisterViewsAndServices, should I put both methods on IModule, or can I get away with just one?
  2. Since the Position module resolves all dependencies in the Initialize method, the Shell seems to need to ensure that the News module is initialized before the Position module. Having the knowledge of these dependencies leak out seems like a very bad thing to me. Perhaps this is why those methods are separated above - a sign of things to come? 

End of Part I

Thus far, I have only looked at how Prism suggests you might structure modules, and how modules can communicate. None of the above really uses anything specific to composite applications or Prism - you could do all of this with an IOC container alone. I think it’s worthwhile looking at this, however, since it’s such an important part of how a composite system can work. The concepts are certainly not new, but it’s good to see the guidance using them.

Here’s a summary of my thoughts so far:

Good: I like that the Prism code is in a full sample solution, and not standalone. That may be accidental, but I hope they don’t change it.

Good: I like that the core of the composite framework is so small, and the sample so simple. It’s a lot easier to understand and see the patterns.

Good: I like that modules aren’t limited to being UI components backed by code. Pure service modules are easily possible.

Great: I like that the module concept doesn’t appear all throughout my code, yet still allows me to take advantage of the concept. The classes within a module don’t need to know that they are in a module, nor a modular application.

Good: I like that so far, the module system seems independent of WPF. We’ll see later though that this does fall down.

Concern: I wonder how dependency ordering will be handled. I hope it will be as simple as the rest of what we’ve seen.

Concern: Glenn says on his blog:

"As I mentioned above this is just the beginning, and there’s much more to come in the future"

I sincerely hope "much more" refers to documentation, videos and blog entries, rather than code. The smaller and simpler the reference implementation, the better. Guidance first :)

As I said, most of what I covered so far isn’t Prism specific, but it’s great to see how Prism suggests designing for and leveraging the power of IOC. Next, I’ll look at the UI specific parts of the sample application, and how they fit into the approach. Until then, check out the Prism Overview page on CodePlex for other people’s opinions.

6 Responses to “Prism: Review, Part I”

  1. i must admit; i still don’t buy IoC at all, in terms of real usefulness. it seems to just cover up underlying problems. but that’s an aside i guess.

  2. @silky,

    How else would you you achieve the modules talking to each other via interfaces, without the modules being aware that they are modules?

    Not saying you can’t, there are ways, but I struggle to come up with one as simple as IOC.

  3. […] Prism Review, Part I (Paul Stovell) […]

  4. without being aware they are modules? can’t say i get that part …. [maybe i’m misunderstanding; possible].

    i suppose i just have seen the acronym way too much lately, without any real examples of what it’s getting me over a regular approach [aside from decoupling, which is fine enough, but it’s as if to suggest it’s the only way, which it isn’t].

    anyway, i don’t want to go off-topic. if you did a post on what value you see in ioc; i’d be interested in reading that…

  5. Nice article. I can’t wait for the second part.

  6. Still waiting on part II ;)

Leave a Reply