The journeylism of @yreynhout

On CQRS, DDD(D), ES, …

Unit of Work and Repository

I imagine one can build a huge index of articles written about the repository pattern and the unit of work pattern. Anybody who has seen Greg’s talk at NDC 2010 (*) may have thought: “Woaw, Unit of Work must be an anti-pattern”.
It’s not. Well, at least if you know what you’re doing. The danger being hinted at lies in the fact that you could be hiding or masking multiple commands by changing multiple aggregates in one go. Technically, changing multiple aggregates is going to hurt your infinite scalability (distributed transaction et al). But more importantly your design will not be the simplest one, the most composable & re-composable one, nor the most testable one if you are going to affect multiple aggregates. Another reason, which goes one step further, might be that you got your aggregate boundaries wrong by touching on multiple aggregates. This one is very subtle and not easy to spot, especially if you are only just starting out with true DDD.
The only approved reason for a Unit of Work might be when you’re doing some kind of batch processing. Mind you that Unit of Work pattern does not prescribe a distributed transaction, so basically you could build one that writes out changes on a per aggregate basis (beyond the scope of this article).
So, knowing all these prescribed best practices would one still use a UnitOfWork? I do. Not to violate any of the above, but because it is the right abstraction for managing aggregates (**) affected by a business transaction (a.k.a. a command). But don’t take my word for it. By all means, come to your own conclusions.
All these technical things aside, as a general rule of thumb you should start out by decomposing your business transactions into ‘one command per aggregate‘.

The interaction between a repository and a unit of work.

public abstract class Aggregate { /*Omitted for brevity*/ }

// Treats a typed set of aggregates as a collection
public interface IRepository<TAggregate> where TAggregate : Aggregate {
  // Queries an aggregate by its identifier.
  bool TryGetById(Guid aggregateId, out TAggregate aggregate);
  // Start tracking an aggregate's changes
  // Note: preferred above Add because if communicates the intent better
  void Attach(TAggregate aggregate);
  // Stop tracking an aggregate's changes
  // Note: preferred above Remove because if communicates the intent better
  void Detach(TAggregate aggregate);
}

// Treats a set of aggregates as a unit of work
public interface IUnitOfWork : IDisposable {
  // Queries (what?!?) an aggregate by its identifier.
  bool TryGetById(Guid aggregateId, out Aggregate aggregate);
  // Start tracking an aggregate's changes
  void Attach(Aggregate aggregate);
  // Stop tracking an aggregate's changes
  void Detach(Aggregate aggregate);
  // Gets all the event changes since last commit
  // Note: This call is delegated to each attached aggregate.
  IEnumerable<IEvent> GetChanges();
  // Commits events/changes to the event store
  void Commit();
  // Optional: Events that communicate when a UoW is committed/committing
  event EventHandler<CommitEventArgs> Committing();
  event EventHandler<CommitEventArgs> Committed();
}

// Creates new units of work
public interface IUnitOfWorkFactory {
  // Creates a new unit of work
  IUnitOfWork Create();
}

// Makes a block of code aware of a Unit of Work (behaves much like a TransactionScope).
// REMARK: This is a very simplified version. A very brittle implementation 
// of the thread static nature of this class is shown here.
// For ideas on how to build your own, go here: http://github.com/riteshrao/ncommon/ 
public class UnitOfWorkScope : IDisposable {
  private IUnitOfWorkFactory _factory;
  public UnitOfWorkScope(IUnitOfWorkFactory factory) { _factory = factory; CurrentScope = this; }

  [ThreadStatic]
  public static UnitOfWorkScope CurrentScope { get; private set; }

  public IUnitOfWork UnitOfWork {
    get {
      if(_unitOfWork == null) _unitOfWork = _factory.Create();
      return _unitOfWork;
    }
  }

  // Commits the ambient unit of work, if any.
  void Commit() {
    if(_unitOfWork != null) _unitOfWork.Commit();
  }

  public void Dispose() { if(_unitOfWork != null) _unitOfWork.Dispose(); CurrentScope = null; }
}

// The generic repository implementation
public class Repository<TAggregate> : IRepository<TAggregate> where TAggregate : Aggregate {
  private IUnitOfWork _privateUnitOfWork;

  // Fallback onto the UoW provided by the UoWScope (production code)
  public Repository() {}

  // Inject a unit of work which is great for TDD (test code)
  public Repository(IUnitOfWork unitOfWork) {
    _privateUnitOfWork = unitOfWork;
  }

