Aggregated specifications

An example from my inversion of control talk involves a message formatter.  It applies formatting rules to a string.

public interface IMessageFomatter
{
    string Format(string message);
}

Instead of doing all the work in the implementation of this interface, the message formatter will aggregate several distinct rules.  An inversion of control tool is configured to compose these rules and provide them to the formatter.

public class MessageFomatter : IMessageFomatter
{
    private readonly IFormatRule[] _rules;

    public MessageFomatter(IFormatRule[] rules)
    {
        _rules = rules;
    }

    public string Format(string message)
    {
        foreach (var action in _rules)
        {
            message = action.ApplyRule(message);
        }
        return message;
    }
}

In this way each rule can be small, testable, and have only one job.  I can add functionality to the formatting process without changing the formatter or any existing rule. 

public interface IFormatRule
{
    string ApplyRule(string text);
}

public class DisclaimerRule : IFormatRule
{
    public string ApplyRule(string text)
    {
        return text + "\nDisclaimer: This message will self-destruct";
    }
}

public class UppercaseRule : IFormatRule
{
    public string ApplyRule(string text)
    {
        return text.ToUpper();
    }
}

This technique is extremely powerful and we use it all over the place in our projects.

Recently we were building a search screen.  It has several text input boxes and select lists and radio button groups, you know, the standard enterprisey UI mess.  Anyway, that's what it was and it's a common feature in the apps I work on. I've seen the scenario over and over. But armed with the above technique and LINQ to NHibernate, we were able to craft a much more elegant solution than we had previously created.

First we have a type that represents the search query.  It could be implemented by the class that represents the user interface form or be built by the user interface layer.  It's sent to a service that will perform the query.

public interface IProductSearchQuery
{
    decimal? Price { get; set; }
    int? PriceRange { get; set; }
    string Name { get; set; }
    ProductCategory Category { get; set; }
    // ...
}

public interface IProductRepository
{
    Product[] Search(IProductSearchQuery query);
    // ...
}

What we don't want is a huge method that checks to see if a search criteria exists and then conditionally appends predicates to a database query.  That's the old school way, and it's a beast to test and to change.  Adding a user interface element, like a new text input field, would require us to change that big method by introducing repetitive and dangerous new code.

What we do want are small, isolated specifications that we can aggregate like the message formatter.

public interface IProductSearchFilter
{
    bool ShouldApply(IProductSearchQuery query);
    IQueryable<Product> Filter(IQueryable<Product> candidates, IProductSearchQuery query);
}

An example filter:

public class PriceRangeFilter : IProductSearchFilter
{
    public bool ShouldApply(IProductSearchQuery query)
    {
        return query.Price.HasValue && query.PriceRange.HasValue;
    }

    public IQueryable<Product> Filter(IQueryable<Product> candidates, IProductSearchQuery query)
    {
        return from product in candidates
               where product.Price <= (query.Price + query.PriceRange)
               && product.Price >= (query.Price - query.PriceRange)
               select product;
    }
}

You can test drive this thing.  It's small and distinct.  And using LINQ to NHibernate you can combine several of them in a way that produces one select.

public class ProductRepository : IProductRepository
{
    private readonly ISession _session;
    private readonly IProductSearchFilter[] _filters;

    public ProductRepository(ISession session, IProductSearchFilter[] filters)
    {
        _session = session;
        _filters = filters;
    }

    public Product[] Search(IProductSearchQuery query)
    {
        var products = _session.Linq<Product>();
        return _filters
            .Where(x => x.ShouldApply(query))
            .Aggregate(products, (candidates, filter) =>
                filter.Filter(candidates, query)).ToArray();
    }

    // ...
}

One tricky spot for a lot of people is that Aggregate call.  It does the exact same thing as the foreach in the message formatter: passes the seed (products, in this case) through the filters aggregating the result.  The lambda parameter variable candidates is the result of the previous filter (or the seed for the first filter).  In other ecosystems besides .NET, Aggregate is called reduce.  You can see why - each filter reduces the candidates according to its specification.

When you think about it, an entire architecture could be a reduce. That would be really interesting.

Posted in C#, Domain-Driven Design | 7 Comments

AutoMapper in NerdDinner

Speaking of NerdDinner, Scott asked me to use it to create an AutoMapper example. logo

AutoMapper, the brainchild of Jimmy Bogard, is an object-to-object mapper.  What that means is up to you – but we’ll use it here to map from the domain model to a view model.  The view model is an object heirarchy that represents the screen.  It’s as dumb as possible, just like the view.

