Prism is a set of guidance coming out of Patterns and Practices for building composite applications in WPF. And what is a composite application? It's essentially an application that is dynamically composed from a set of different pieces, and basically composite applications address really complex enterprise application scenarios.
In one sense very different because we are not taking one line of code from CAB into Prism, so it's a completely new effort. The reasoning for that is several fold: one reason is that WPF is entirely different than WinForms, completely different paradigm, the technology is different. There is a lot of things in CAB that we have to reinvent the wheel because there was no similar construct in WinForms, but now actually things like commanding, for example, is build in to WPF. So for that reason plus combined with a large amount of feedback that we got from customers who use Smart Client Software Factory which built on top of CAB and CAB, about how difficult it was to grok the number of abstractions, the fact that it was very imposing. I really had to accept every aspect of it which brought along a bunch of heaviness with it, and also it required me to build from scratch. So we've got costumers that are extremely happy with CAB and SCSF, but even the people that have been very happy have had a bunch of pains getting there, so we felt for that reason that we had a chance to both address delivering the right kind of guidance for the technology, being WPF, and at the same time to address the concerns that we heard from many customers.
It's always been part of our strategy even when we've done code deliverables or we've done the factories, for example the Software Factories which is probably the most extreme version of guidance that we've done. It's all been in the name of guidance and we've actually always intended for costumers to rip open what we've done, to look at it as a start point. In some cases we may have done to good of a job and people have taken like Enterprise Library, for example, out of the box like a product. That was never really our intention and that's caused a lot of positives in terms of adoption, but it's also caused negatives, perceptions and other things, so for that reason we have been for a while trying to get back to basics sort of speak and be less focused on delivering guidance as tooling or frameworks, but more about example implementations, libraries and again that's not completely across the board. We still have things like Enterprise Library that are going on and will continue, but we are also certainly looking at the guidance aspect.
When we look at Prism we break it into two categories of major challenges that Prism addresses. The first one is around what we call "modularized development" and that means being able to develop my application as a set of modules that can be separately developed, tested and deployed. The second challenge is around UI composition and that's where a Prism application or a composite application of which Prism is giving guidance on is an application that is dynamically composed of a set of pieces, and they need to be able to work with each other in a coherent fashion and in the UI that causes a lot of challenges like: "Hey, I've got shell where I am going to populate some content that comes from many different places." But those pieces on the shell need to actually work with each other, so when I click this thing, this thing over here responds. But because of the fact that it's a composite it's loosely coupled relationship between them, they don't directly know about each other. So those are the kind of things we're addressing within Prism and we're doing it specifically around WPF, so what that means is when we look at UI composition we are saying: "Hey, what does WPF have as a technology that we can leverage to address these challenges?"
Sure. One of the things we've been looking at is WPF has attached properties and attached properties allow you to basically attach your own, it's metadata essentially, but allows you to attach functionality that you can put in XAML, and in the past when we would wanted to do these kinds of things, like in CAB, we would have to do it like an attribute or through using reflection, and we would have to look at a bunch of classes at runtime which, one was problematic because it forced you to use our mechanism of doing that reflecting or it was very heavy for you to have to replace that, it was so wired in deeply in the framework (I am referring the object builder for anybody who knows about CAB), so with WPF using attach properties we can do a lot of these things in a much lower friction, easier to maintain, way, easier to debug and the nice thing about it is the platform provides the support.
So what I mean by that is we have a notion of these things called "regions in the UI", as an example, and regions are these place holders where content will get contributed. Well, you can use attach properties in your XAML to go and say: "I want this particular portion of the screen to be a region named X" and when that's getting built up at runtime, and this doesn't require any extra work from us except for registering this attach property, we can intercept that and we can say: "Ok. There is a region, let me go put that in the region manager service." That is one example and that's not really innovating, it's using what's in the platform, and we are just kind of building on top of it things that relate to the kind of stuff you're doing in a composite UI.
The area where we've gone a little bit more is looking a commanding. So WPF has a command infrastructure as I mentioned. Commands in WPF can bind to almost anything, any kind of UI element and their actions, action driven. And they carry parameterized data, so you can pass additional contextual information along with them. We looked at the UI routed commands build into WPF and found them insufficient for many of the things that we were trying to do, in composite apps, not to say that routed UI commands are a bad thing, but specifically around what we were doing we found insufficiencies. Fortunately WPF has an ICommand implementation, so the framework itself only cares about a thing they implement ICommand.
That allowed us to write a whole set of new commands around composite applications scenarios. We're not done and we're still constantly refactoring, but so far we've certainly seen areas, like an example, a delegate command being a command, because one of the challenges around commands is you end up having these little commands, you create lots of commands, your code is scattered throughout your system in these little micro commands and that makes it more difficult to maintain while a composite app is supposed to improve maintainability. So we found by using a delegate command pattern, we could have one command object, one command class that allows delegates to wire it up so that somebody else can do the listening. Now instead of having all these classes scattered throughout, I have these delegate command instances, but they are all wired to a presenter. So it gives the nice medium between maintainability and also still being able to leverage the capabilities of WPF.
It's interesting. We initially started off looking at a hybrid of presentation model and Model View Presenter, and one of the reasons for that is data binding in WPF takes out a whole new meaning than what you were used to. If you haven't worked with WPF and WinForms, data binding is very simple in the sense that what you can do with it is specify if this value is to show or not, column wise. In WPF you have data templates that allow you to actually decide the rendering of the content. So it's not just: "Hey, here is a set of fields or here is a set of rose in a grid". It's: "Here is how I want each field to render.
Here is the UI elements and the styling and things that I want to apply." Because of that rich functionality that it gives you, it allows you to consolidate and use, and plus that data binding is aware so that when a change happens in the object it's two way: it knows the change happened in the object and the UI detects it and is automatically updated. So that allows us to consolidate and create these UI presentation models which are shielding the domain model behind the scenes and doing things they are completely UI specifics; so they are not violating separation of concerns because their concern is the UI.
And you can just, as Fowler calls it, throw those models against the glass and render them. Currently we've been doing a hybrid of both. We have models that we have commands on and then we wire up to those commands and we have a presenter in some cases that's responsible for creating the model and doing some of the handling of those commands. So, you know, the commands hang of the model, there're those delegate commands, so we can wire them in. But what we've been looking at, and we just had a meeting yesterday with the WPF team, is it may make sense actually consolidate and just have presentation models. Because WPF is so rich, it mitigates the needs necessarily to have the separate presenter.
Now this is not final and this is showing you that this is still a work in progress, but it's also illustrating the challenge of what we have to go through which is that it's not necessarily always a clear A to Z path. What makes me feel good about that is because we are investing that work that means that's work that hopefully costumers won't have to do because we'll be able to paint to them and say: "Here is why you should consider presentation model, here is why you should consider using MVP. We think this one is probably better for most of your scenarios" so that is the kind of guidance that's there. But the definitely those two patterns are the big players plus the command pattern because of the inherent command support.
The first thing was we had a challenge with this as we started to talk to customers about Prism because they came with that CAB context. It was like: "Ok, I want CAB for WPF" and we set a line in this end and said "No" because we thought that was the right thing. We said: "We want to understand your scenarios. If you are going to tell us about a workspace or a work item, we want to know what the work item gives you, not how can we do the work item in Prism." One of the things we did, and I think it's one of the great things about being in Patterns and Practices, is that when we went off to start Prism we didn't come to costumers 3-4 months in and say: "Hey, we've been building this. What do you think?".
Actually we spent about 6 weeks spiking around WPF. I probably spent about 8 months leading up to Prism, gathering feedback of what people didn't like about CAB, but it was all part of the research process, even though I didn't know that Prism was actually going to happen initially, but it was quite a lot of research in terms of gathering all this information. Then what we did is we called out about 20 customers and partners and experts in the industry; I am including Jeremy Miller, who is here, out to Redmond, and we had a customer review and what this was very different about is a lot of people hear about SDRs and things that go on at Microsoft, this was: "Hey, we've done nothing yet, except a bit of exploration.
Here is what we think we know, here is what we think we should be focusing on. What do you guys think?" And we literally shifted our direction significantly based on that 3-day-meeting with costumers. Back to your question, yes there were a ton of requests from across the board and that is a challenge for us. We have to look at those requests and say: "What are the things that we think it's feasible for us to focus on? What are the things that will be the biggest bang for the biggest buck?" One thing, for example, was around domain isolation. There was a big concern from a few of the customers that: "Hey, we really need this."
But to the majority they didn't feel they needed it, but the bigger thing was that when we spiked on how we would do it, it looked like it was a major effort and we were like: "Ok, if we do this, this could be like taking away from 50% of the other things that we want to do". So we had to be disciplined, we told customers: "Look, we are not going to do this. We can't. We hear it's a concern for some", so we did basically a middle way which was: "We provide the hooks for us that if we want to do it." That is what some of our bigger customers, they said: "We throw 20 people on our team to do this, just give us the hooks." So that has been the balance. The other thing is we, of course, use our CodePlex community site, we have an advisory board which actually consisted mostly of those people that came out to Redmond, but others additionally who have been throughout the development of our deliverables, like every two weeks we are having advisory work meetings, reviewing what we are doing, projecting our back log of features and we prioritize that way.
One of the things we've done is we've come up with, and probably some of the viewers might have seen the blog post where I talked about this thing called "simple first development". And we said that one of the challenges we saw from a CAB perspective is that the simple path in many cases was as difficult as the complex path, in order to do the simple thing, because we wanted one way of doing things, it was much more complicated than it needed to be. So in Prism we've really looked at this simple path and this complicated path and said: "The two approaches don't have to be the same. If we can address 80% of the scenarios with the simple path, let's do that and in certain cases we may have to turn up the complexity bar, but that will only be for those complex cases."
So one of the places where we've done that is in this commanding, in commanding we've got other this like: how do I deal with commanding for multi-instance. Well if I don't have multi-instances of orders for example, open at the same time then I don't need any of that multi-instance stuff that we've done with commanding; we call it composite commanding. So you don't have to, that is the nice thing; you don't have to use it at all. With those regions I was just describing we have the ability to have these instance regions, where I have these composite views that are within my application that need to have their own localized regions that they can push into.
But again the 80-20, there is a lot of case, maybe not the 80-20, but there is a significant number of cases where you don't need that. So again it's like turn up the complexity; if you don't want it, it doesn't affect you at all. If you want to use it, use it. And I think that is where we are doing a lot of great work in what we are doing now with Prism in that we are keeping that dividing line. And we are saying some things we just won't do them, but we won't preclude you from doing them because again like you mentioned we are not looking at this as the super framework; as a matter of fact I said several times that I think success is not solving world hunger. Having less features is actually a feature, so Prism right now is essentially has a reference implementation, a stack trader application and we are building around scenarios in that app. And if there is any reusable code, it's based on that app, it's not based on every single kind of application that developers are going to build.
Of course. Everything we do in PMP is done through test driven development and we try to share that with the community. We also look at promoting test driven development or promoting at least testability. You don't necessarily have to do test driven development, but we do want to enable it because we believe in it, but at least having the ability to build things in a decoupled manner so that they can be unit tested. So when you look at Prism we certainly have unit tests, we even have acceptance tests; we've been using White which is a ThoughtWorks open source acceptance test framework. We include the acceptance tests with our deliverable and you can look at those and see how we are using it; you could download White. We also do talk about things like separated presentation patterns like I mentioned: MVP, presentation model; so we are going to illustrate for you how you can do that and we are looking at WPF and saying: "In WPF the problem gets a bit more complex because you've got this great XAML thing that I can put all this mark-up in, but I've got to be disciplined as to what kind of logic I put in there". So that's going to appear in the guidance. So you'll have RUnit tests for everything that we build, and you'll have a set of guidance on how to do things in a testable fashion.