  // Select the proper UoW
  protected IUnitOfWork UnitOfWork {
    get {
      if (_privateUnitOfWork != null) return _privateUnitOfWork;
      return AmbientUnitOfWork;
    }
  }

  private IUnitOfWork AmbientUnitOfWork {
    get {
      return UnitOfWorkScope.CurrentScope.UnitOfWork;
    }
  }

  public bool TryGetById(Guid aggregateId, out TAggregate aggregate) {
    Aggregate weakAggregate;
    if (this.UnitOfWork.TryGetById(aggregateId, out weakAggregate)) { 
      aggregate = (TAggregate)weakAggregate;
      return true;
    }
    aggregate = null;
    return false;
  }

  public void Attach(TAggregate aggregate) { this.UnitOfWork.Attach(aggregate); } 
  public void Detach(TAggregate aggregate) { this.UnitOfWork.Detach(aggregate); }
}

The take-away is how the generic repository is nothing more than a typed shell around the UoW, and can interact with both an injected and ambient UoW. The injection aids the testability of a repository implementation. Because the UoW interacts with an IEventStore and encapsulates an IdentityMap, it has also gotten the responsibility of querying by aggregate identifier (i.e. query from cache, fall back to query from store).
Yet, I’m not a real fan of the generic repository approach. Especially if it goes down the path of passing in criteria objects to query. When using an event store, it’s not even an option. I prefer using explicit interfaces that are easy to fake (although that’s not a goal in and by itself), as shown below.

public interface IUserAccountRepository : IRepository<UserAccount> {
  // Additional write model queries (immediately consistent secondary indexes)
  bool TryGetByLogin(string login, out UserAccount userAccount);
  // Additional read model queries (eventual consistent secondary indexes)
  IEnumerable<UserAccount> FindDeprecatedAccounts();
}

As you can see, the repository can be extended with write/read model queries, providing a unified querying experience.

The interaction of the repository, unit of work and command handler.

What is it that you want to test of a command handler? Do you want to emulate each scenario you just tested on your aggregate? Really? Do you like writing the same (almost) tests twice? I don’t.
What’s the responsibility of a command handler, assuming we’re dealing with two-way commands? I see two responsibilities: cause an event to happen and any domain exceptions to be translated into a command error.

public class NewRealEstatePropertyCommandHandler 
  : ICommandHandler<NewRealEstatePropertyCommand> {
  private IRealEstatePropertyRepository _repositoryRealEstateProperty;
  private IOwnerRepository _repositoryOwner;

  public NewRealEstatePropertyCommandHandler(
    IOwnerRepository repositoryOwner,
    IRealEstatePropertyRepository repositoryRealEstateProperty) {
    _repositoryRealEstateProperty = repositoryRealEstateProperty;
    _repositoryOwner = repositoryOwner;
  }

  public void Handle(NewRealEstatePropertyCommand command) {
    Owner owner;
    if(!_repositoryOwner.TryGetById(command.Owner.Id, out owner)) { 
      Throw(NewRealEstatePropertyCommandError.OwnerNotFound); 
    }
    try {
      _repositoryRealEstateProperty.Attach(
        owner.NewRealEstateProperty(
          command.RealEstateProperty.Id,
          /* other props mapped from command */));
    } catch(BehaviorException<NewRealEstatePropertyError> exception) {
      exception.
         ThrowIf(
           NewRealEstatePropertyError.MaxNumberOfPropertiesExceeded,
           NewRealEstatePropertyCommandError.MaxNumberOfPropertiesExceeded).
         ThrowIf(
           NewRealEstatePropertyError.OwnerDisabledBecauseBillNotPaid,
           NewRealEstatePropertyCommandError.OwnerDisabledBecauseBillNotPaid).
         Throw();
    }
  }
}

Not exactly helpful, is it? I mean, how are you going to test each of its responsibilities without simulating all of the aggregate behavior? Let’s split things up (SRP, anyone?).

public class NewRealEstatePropertyCommandHandler 
  : ICommandHandler<NewRealEstatePropertyCommand> {
  private IRealEstatePropertyRepository _repositoryRealEstateProperty;
  private IOwnerRepository _repositoryOwner;

  public NewRealEstatePropertyCommandHandler(
    IOwnerRepository repositoryOwner,
    IRealEstatePropertyRepository repositoryRealEstateProperty) {
    _repositoryRealEstateProperty = repositoryRealEstateProperty;
    _repositoryOwner = repositoryOwner;
  }

  public void Handle(NewRealEstatePropertyCommand command) {
    Owner owner;
    if (!_repositoryOwner.TryGetById(command.Owner.Id, out owner)) { 
      Throw(NewRealEstatePropertyCommandError.OwnerNotFound); 
    }
    _repositoryRealEstateProperty.Attach(
      owner.NewRealEstateProperty(
        command.RealEstateProperty.Id,
        /* other props mapped from command */));
  }
}

