Friday, October 08, 2010

My Silverlight 4 Reference Architecture: Commanding

After sharing my thoughts on unit testing in Silverlight and the combination of NHibernate and WCF Data Services, it is time to discuss the updated version of the Silverlight reference architecture from one of my posts of last year. To put the discussion into perspective, here is a diagram illustrating the layers, components and supporting frameworks I use, and which I will refer to in the coming posts.

clip_image001

I've seen many projects stumble on the decision on how to expose the domain model via web services. And more often than that, I've received questions on how to deal with the granularity of DTOs versus domain entities. To overcome that problem myself, I decided to include some aspects of the CQRS principle. Changes to the domain are now solely tunneled through one or more Commands, and queries are executed on a dedicated REST Service.

Commands have several advantages. They are expressed in the Ubiquitous Language which lowers the threshold between the developers and the business. There is no need for any tedious and elaborate conversions between incoming DTOs and domain entities.

And because those commands are already very business-oriented, the Command Handlers replace the traditional domain services that you often find in a system build around DDD concepts. And although a task-based UI is better suited for an architecture like is, I managed to break down the user interaction of a CRUD-style application into logical commands without too much trouble.

Because they are very focused they often can be directly mapped to corresponding methods on the aggregate root in the Domain Model. That's why I use a generic command handler that uses mapping attributes and conventions (an idea I borrowed from the NCQRS framework) to map entity references to the actual entity instances. The following example for instance, maps a command to the equally named method of the Registration aggregate root.

    [DataContract]
    [MapsToAggregateRootMethod(typeof(Registration), "ChangeShelfLife")]
    public class ChangeShelfLifeCommand : VersionedCommand
    {
        [DataMember(IsRequired = true)]
        public string PresentationName { get; set; }

        [DataMember(IsRequired = true)]
        public int ShelfLife { get; set; }
    }

This example illustrates two other aspects of my implementation: that each command is a WCF data contract, and that most commands are supposed to be applied to a specific version of an aggregate root. The latter is not required, but it occurs that often that I created a simple base class for that. The signature of the single operation of the Command Service is:

    [OperationContract]
    public string Execute(IEnumerable<Command> commands) { }

Which means I can pass a whole batch of commands from the Silverlight client back to the command service.

In the next part, I’ll discuss the querying aspects of this architecture.