A while ago, I was playing around with the XAF framework from Devexpress, in particular with the Domain Components technology (see here and here). I was really convinced about this technology which keeps it simple to test/mock domain objects/classes. Now here is the basic idea:
Instead of having a Domain object Customer
implemented in a concrete class Customer
, we define a Customer
with an interface ICustomer
. In many traditional DDD implementations, where a sort of anemic domain model is used, all logic on certain entities is placed in so called services. This brings a few problems with it, especially in terms of maintenance. This is explained very well in this talk from Jimmy Bogard
The solution to this problem is containing business logic in the domain models itself. This is a very good theory, but in practice we see that this is very hard to align with the modern ORMs. When it comes to hosting a WCF, NSericeStack service, we want to reuse this Domain model, but not necessarily transfer all the business logic to the client/server side. This is where my idea comes in. I wanted to create an extensible platform in which a domain model is merely a contract defining which data an entity should hold, and which functionality it exposes. The concrete implementation of these interfaces is something the developer doesn't have to deal with. Those are generated at runtime by MData internals. Now one of the main problems with this approach is that interfaces typically do not contain ‘real’ code. What I mean by this is that an interface never supplies an implementation for let’s say a method (nor any other member). So to make it possible for the developer to actually write his ‘domain logic’, I created the notion of a LogicBase<T>
, where T
is the interface it supplies the logic for. This is a zero/one to one relationship, meaning that for one given interface (domain model), there can at most be one LogicBase implementation. If no implementation was provided, the system uses the default generic LogicBase
class.
Now this blog-series will cover how I implemented the MData framework step by step, I’ll try to list the benefits and liabilities, and show some interesting use cases for this framework.
By the end of the series, we will be able to write this code:
private static void Main(string[] args)
{
using (DomainContext t = new DomainContext())
{
ICustomer customer = t.Customers.Create();
t.Customers.Add(customer);
ICustomer firstCustomerEver = t.Customers.FirstOrDefault(x => x.Id == 1);
t.SaveChanges();
}
}
public class DomainContext : MDbContext
{
public MDbSet<ICustomer> Customers { get; set; }
}
In the meanwhile, all code for MData is publicly accessible on github.