public class NewRealEstatePropertyCommandExceptionHandler 
  : ICommandHandler<NewRealEstatePropertyCommand> {

  private ICommandHandler<NewRealEstatePropertyCommand> _handler;

  public NewRealEstatePropertyCommandExceptionHandler(
    ICommandHandler<NewRealEstatePropertyCommand> handler) {
    _handler = handler;
  }

  public void Handle(NewRealEstatePropertyCommand command) {
    try {
      _handler.Handle(command);
    } catch(BehaviorException<NewRealEstatePropertyError> exception) {
      exception.
         ThrowIf(
           NewRealEstatePropertyError.MaxNumberOfPropertiesExceeded,
           NewRealEstatePropertyCommandError.MaxNumberOfPropertiesExceeded).
         ThrowIf(
           NewRealEstatePropertyError.OwnerDisabledBecauseBillNotPaid,
           NewRealEstatePropertyCommandError.OwnerDisabledBecauseBillNotPaid).
         Throw();
    }
  }
}

You guessed it, it’s decoration time. From a testability point of view, one can now test the exception conversion separate from the event production. As an added bonus, going from two-way commands to one-way commands does not require changing the command handler – only the command exception handler. Let’s focus on the event production related test, i.e. testing the actual command handler.

[TestFixture]
public class Given_A_NewRealEstateProperty_Command {
  private NewRealEstatePropertyCommandHandler _handler;
  private IOwnerRepository _repositoryOwner;
  private IRealEstatePropertyRepository _repositoryRealEstateProperty;

  [SetUp]
  public void SetUp() {
    // Fake It Easy @ http://code.google.com/p/fakeiteasy/
    _repositoryOwner = A.Fake<IOwnerRepository>(); 
    _repositoryRealEstateProperty = A.Fake<IRealEstatePropertyRepository>();
    _handler = new NewRealEstatePropertyCommandHandler(
      _repositoryOwner, _repositoryRealEstateProperty);
  }

  [Test]
  public void When_X_Then_Should_Have_Emitted_NewRealEstatePropertyAddedEvent() {
    // Arrange omitted
    _handler.Handle(command);
    A.CallTo(() => 
      _repositoryRealEstateProperty.Attach(
        A<RealEstateProperty>.Matches(
          y => y.GetChanges().
                   OfType<NewRealEstatePropertyAddedEvent>().
                   Count() == 1))).MustHaveHappened();
  }
}

Right, pretty darn ugly. And for the record, are we really interested in testing the attachment to a repository? It’s just a means to an end, namely testing the event production – the fact that something happened in the system. The plot even thickens when a change is made to an existing aggregate – how is one to test that using repositories? The answer I came up with: the unit of work. The revised test code is shown below.

[TestFixture]
public class Given_A_NewRealEstateProperty_Command {
  private NewRealEstatePropertyCommandHandler _handler;
  private IOwnerRepository _repositoryOwner;
  private IRealEstatePropertyRepository _repositoryRealEstateProperty;

  [SetUp]
  public void SetUp() {
    // You can attach objects to be found in this unit of work implementation.
    _unitOfWork = new MemoryUnitOfWork();
    _repositoryOwner = new OwnerRepository(_unitOfWork); 
    _repositoryRealEstateProperty = new RealEstatePropertyRepository(_unitOfWork);
    _handler = new NewRealEstatePropertyCommandHandler(
      _repositoryOwner, _repositoryRealEstateProperty);
  }

  [Test]
  public void When_X_Then_Should_Have_Emitted_NewRealEstatePropertyAddedEvent() {
    // Arrange omitted
    _handler.Handle(command);
    _unitOfWork.GetChanges().ShouldHaveExactlyOneEvent<NewRealEstatePropertyAddedEvent>();
  }

To conclude, I hope you surf away with an understanding of the dangers of Unit of Work, but also with some of its merits if applied properly. Lots of holes left for you to fill 😉

(*): Want to watch this on Windows? Use IE (yeah, I hear you).
(**): I know, it should be singular.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: