Monday 20 September 2010

Update

After months of defect resolution and testing our code finally shipped this morning.  The effort to deliver this product was beyond anyone's estimation.  The difficulty was not so much on the .Net front, but more in the area of system coordination.

Some background...we set out to develop a WPF/Prism application which would be run on a mobile handheld device (think fat, rugged iPad).  That, in itself, is not terribly difficult, it was everything else that proved to be challenging.  Namely four separate SAP systems, all contributing data which get bundled up and distributed to the mobile device via SAP's NetWeaver.  And then back up again...

On a good day it's hard enough to get SAP to play with SAP, raise that to the fourth power and add SAP's own client synchronization framework in the mix...well, you get the idea.  It's a minor miracle it works at all.

This is my second large SAP/.Net development project, and this one being the largest and most complex of the two.  Now, I'm the first to admit that I can be a techno-bigot.  I love working with C# and .Net and frameworks like Prism and MEF.  There is a real elegance that can be achieved and when you get it right it's poetry in motion.

Compare that with SAP...well, it's a dinosaur.  A plodding, kludgey artifact from the Stone Age.  I'm sorry, it's not my intention to offend, but it's true.  I sometimes wonder how long SAP can continue, while the rest of the world races ahead with more and more sophisticated development tools?  Not to mention the inherent complexity and true cost of ownership.

That said, I can say SAP does what it says on the tin, often times with a half dozen SAP Consultants hovering over scratching their chins.  I have to admire these guys, namely because they have the patience and persistence to work with these types of systems.  I don't know if I could do what they do.  If the technology I'm working with becomes too restrictive or cumbersome or complex I simply find another.  Not so in the world of SAP.  What you see is what you get...warts and all.

Enough of that.  In the end, after shedding blood, sweat and tears, we got there and it was a real team effort of two very different IT cultures.

Now onto version 2...
        

Monday 3 May 2010

Some Observations...

Sorry for neglecting this blog, I'm in the throes of delivering a large mobile application, which has consumed all my waking hours.

In our big push to get this product out the door, we've brought on-board additional developers.  Unfortunately,  they were not sufficiently grooved in to our architecture and coding standards.  As you can imagine, the result was less than expected.  One of the purposes of having a known architecture, in my opinion, is that it serves as a point of agreement within the team.  It defines where things are located, what function it performs, what its relationship is to other parts of the system.  In short, it establishes order and structure to a large number of projects and should bring about simplicity.

When someone does not adhere to the agreed upon architecture they can be counted upon to introduce complexity.  To the uninitiated faced with a solution with 40-50 projects, all is complex.  Any changes they introduce will undoubted contain that complexity.

On a similar note, regarding WPF....

Whenever I see Xaml loaded up with Alignment, dimension attributes, etc, or StackPanels within StackPanels within Grids within StackPanels...ad nauseum, I know what the developer was experiencing.  He is using more and more settings and properties to force the Xaml to behave a certain way.  This brute force approach always bloats your code and is always inefficient.  If the UI does not bend to your will, the compulsion is to add more settings - this is almost always a mistake.

My golden rule when working with Xaml is:  Less is More.

If I'm faced with sorting out some misbehaving Xaml, the first thing I do is delete all the unnecessary properties and work with the core object.

Anyway...just some observations.  I'm hoping to be more active on this blog once I've completed this current project.

One new development effort I've been working on in the evening, is creating a Win 7 Media Center Add-in using Visual Studio 2010 and the Media Center SDK.  It's my first attempt, so I hope to have something worthwhile to report.

Wednesday 24 March 2010

New Composite/Pattern Forum

A new developer forum has been launched dedicated to composite technologies and design patterns, including Prism, MEF and MVVM.

http://www.compositedevpatterns.com/forum.php

Wednesday 10 February 2010

Prism Guidelines

Introduction
Due to the number of projects and files which can make up a Prism solution, it is important to adhere to conventions which are intuitive and sensible.  Maintaining these conventions takes the guesswork out of working with Prism and makes navigating through a solution predictable.
This document assumes a basic understanding of Prism, the Model-View-ViewModel (MVVM) design pattern, the Model-View-Controller (MVC) design pattern and Windows Presentation Foundation (WPF).

Modules
Prism requires that each module contain a class which implements IModule.  This effectively serves as a stub, allowing Unity to load the module.  IModule has an Initialize method that is often overridden and is used to register items in the container.


Avoid using the Initialize method to register the module’s items, instead create an entry in your unity.config file.  It is easier to maintain and does not involve code.

Views
GOAL: To maintain a separation of UI and business logic.
It is rare that a UI requirement cannot be expressed using Xaml alone.  Effort should be made to eliminate any UI logic contained in the View. 

Views always have a corresponding ViewModel.

Setting the ViewModel
Each View should contain a setter for its ViewModel, as shown below.
This property uses the Microsoft.Practices.Unity.DependencyAttribute, which gets picked up by Unity and automatically set.

Use of Styles
Avoid defining custom styles which effect appearance within your module or view.  Instead, use styles defined in your application resource assembly.  If you need to modify a control’s behaviour through the use of a Trigger, use the BasedOn property of the Style, referencing the resource Style.
Always reference the resource Style by using a ComponentResourceKey defined in your Interfaces assembly.
Style="{StaticResource {ComponentResourceKey TypeInTargetAssembly={x:Type Resources:Styles}, ResourceId=DialogBorderStyleKey}}"