We get a lot of nice things out of it and it helps us go faster.  You can read more about it AutoMapper from Jimmy or at the website on Codeplex.

For starters, NerdDinner isn’t the best scenario in which to apply AutoMapper.  NerdDinner is very small so there’s not much reuse to harvest. For example, if you format dates the same way a million times you can use AutoMapper to only write that formatting code once.  In a small application you may format dates two ways and only use the resulting text in two views.  It doesn’t make a lot of sense to extract a class just for that – it will seem like a lot of overhead. 

Also NerdDinner doesn’t have a rich domain model – there’s just not that much to do.  So the AutoMapper feature of flattening complex hierarchies can’t be appreciated.

I posted the result of this quick and dirty spike as a sample project – hopefully this will help you get started looking at it.

First, I copypasted a class to bootstrap AutoMapper:

namespace NerdDinner.Helpers.AutoMapper
{
    public class AutoMapperConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(x => x.AddProfile<ViewModelProfile>());
        }
    }
}

.. which will be called when the application starts:

void Application_Start()
{
    AutoMapperConfiguration.Configure();

    RegisterRoutes(RouteTable.Routes);

    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new MobileCapableWebFormViewEngine());
}

I copypasted another class that will check the mapping configuration for errors, providing fast feedback should I make a mistake.

[TestClass]
public class AutoMapperConfigurationTester
{
    [TestMethod]
    public void Should_map_dtos()
    {
        AutoMapperConfiguration.Configure();
        Mapper.AssertConfigurationIsValid();
    }
}

Now I'm ready to begin creating the view model and configuring AutoMapper.

To design a view model, start with the screen.  What's displayed will be represented in the model.  Again: the view model is an object hierarchy that represents the user interface.  I picked the Dinner Details screen, by the way.

The current model being used by the view was the Dinner entity itself.  There was a lot of formatting in the view and a lot of duplication.

Almost every property was surrounded by code that would HtmlEncode it (it will be nice to have AutoMapper do this for us):

<%= Html.Encode(Model.Title) %>

And there is a lot of formatting to do:

<abbr class="dtstart" title="<%= Model.EventDate.ToString("s") %>">
    <%= Model.EventDate.ToString("MMM dd, yyyy") %>
    <strong>@</strong>
    <%= Model.EventDate.ToShortTimeString() %>
</abbr>

Imagine a project with 300 screens and a team of analysts and you can imagine that specifying this formatting over and over again in requirements documents and planning would become tedious.  Not to mention coding it.  It'd be easier to just say: "Format this date in the standard way." You can also imagine the security implications of forgetting to encode even one value.

In converting these screens to use a view model instead of the domain model I didn't want to change existing functionality.  So I took this:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>"

and changed it to this:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<DinnerDetailsViewModel>"

See what I did there?  I just changed the type of the Model property to a new DinnerDetailsViewModel type.

The view will receive a view model mapped from the domain model when I apply a special action filter to the controller action:

[AutoMap(typeof(Dinner), typeof(DinnerDetailsViewModel))]

The code's in the sample, straight from Jimmy's post.

I started out with DinnerDetailsViewModel being an empty class definition and used Resharper to generate each property as I encountered it.  I removed the formatting and the ubiquitous encoding from the parameters, turning this:

<div id="dinnerDiv" class="vevent">

    <h2 class="summary"><%= Html.Encode(Model.Title) %></h2>

    <p>
        <a href="http://feeds.technorati.com/events/<%= Url.AbsoluteAction("Details", new { id = Model.DinnerID }) %>">
            Add event to your calendar (iCal)
        </a>
    </p>

    <p>
        <strong>When:</strong>
<abbr class="dtstart" title="<%= Model.EventDate.ToString("s") %>">
<%= Model.EventDate.ToString("MMM dd, yyyy") %>
<strong>@</strong>
<%= Model.EventDate.ToShortTimeString() %>
</abbr>

into this:

<h2 class="summary"><%= Model.Title %></h2>

<p>
    <a href="http://feeds.technorati.com/events/<%= Url.AbsoluteAction("Details", new { id = Model.DinnerID }) %>">
        Add event to your calendar (iCal)
    </a>
</p>

<p>
    <strong>When:</strong>
    <%= Model.EventDate %>
</p>

I had to write a formatter to replace the custom formatting performed by the view.

public class AttendeeNameFormatter : BaseFormatter<string>
{
    protected override string FormatValueCore(string value)
    {
        return value.Replace("@", " at ");
    }
}

See how testable that is; small and reusable?

