Bootstrap Your App! : Domain

So the first topic I would like to talk about is bootstrapping your app, that is, getting a base set up for building a decent enterprise application with a domain driven design, data-access layer abstraction, dependency injection and a nice, clean API to interact with your domain logic.

I will be using Microsoft's .Net for my examples but I think that the concepts should translate pretty well across technologies.

The aim of this series is to get a new project off the ground and ready for work quickly while having a solid base to work from. We'll start by creating a Domain project. Some people might prefer to name this section 'Core' or something similar, whatever you prefer to name it should be fine but it will be the central portion of the application, the middle of the onion, and will not reference any other projects from your app except, perhaps, a 'Common' library with utility code.

Entity Bases

The first step in creating our new domain is to add a base entity interface to work with our repository and to enforce identity on our entities:

    public interface IEntity<TIdentifier>
    {
         TIdentifier Id { get; set; }
    }

I am using a particularly flexible approach here as we can then choose to use any type as our identifier for entities. This flexibility can allow for different types of identifiers to be used for entities which come from disparate source systems, for example we could load entities from a relational database that have integer identifiers and we could load entities in the same domain with guid identifiers, from a web-service or flat file perhaps. This approach abstracts the concept of entity identity away from concrete ideas like database primary keys.

The interface here is implemented below in the Entity base class:

    public abstract class EntityBase<TIdentifier> : IEntity<TIdentifier>
    {
        public TIdentifier Id { get; set; }

        public EntityBase()
        {
            this.Id = default(TIdentifier);
        }
    }

and specialized here:

    public abstract class GuidIdentifiedEntity : EntityBase<Guid>
    {
        public GuidIdentifiedEntity()
        {
            this.Id = Guid.NewGuid();
        }
    }

You can create as many specialized entity bases as you like to make things a bit easier in the domain. In the case of guids the base class can manage assigning new identities internally.

A Note on DDD Principles

I am using entity base interface for the repository for the sake of simplicity and the ability to plug this system onto an existing data structure which was not necessarily designed with DDD in mind and does not have proper aggregate roots. If you are designing from scratch it might be a good idea to use a marker interface which inherits from IEntity called IAggregateRoot

Inversion of Control

Next we'll probably want to setup our IOC container. My preference is to use Castle Windsor as it's very mature, reliable and flexible. The easiest way of adding the latest version of Windsor to a .Net app is to add it via Nuget package manager.

You'll want to bootstrap your IOC container in the core of your app to allow you to register anything you will need to run the core and we will then pass the container back up to the calling code to allow it to register any dependencies it might have.

With the current version of Windsor, we can initialize a container like this:

    public static class Bootstrapper
    {
        public static IWindsorContainer BootstrapContainer()
        {
            return new WindsorContainer()
               .Install(FromAssembly.This()
               );
        } 
    }

Our core bootstrapper is one of the few places we will allow a static class and method as there needs to be an entry point into the app. As we initialize our container we make a call to Install which takes a set of classes implemented IWindsorInstaller and installs the dependencies registered in them. Windsor provides a useful helper class in the form of FromAssembly which in turn has several methods for finding installers. The code above will install any installers in the assembly in which the bootstrapper is located.

When first starting to build our app we probably won't have much to register in the domain and we can therefore stick to a pretty simple installer:

    public class DomainInstaller : IWindsorInstaller
     {
          public void Install(IWindsorContainer container, 
                           IConfigurationStore store)
          {
             container.Register(
                 Classes.FromThisAssembly().Pick()
                     .WithService.DefaultInterfaces()
            );
          }
     }

This code will register all interfaces and their implementers by convention and while it is very useful you really should read the documentation regarding dependency registration (you can read about Windsor's system here).

IRepository and ISpecification

Now that we have our bases for entities in place we can look at getting the basics in place for persisting and retrieving data. I like to use the repository pattern in conjunction with the specification pattern as it's flexible and it provides a nice abstraction of your data-access layer.

Our repository interface will look like this:

    public interface IRepository<TEntity, TIdentifier>;
    {
         TEntity Get(TIdentifier id);

         TEntity Find(ISpecification<TEntity> specification);

         IEnumerable<TEntity> GetAll();

         IEnumerable<TEntity> FindAll(ISpecification<TEntity> specification);

         TEntity Save(TEntity entity);

         void Delete(TIdentifier id);

         void Delete(TEntity entity);
     }

And our specification interface:

public interface ISpecification<T>  
    {
        Expression<Func<T, bool>> Predicate { get; }

        ISpecification<T> And(ISpecification<T> specification);

        ISpecification<T> And(Expression<Func<T, bool>> predicate);

        ISpecification<T> Or(ISpecification<T> specification);

        ISpecification<T> Or(Expression<Func<T, bool>> predicate);

        T SatisfyingItemFrom(IQueryable<T> query);

        IQueryable<T> SatisfyingItemsFrom(IQueryable<T> query);

    }

This will be fleshed out with an implementation of the specification using predicates here but you can do it any way you prefer:

public class Specification<T> : ISpecification<T>  
    {
        public Expression<Func<T, bool>> Predicate { get; protected set; }

        public Specification()
        {
            this.Predicate = T => true;
        }

        public Specification(Expression<Func<T, bool>> predicate)
        {
            Predicate = predicate;
        }

        public ISpecification<T> And(ISpecification<T> specification)
        {
            return new Specification<T>(this.Predicate.And(specification.Predicate));
        }

        public ISpecification<T> And(Expression<Func<T, bool>> predicate)
        {
            return new Specification<T>(this.Predicate.And(predicate));
        }

        public ISpecification<T> Or(ISpecification<T> specification)
        {
            return new Specification<T>(this.Predicate.Or(specification.Predicate));
        }

        public ISpecification<T> Or(Expression<Func<T, bool>> predicate)
        {
            return new Specification<T>(this.Predicate.Or(predicate));
        }

        public T SatisfyingItemFrom(IQueryable<T> query)
        {
            return query.Where(Predicate).SingleOrDefault();
        }

        public IQueryable<T> SatisfyingItemsFrom(IQueryable<T> query)
        {
            return query.Where(Predicate);
        }
    }

To use this implementation of specifications using predicates with the nice And/Or functionality you will need some code from Colin Meek's blog.

Specifications provide a nice way to abstract the ways we search for data in our repository in a re-usable manner while still being able to use the base repo. Creating specific repositories to implement searching logic should be rare.

This should form a solid foundation for the domain of your app and provide a good base to work from going forward. Please let me know what I've forgotten or any additional things you like to include in your domain in the comments below.

Check back or subscribe for the next post in this series where I'll cover creating a basic data-access layer.