Use of Converters
Avoid excessive use of custom converters (IValueConverter).  Often the same can be accomplished using Triggers or DataBinding.  Converters can act as “hidden” code-behind, making testing difficult.  Always look for a Xaml solution before resorting to the use of converters.

Naming Conventions
TYPE NAMING RULE EXAMPLE
View <name>View CustomerDetailView
Interface I<name>View ICustomerDetailView


ViewModels
GOAL: To encapsulate all UI-related logic in a single, testable class.

The ViewModel exists to serve the View, so use it.  Instead of using custom Converters do it in your ViewModel.

Avoid passing the IUnityContainer (or an abstract version) in your ViewModel constructor.  This hides the actual dependency and makes testing difficult.

Consider implementing INotifyPropertyChanged on your ViewModel so your View can respond to changes in the ViewModel.

Naming Conventions
TYPE NAMING RULE EXAMPLE
ViewModel <name>ViewModel CustomerDetailViewModel
Interface I<name>ViewModel ICustomerDetailViewModel


Interfaces
GOAL: To provide contracts that define a public interface, separate from its implementation.

Prism relies heavily on the use of interfaces.  All entities registered in the UnityContainer must include an interface and an entity that implements the interface.

Do not include public interfaces in your implementation assemblies, as this defeats the purpose of decoupling interface from implementation.


UserControls
GOAL: To provide reusable UI elements independent of implementation.

WPF UserControls differ from Views in that they do not have a related ViewModel.

Consider adding DependencyProperties to your UserControl to take advantage of DataBinding and Triggers, this makes your UserControl more versatile and reusable.

Avoid including binding to specific properties in your UserControl as this can greatly limit its reuse.

Naming Conventions
TYPE NAMING RULE EXAMPLE
UserControl <name>UserControl AddressUserControl


Services
GOAL: To provide static, stateless business logic and functionality across domains.

Services are normally registered in Unity as a singleton.

It is best to think of Services as a static library of methods.  If state persistency is required consider using a Controller (MVC pattern).

When consuming Services, avoid accessing them through IServiceLocator, instead explicitly use the service interface in your class constructor.  This makes for predictable testing and does not hide functionality or dependencies.

Naming Conventions
TYPE NAMING RULE EXAMPLE
Service <name>Service LoggingService
Interface I<name>Service ILoggingService

Events
GOAL: To provide multicast notifications across domains.

Note: The events referred to here are to be used by the EventAggregator, not standard .Net events.

Do not define events in your implementation assemblies. Since other assemblies will need to reference your event class placing them in an implementation assembly forces you to create a strong reference. Instead, place it in your interface assembly or, if appropriate, a shared core assembly.

Naming Conventions
TYPE NAMING RULE EXAMPLE
Event <name>Event SaveCustomerEvent
Handler <name>EventHandler SaveCustomerEventHandler


Commands
GOAL: To provide an input mechanism which allows for multiple and disparate sources to invoke the same command logic.

Include command logic in your ViewModel, or if using a Controller you may want to defer execution to the Controller.

Consider using a Command Behavior AttachedProperty to convert events to Commands on controls that do not natively support ICommand.

Naming Conventions
TYPE NAMING RULE EXAMPLE
Command <name>Command SaveCommand
Handler <name>CommandExecute SaveCommandExecute
<name>CommandCanExecute SaveCommandCanExecute

Conclusion
Prediction and consistency go a long way in working with Prism. Not subscribing to agreed upon conventions adds confusion and slows down development.

Monday 25 January 2010

Code Complexity and Prism

I've recently had to review a number of problem areas of a large Prism project.  In the course of review, I had a number of realisations regarding design patterns, WPF and code complexity.  We use MVVM and MVC design patterns throughout our project.  Not surprising, many of our problem areas were related to divergence from these patterns.

In our implementation of MVVM we strive to have a complete decoupling of our Xaml views and any business logic.  So, finding views riddled with code-behind indicated a lack of understanding of:

  1. The MVVM design pattern, or
  2. The benefits of code separation

Or as I was to find out, a limited understanding of Xaml.  The view in question utilised over ten custom converters.  Not that converters are inherently evil, however, these converters were being used where Triggers or Data Binding could have easily gotten the job done.  But, if one is unfamiliar with these, they tend to use techniques they are familiar with -- in this case, IValueConverter.  Poor use of custom converters effectively becomes "hidden code-behind," and is difficult to debug and test.

Additionally, I found the ViewModel being underused and misused, providing a sparse selection of high level properties for binding.  This, in part, prompted the excessive use of custom converters.

The offending code-behind was an unusual solution brought about by a lack of Xaml know-how.   All of this code could have been expressed using Xaml.  Conclusion: Knowing a little about Xaml can reek havoc on a well-structured Prism project.

The hallmark of these decisions is code complexity, your first clue things have gone astray.

After much refactoring, including the removal of all the custom converters, the code-behind and reworking the ViewModel, the whole area straighten out and was greatly simplified.  It was a prime example of the power and importance of design patterns in maintaining good form and structure.

Saturday 2 January 2010

MEF Presentation Video

A work colleague recently turned me on to Microsoft's Managed Extensibility Framework (MEF) [see http://mef.codeplex.com/].  For anyone into Prism, MEF is worth a look.  Headed up by Glenn Block of Prism fame, MEF is an impressive technology.

Glenn gives an hour long MEF presentation at PDC 09 at http://microsoftpdc.com/Sessions/FT24.

In addition to an MEF orientation, there is a short presentation on MEF + Prism.

Exciting stuff, in a geeky sort of way.