PRISM from Patterns and Practices


I’ve been looking into the Prism framework that came out of the Patterns and Practices team – if you’ve not heard of the framework, it’s basically the WPF and Silverlight version of Smart Client Software Factory. And if you’ve not heard of that – well, it’s a framework and set of guidance packages to write modular, decoupled and extensible applications i.e. any application that you expect to have a medium-long shelf life with changes throughout it’s lifespan.

I’ve had a relatively short look at it but expect to be spending more time with it over the next few weeks and months. So far, it looks like it addresses a number of the shortcomings of SCSF, such as the lack of flexibility with the framework in terms of IoC container (which was pretty much fixed to object builder in SCSF) and a clearer set of services and interfaces. It also allows you more control in terms of how you register modules within the shell than SCSF.

Generally, so far it seems more lightweight and easier to access than SCSF, although it retains many of the concepts. As I touched on before, it can use any IoC container that you want, although by default it uses Unity – which suits me fine as I really like that.

One thing I’ve not seen a decent answer on yet is how to register regions (think workspaces) into a modal dialog; in SCSF you had a modal dialog workspace which popped up a window automatically when you did a ShowViewInWorkspace – not seen anything like that in Prism yet.

There are a good set of videos on the net on Prism; I’ve been going through good old Mike Taulty’s series on Channel9 recently, and I’d recommend that if you want a good start in Prism. In particular, the first video is an excellent introduction if you have never thought about how to write decoupled and extensible applications using principles like SRP and the like.

Assembly references and dependencies


I’m currently working on a largish solution in VS2008 – maybe fifteen or twenty projects. We’re using Smart Client Software Factory (SCSF) and TDD for all of our code where possible. One of the things that SCSF gives you is the ability to create a unit test project for every business module that you create for free. This is nice, except that having all those extra projects slows down build time and almost doubles the number of assemblies that you have. Plus, it makes it harder to share code across your unit test projects.

So I made the decision a few days ago to make a new unit test project which would contain all our unit tests, divided by folders and namespaces for the different areas that we were testing. This has turned out to be a Good Thing, as we now can easily e.g. make base unit test classes to do a lot of the grunt work of our unit tests – so it aids readability when maintaining the tests, and also cuts down on the boilerplate code that you need to write.

Anyway, you might be wondering “what does this have to do with assembly references”? Well, the problem I noticed shortly after doing this was that the build time just for running unit tests was pretty long – maybe twenty seconds. Bear in mind that we might change unit tests every minute or so – so effectively a third of our time is being wasted on rebuilds of the solution. I couldn’t understand why this was until I looked at the build output window – EVERY referenced project gets rebuilt whenever we modify a unit test!

Understand that our unit test assembly references maybe ten (or more) different assemblies containing testable code – every time we need to change a single unit test, it rebuilds all ten of them – even those that have no dependencies on them. None of them have changed at all – just the unit test project. And there’s nothing referencing my unit test assembly at all.

I can’t understand why this is. On my home PC, doing this doesn’t do the same thing – if I create a class library and then a unit test project, and then modify some of the unit testing code (but NOT the class library itself), I see the following in VS’s output window:

 

—— Build started: Project: ClassLibrary1, Configuration: Debug Any CPU ——
ClassLibrary1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll
—— Build started: Project: TestProject1, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll" /reference:"C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\TestProject1.dll /target:library Properties\AssemblyInfo.cs UnitTest1.cs

Compile complete — 0 errors, 0 warnings
TestProject1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\TestProject1\bin\Debug\TestProject1.dll
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

 

Notice how TestProject1 does a recompile (with the call to csc.exe), whereas ClassLibrary1 does not – because VS knows that ClassLibrary1 has not changed.

If I then do indeed modify something in ClassLibrary1 but not TestProject1, and re-run my unit tests, I get the following:

—— Build started: Project: ClassLibrary1, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\ClassLibrary1.dll /target:library Class1.cs Properties\AssemblyInfo.cs

Compile complete — 0 errors, 0 warnings
ClassLibrary1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll
—— Build started: Project: TestProject1, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll" /reference:"C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\TestProject1.dll /target:library Properties\AssemblyInfo.cs UnitTest1.cs

Compile complete — 0 errors, 0 warnings
TestProject1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\TestProject1\bin\Debug\TestProject1.dll
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

 

This time, both projects have been recompiled – ClassLibrary1 because it was changed since the last build, and TestProject1 because it’s dependant on ClassLibrary1. This makes perfect sense to me.

If I add another class library into the mix, VS continues to behave properly, only doing rebuilds where necessary.

Yet on my work solution, this is not the case. EVERY assembly gets rebuilt EVERY time. I cannot find any rhyme or reason for this though! Does anyone know how VS determines whether an assembly is “dirty” (and therefore needs to be rebuilt) – my guess is that something is interfering with that and causing it to rebuild every assembly regardless….

Smart Client Software Factory – Day Two


So, I’ve managed to get through most of the problems and actually worked through a few of the labs! Some of what SCSF gives you seems quite good – a lot of the stuff that you do (or would like to do) in projects but generally do in a different way each time. Things like the following, which I have done in the last few projects in a bespoke manner that you get pretty much for free with SCSF: –

  • Model-View-Presenter framework
  • Commands / multicast delegates (nothing you don’t get in C# anyway except that you can do it quite elegantly using attributes on methods)
  • Decoupling between your form’s shell and inner modules / views
  • View management
  • Inter-view messaging

I’m sure that there’s lots more to see. But I’ve also found a few more annoying things about it: –

  • When you try to create a new View in VS2008 SP1, if your Infrastructure assembly is not named Infrastructure.Assembly but instead <root namespace>.Infrastructure.Assembly, the option won’t appear in VS! Why???
  • Namespaces of views that you create do not obey folder hierarchy rules e.g. a View + Presenter living inside MySolution/MyProject/Views/MyView should have a namespace something like MySolution.MyProject.Views.MyView.MyView.cs and MyPresenter.cs etc.. Instead, it’s simply in MySolution.MyProject. This is (IMHO) just plain wrong. VS automatically pads on the namespace for new classes based on the folder structure, so why doesn’t SCSF? Even worse, any other classes that you create will obey the “proper” rules so you end up with classes in the same folder with different namespaces!

So generally I think SCSF looks quite nice, albeit it seems like they haven’t updated it in a while and that it’s got a few issues with it that could have been fixed relatively easily but they just haven’t been bothered / had time (note – last version of SCSF WinForms was April 2008)??

Smart Client Software Factory Review – Day One


Its looking like we’re going to use Smart Client Software Factory (SCSF) 2008 as the UI framework for writing my next project. As part of that, I’m spending the next few days getting up to speed on SCSF (since I’ve never “really” used it before in anger)… here’s my thoughts as I go through the install process and the guiding SCSF Lab sessions…

12.15: OK. Firstly, the default install we have on my PC doesn’t work – when I try to create a new SCSF project type (Guidance Packages/Smart Client Development) it comes up with a warning about a missing registration to a VB dll – not a good start. Drop a colleague an email to ask about this… seems like it’s a known problem with our builds and I need to reinstall it.

12.25: Reinstalled the SCSF framework off the network.

12.30: Open up the Lab sessions word document, and successfully create a new Project.

12.35: Firstly thing I notice is that assembly Titles, assembly Names, and Namespaces in those assemblies do not match e.g.

  • Assembly name: AdventureWorks.Infrastructure.Shell
  • Namespace: AdventureWorks.Infrastructure.Shell
  • Assembly Title: Shell

Why is the Title not the same as the other two (Title is what you see in Solution Explorer)??

12.40: Following the instructions in the word document, I hit F5 to run the project. It crashes immediately:

Assembly file C:\Dev\AdventureWorksCyclesEx\bin\Debug\Infrastructure.Module.dll was not found.

I email a colleague again and then go for lunch.

13.45: I find out how to fix this problem – it’s actually related to that mismatch of assembly names etc..

There’s a config file called ProfileCatalog.xml which lists the different modules of your application. It puts in the Infrastructure module automatically, except it does it wrongly – it puts in the Assembly Title instead of it’s Name e.g. “Infrastructure.Module.dll” instead of “AdventureWorks.Infrastructure.dll”. Change this and it works:

<Modules>
    <ModuleInfo  AssemblyFile="AdventureWorks.Infrastructure.Module.dll"/>
</Modules>

14.00: Try to add a new smart part to the Shell, but the toolbox doesn’t yet have the controls in there, so I have to add them myself (Microsoft.Practices.CompositeUI.Winforms.dll).

14.05: I drag a Tab workspace onto the Form. Visual Studio complains that I already have a reference to the above WinForms dll. I have to remove the reference from the project and then it works. Why??

14.20: More problems with assembly references. It seems that the project by default references one version of the CompositeUi dlls whereas the one I added above is a different version, so I’m now getting version mismatches. I have to go through all the projects in the solution, remove the references to the old version and add the references to the new one.

To be continued…

Model View Presenter


I’m playing around with the Model View Presenter (MVP) design pattern for use in a new project. At first I found it a little strange – we’ve been toying with the use of the Microsoft Smart Client Factory (MSCF) which makes use of MVP; however, the project I’m on won’t be using the MSCF – so I went about implementing my own version of it.

At first I found it a little unusual – however, I’ve now gotten my head around the main issues with it (such as confusing it with the Model View Controller pattern) and am happily using it. One thing I find strange is that the MSCF classes seem to suggest that your Presenter is in the same physical assembly as your View – I always thought that the whole point is to abstract the two apart from one another, hence allowing you to replace the View with another one. You can of course still do this in the MSCF implementation, but I couldn’t understand why they’ve somewhat coupled the two together by putting them in the same assembly.

Another thing that’s confused me. Who’s responsibility is it to control navigation between one view/presenter and another one e.g. your first View has a button on it, and on clicking this you want to navigate to a new view. In your first View, should you do something like this?

// On click event

MyChildForm Child = new MyChildForm ();

MyChildForm.ShowDialog ();

I don’t like this approach, because you’ve got business-level logic in your View i.e. controlling navigation to another part of the system. What if you had some complex business logic there? I suppose you could have a method on the View’s interface like "LaunchChildWindow()" which would get called by the Presenter, and move the business logic into there like so:

// In View

private void ButtonClickHandler (object sender, EventArgs e)
{
Presenter.DetermineNavigation();
}

#region Implementation of IView
public void ShowChildFormA ()
{
ChildFormA MyForm = new ChildFormA ();
ChildFormA.ShowDialog ();
}

public void ShowChildFormB ()
{
ChildFormB MyForm = new ChildFormB ();
ChildFormB.ShowDialog ();
}
#endregion // In Presenter public void DetermineNavigation ()
{
if // bla View.ShowChildFormA (); else View.ShowChildFormB (); }

However, I’m still not convinced about such an approach, and so thought about the Command pattern.

Bear in mind that my Presenters are in another assembly to my View, and therefore can’t reference the View assembly (circular reference). So what I ended up doing what implementing a set of Commands. These live in a third assembly and have a reference to my Views assembly and can leave those Views as required. They implement an ICommand interface that is defined in my Presenter assembly. So depending on some business logic, a Presenter may launch a Command as required. The Command may spawn another Presenter/View combination off, or it may create some business logic class etc.

The only issue I have with this approach is where my business logic sits – some are in the Commands, some in the Presenters. I think I’ll end up making presenters even for non-visual commands (or some other classes) so that all my business logic is in one place – plus they shouldn’t sit with the Command tier as that currently is closely coupled to my UI layer.