Today we are working on a system that, among other things, sends notification e-mails to employees when their attention is required. Getting an employee’s e-mail address is normally pretty simple, but this organisation has are around 10,000 staff out in the field, many of whom don’t have access to a computer let alone a work e-mail account.

To counter this problem we use some simple chain-of-command rules:

  1. If the Employee has an e-mail address, send it to that.
  2. If he doesn’t have one, send it to his immediate manager. If his manager doesn’t have an e-mail address, keep backtracking up the organisation until you find someone that does.
  3. If still no email address is found, send the message to a system administrator, and they can get the word out via other channels.

The interface for this service is pretty simple. It takes an employee, and returns an email address:

/// <summary>
/// Service that can find an email address for an Employee... or the next best
/// alternative if they don't have one.
/// </summary>
public interface IEmailAddressResolver
{
   string GetEmailAddressFor(IEmployee employee);
}

So how am I going implement it? With a T-SQL stored procedure, of course.

What? That may sound like a pretty bad idea — stored procedures are notorious for leaking application + domain logic into the persistence layer, and they are practically impossible to write tests for. But here is my justification:

  • This is a database-driven legacy app, and only one bounded context has been modeled using DDD so far. The organisational hierarchy is only accessible via SQL, and modeling and mapping the legacy schema with NHibernate would take a couple of weeks at least. Therefore the simplest way to query it is via stored procedure, or stored-procedure backed services.
  • I don’t want to add an e-mail property to Employee because that is an application concern, not part of the domain model. This needs to be done in a different layer, along with usernames, passwords and UI state, and we haven’t really thought about that yet.
  • We’re getting close to the final release date for this project and we have a massive backlog of work remaining. A stored procedure is about the quickest thing I can think of to implement, and everyone in the team is well-versed in SQL.

Putting it to practice, here’s the concrete implementation we wrote. It’s called via NHibernate so at least we get caching:

// Implements IEmailAddresssResolver using a stored proc.
public class EmailAddressResolver : IEmailAddressResolver
{
    readonly ISession session;

    ...

    public string GetEmailAddressFor(IEmployee employee)
    {
        if (employee == null)
            throw new ArgumentNullException("employee");

        return this.session.GetNamedQuery("employeeEmailAddress")
            .SetParameter("employee", employee)
            .SetCacheable(true)
            .UniqueResult<string>();
    }
}

I’m not even going to show you the stored proc.

SOLID lets you write ugly code when you have to

The point of this story is that sometimes you have to write ugly code. But when you do, SOLID lets you do so in a neat decoupled manner. None of the callers of IEmailAddressResolver have any idea it’s actually just a dirty stored procedure because the implementation details are all hidden behind an intention-revealing interface. One day we can write a better implementation, swap them out in the IoC container, and no-one will be any wiser.

September 4th, 2009 | 4 Comments

This insight follows on from an earlier article where I identified that the business rule “when an employee leaves the organisation, all their assets must be returned” was part of the domain model, and not just a matter of cleaning up foreign keys in the database.

I originally implemented this rule as part of a dedicated domain service called IPersonTerminatorService. Later on, I refactored it out into a standalone IAssetReturnerService to satisfy the single-responsibility principle.

asset-returner-service

But this morning I realised something: in real life, it’s the employee himself who returns all his stuff — not some other process. By taking this responsibility away from the Employee class I’ve committed two sins: creating a fictional concept in the domain, and reducing the capabilities of the Employee (leading to an anemic data-only domain model).

Time to give this responsibility back to the employee:

employee

January 29th, 2009 | No Comments Yet

Here’s a snippet from my prototype NHibernateRepository<T> I mentioned the other day. Can you see what I’ve done wrong here?

public abstract class NHibernateRepository<T>
{
    protected ISession unitOfWork;
    protected IEntityValidator<T> validator;

    protected NHibernateRepository(ISession unitOfWork,
        IEntityValidator<T> validator)
    {
        if (unitOfWork == null)
            throw new ArgumentNullException("unitOfWork");
        if (validator == null)
            throw new ArgumentNullException("validator");

        this.validator = validator;
        this.unitOfWork = unitOfWork;
    }

    protected virtual void Validate(T item)
    {
        IEnumerable<RuleViolation> ruleViolations =
            this.validator.GetAllRuleViolations(item);

        if (ruleViolations.Count() == 0)
            return;

        string message = String.Format(
            "The {0} '{1}' could not be persisted because it failed validation.",
            typeof(T).Name, item);

        throw new RuleViolationException(message, ruleViolations);
    }

    public virtual void Save(T item)
    {
        Validate(item);
        using (ITransaction transaction = this.unitOfWork.BeginTransaction())
        {
            this.unitOfWork.SaveOrUpdate(item);
            transaction.Commit();
        }
    }

    // ...
}

See that Validate() method? It’s very clever, automatically checking entities are valid before it commits them to the database. Unfortunately, validating entities is not the responsibility of a repository. This is a big fat violation of the single responsibility principle (SRP), and should be moved to a higher-level domain service instead.