I also moved some methods that were previously being called from the view directly into the domain model which AutoMapper will evaluate at runtime.

Before:

<p id="whoscoming">
    <strong>Who's Coming:</strong>
    <%if (Model.RSVPs.Count == 0){%>
          No one has registered.
    <% } %>
</p>

After:

<p id="whoscoming">
    <strong>Who's Coming:</strong>
    <%if (Model.IsNobodyRegistered){%>
          No one has registered.
    <% } %>
</p>

The view model for this screen ends up looking like this:

public class DinnerDetailsViewModel
{
    public string Address { get; set; }
    public string Title { get; set; }
    public string DinnerID { get; set; }
    public string EventDate { get; set; }
    public string Country { get; set; }
    public string Latitude { get; set; }
    public string Longitude { get; set; }
    public string Description { get; set; }
    public string HostedBy { get; set; }
    public string ContactPhone { get; set; }
    public bool IsAnyoneRegistered { get; set; }
    public bool IsNobodyRegistered { get; set; }
    public bool IsCurrentUserRegistered { get; set; }
    public bool IsCurrentUserHosting { get; set; }

    public List<RsvpViewModel> RSVPs { get; set; }

    public class RsvpViewModel
    {
        public string AttendeeName { get; set; }
    }
}

The really key part is the AutoMapper configuration profile.  You can group configurations with profiles.  Maybe in one profile you format dates in one way, in another profile you format dates in another way.  I'm just using one profile here.

public class ViewModelProfile : Profile
{
    protected override string ProfileName
    {
        get { return "ViewModel"; }
    }

    protected override void Configure()
    {
        AddFormatter<HtmlEncoderFormatter>();
        ForSourceType<DateTime>().AddFormatter<StandardDateFormatter>();

        CreateMap<Dinner, DinnerDetailsViewModel>()
            .ForMember(x => x.IsCurrentUserRegistered, o => o.ResolveUsing<CurrentUserRegisteredResolver>())
            .ForMember(x => x.IsCurrentUserHosting, o => o.ResolveUsing<CurrentUserHostingResolver>())
            .ForMember(x => x.EventDate, o => o.SkipFormatter<HtmlEncoderFormatter>());

        CreateMap<RSVP, DinnerDetailsViewModel.RsvpViewModel>()
            .ForMember(x => x.AttendeeName, o => o.AddFormatter<AttendeeNameFormatter>());
    }
}

Most properties of the view model are mapped conventionally.  The property names match up so AutoMapper knows exactly what do do with them.  AutoMapper will do a lot more for you if you'd like it to.  This is actually a pretty hefty configuration.  In a different scenario it'd be likely that almost everything is mapped conventionally.

Note the first AddFormatter call.  That's instructing AutoMapper to html encode everything.  I skip it for a property later.  The possibilities here are endless.  One cool thing we do in another project is wrap each property in a span that's given a conventionally named CSS class.  In automated UI tests, we can use that class to find the proper element and ensure that the screen is displaying the right thing.

image

Let me know if you have any questions.

Posted in Tools | Tagged , | 17 Comments

More On Value Objects

A few days ago Dylan Beattie wrote a nice post about value objects.  He explains the idea in a more palatable way than my attempt:

If it’s not clear how to model a particular element in your model, try asking “which one?” If the question makes sense within your own scenario then you’re probably dealing with entities. If the question “which one” is meaningless in the context of your domain then you’re probably better off modeling the subject of the question as a value object.

I suggest that if you’re maintaining a collection, you implicitly care which one.

Posted in Domain-Driven Design | Tagged , , | 1 Comment

Practical IOC slides and code

Last night I presented a talk titled Practical Inversion Of Control to a packed house at the Austin .NET User Group.  It was a blast.  I’d guess there were 80 developers there, maybe more.  Interestingly, when I asked the room “Who uses an IOC tool at work,” about 10 hands went up, at the most.

I tried to focus on the practices of using IOC tools, because there’s a lot of abstract jibber-jabber about principles.  Don’t get me wrong, I love the principles and the theory.  I just think talking about the practices creates a more powerful pedagogical vector through which a comprehension of the principles can “sneak” in.

If I do this talk again I’ll scrap the open generics tidbit.  I think it’s really neat, and that’s why I included it.  But if one hasn’t run into that pain, solving it isn’t so cool, and it adds unnecessary complexity to the demonstration.  I’ll have to come up with something better to replace it.

Here’s an archive of the slides, notes and demo code.

And here’s a thing, if you just want to browse a slightly mangled view of the slides:

Posted in Community | Tagged , | 1 Comment

There is never a collection of Value Objects

Adding to a Value Object property always adds to it, never adds another instance to it.  Distinguishing Value Objects by maintaining a collection of them implies identity.

It is a mistake to attempt to maintain a collection of Value Objects.

Let’s take the near-canonical Address, a perfectly valid Value Object as described on page 98 of the Big Blue Bible:

public class Address : ValueObject<Address>
{
    public virtual string StreetAddress1 { get; set; }
    public virtual string StreetAddress2 { get; set; }
    public virtual string City { get; set; }
    public virtual State State { get; set; }
    public virtual string ZipCode { get; set; }
    public virtual Country Country { get; set; }
}

And a perfectly valid usage of this Address Value Object is as a component of an Entity:

public class Customer : Entity
{
    public Address WorkAddress { get; set; }
    public Address HomeAddress { get; set; }
    // ...
}

This, on the other hand, is incorrect:

public class Customer : Entity
{ private readonly ISet<Address> _addresses = new HashedSet<Address>(); public Address[] GetAddresses() { return _addresses.ToArray(); } }

Again, distinguishing addresses by maintaining a collection of them implies identity. If you tried to edit one of the addresses respecting some immutable Value Object oriented thinking, you would clear the collection, find (somehow) the one you intended to edit, replace it along with all the others.  This is not possible.  When you only care about the values of an object, rather than a key, you cannot find the original one you intend to edit from an instance of an edited object.  If you care about a key you have an Entity.

The original and the edited will never match. You might try to give the Value Object a database key so that it is easy to find.  But if you do that, why again are you clearing all the rest and re-adding them?  That doesn't make sense - just edit it.

There's another problem.  In the "wallet" example you have paper money in your wallet, several pieces of paper.  Your wallet is the Entity and the money is a Value Object.  If you were to take some money out of your wallet, you would subtract from the Value Object, not remove an instance of the Value Object from a collection.  You don't care if you have five ones or one five, you just care that you have five.  Value Objects never collect, they only aggregate.

If you care about each individual instance, you have an Entity.

The best way to model something like this is to use an Entity that has a Value Object component.  If I am maintaining a collection of Addresses, I do actually care that each is different - the trick is to find out why.  In my case I care because the Customer has an address history and I wish to maintain that history.  I model that like this:

public class HistoricalAddress : Entity
{
    public Address Address { get; set; }
    public DateTime? Start { get; set; }
    public DateTime? End { get; set; }
    public AddressType Type { get; set; }
}

Now the HistoricalAddress Entity lives in the Customer Aggregate...

public class Customer : Entity
{
    private readonly ISet<HistoricalAddress> _addresses = new HashedSet<HistoricalAddress>();

    public HistoricalAddress[] GetAddresses()
    {
        return _addresses.ToArray();
    }

    public HistoricalAddress GetAddress(Guid historicalAddressId)
    {
        return _addresses.SingleOrDefault(x => x.Id == historicalAddressId);
    }

    //...
}

... and I am free to edit, list, and delete them with ease.

The one caveat is when you are maintaining a collection of Value Objects that represent all possible values.  If you have a State Value Object you may want to represent a collection of all 50 U.S. States as a select list in the user interface.  This works fine and is programmatically possible, until you are interested in maintaining this collection.

Posted in Domain-Driven Design | Tagged , , | 16 Comments

Obligatory Utility Roundup Post

I have set up a few new PCs lately in the course of getting set up on my new job.  Here is what I install:

  • Windows XP SP3 – Vista too much friction
    • Use BlackViper‘s Safe config
    • Turn off System Restore
    • Pop a shortcut to Start Menu in my SendTo folder for easy/lazy Launchy indexing)
    • Set up my folder views and apply to all folders:

image 

image

  • Windows XP continued
    • Set up Windows Classic Theme and turn off any fancy UI stuff like animations

image

  • Windows XP continued
    • Setup toolbar to locked with just the Show Desktop shortcut

image 

Posted in Tools | 5 Comments

Self-signed SSL Certs on IIS 6 part 2

Q: How do I install self-signed SSL certificates on two IIS 6 websites on the same server where both sites use port 443 and are configured with host headers?

A: Multiple SSL sites on a single IIS server using host headers.  <- the answer. 

Basically, use SelfSSL or SSLDiag to create a cert with CN=*.example.com, then just point the second site to that cert in the Directory Security tab.  Also, configure secure server bindings using adsutil (found in c:\inetpub\adminscripts).

Posted in Tools | Tagged , , , | Leave a comment