January 21st, 2009 | No Comments Yet

In the past couple of weeks, I’ve started working on a new framework for my team, for developing domain-driven, test-driven web applications with ASP.NET MVC. Actually, it’s more of a meta-framework: a pattern for application development that leans on as many community-backed, best-of-class tools like NHibernate, NUnit, Rhino.Mocks, Json.NET etc as possible.

From time to time, however, I need to write my own utility class or interface, because it’s too specialised or not available elsewhere. To promote reuse and consistency between applications, I started putting them in a shared Foo.Core project (plus Foo.Core.Tests of course), similar to SharpArch.Core. Unfortunately, it began to turn into a bit of a mess; I had DDD-specific stuff like concept base classes and repository traits mixed in alongside generic LINQ extension methods and other random .NET utility classes.

It’s quite likely that some of the more generic stuff will be used in non-DDD projects, like SharePoint components and addins for Microsoft Office. But to a non-DDD developer, Foo.Core contains a lot of mysterious and scary stuff for whom the purpose of isn’t clear. This is not going to help adoption within my team.

To solve this problem, I decided to split the project in two. I now have a Foo.DomainDrivenDesign project that so far includes:

  • Repository Traits
  • Specification bases
  • DomainException
  • IEntityValidator<T>, RuleViolation and RuleViolationException
  • ObjectWithId<T>

The project name makes it immediately obviously what all this stuff is for. The rest has been dumped in Foo.Utilities:

Hopefully in future, the Utilities project can be eliminated completely and replaced by Umbrella or Utilities.NET so we don’t have to maintain it.

January 20th, 2009 | No Comments Yet

On my quest for DDD/TDD nirvana, I’m going to start documenting moments of insight on real projects when design problems are solved, principles suddenly make sense for the first time, or pitfalls are avoided. I want to do it partly for posterity, and partly to help others who are also learning. Here’s the first one.

One of my projects at the moment is developing a simple asset management system. It’s basically just a catalog of assets (computers, devices and office furniture) with various details (specs, serial numbers, notes on wear and tear etc). Each asset may be issued to a person.

I was writing some tests for my concrete repositories (mainly in order to check the database mappings are correct), when the question arose: what should happen to a person’s assets when the person is deleted?

My first thought was simply to edit the mapping XML and change a cascade option so Asset.AssignedToPersonID would be set back to NULL. However, I realised this is more than just a foreign key issue for NHibernate — returning a person’s assets when they leave the organisation is a significant domain concern.

If I take the shortcut and leave it implemented as a cascade option:

  • It’ll work fine, but the business rule will be implicit, rather than explicitly expressed somewhere as something that happens when a person is terminated. Other developers probably won’t even notice it at all.
  • The implementation won’t be testable without hitting a live SQL instance.
  • The business rule won’t be observable in other test cases unless they hit a live SQL instance, because mock repositories will likely not factor for it.
  • If we ever move away from NHibernate, or otherwise need to recreate the database mappings, this feature could be lost, and will probably only be rediscovered after FK constraint errors arise.

That’s no good. Let’s make this business rule an official part of the domain model instead, with a fully-fledged domain service:

public interface IPersonTerminatorService
{
    void TerminatePerson(Person person);
}

public class PersonTerminatorService : IPersonTerminatorService
{
    IPersonRepository personRepository;
    IAssetRepository assetRepository;

    public PersonTerminatorService(IPersonRepository personRepository,
        IAssetRepository assetRepository)
    {
        DesignByContract.Require(personRepository != null,
            "personRepository cannot be null.");
        DesignByContract.Require(assetRepository != null,
            "assetRepository cannot be null.");

        this.personRepository = personRepository;
        this.assetRepository = assetRepository;
    }

    public void TerminatePerson(Person person)
    {
        ReturnAllAssetsIssuedToPerson(person);
        this.personRepository.Remove(person);
    }

    public void ReturnAllAssetsIssuedToPerson(Person person)
    {
        IEnumerable<Asset> assets =
            this.assetRepository.GetAssetsIssuedToPerson(person);

        foreach (Asset asset in assets)
        {
            asset.Return();
            this.assetRepository.Save(asset);
        }
    }
}

The implementation is not tested yet (and will likely be refactored later because I think it does too much stuff) but here’s what it’s going to satisfy:

[Test]
public void Terminating_a_person_returns_all_assets_issued_to_them()
{
    Asset a = new Computer() { Name = "Apple Powerbook" };
    Asset b = new Computer() { Name = "Dell Dimension" };
    Asset c = new Computer() { Name = "IBM ThinkPad" };

    Person p = new Person("Richard");

    a.IssueTo(p);
    b.IssueTo(p);
    c.IssueTo(p);

    IPersonTerminatorService terminatorService =
        ServiceLocator.Current.GetInstance<IPersonTerminatorService>();

    terminatorService.TerminatePerson(p);

    Assert.IsNull(a.IssuedTo);
    Assert.IsNull(b.IssuedTo);
    Assert.IsNull(c.IssuedTo);
}

It’s a start!

January 20th, 2009 | No Comments Yet