Relations Put Into Context

Introduction

Since the creation of the object oriented paradigm we have been drawing class diagrams that reflect what we think is the true model that represents the domain we are developing the application for. Relations are a very important component of those diagrams and there are three types of them:

  1. Association (Line with optional arrows on one/both sides).
  2. Aggregation (Empty diamond shape).
  3. Composition (Filled diamond shape).
    NOTE: inheritance is also a relation but an obvious one (i think so) with an understood and clear meaning so it won’t be discussed here.

Back in college our teacher asked us about the difference between the three types and even though i did a research about that and used them around i really didn’t feel that i have fully understood and comprehended the real difference until i have put those types in context.

It Is All About Context

So what is the context that opened up my mind, it was DDD (Domain-Driven-Design). When i was reading the chapter about Aggregates it all felt right. Aggregates are a group of objects that are managed by a another object that belongs to the aggregate itself and is called the Aggregate Root. Aggregate roots are responsible for making sure that the objects they control (in the aggregate) are always in a consistent state (they enforce invariants) and when we get rid of the root (make it ready for garbage collection) the whole aggregate it manages must go along with it.

NOTE: the definitions i present above aren’t the ones presented by Eric Evans in his book (Domain-Driven Design: Tackling Complexity at the Heart of Software), they are my personal way of thinking about those concepts.

What does that have to do with relations ?

Now we know that Association relationships are normal relations in the sense that they don’t introduce any lifetime or ownership behavior so going along with my aggregate context that means they should be preferably used  to denote relations between objects in different aggregates. On the other hand Composition presents a whole-part, ownership, lifetime management relationship where an object composed of other objects owns those objects and in that sense it also controls there life time, now in connection with my context i see this clearly fits the type of relation an Aggregate Root must have with other objects in his aggregate as he should be the one creating and destroying those objects.

So What About Aggregation !

Aggregation may seem related to aggregates and aggregate roots from the sound of it but it has nothing to do with them. so what is it there for ?. To tell you the truth my context didn’t help a lot with this one so i had to dig a little bit. Technically aggregation is whole-part relationship with no lifetime management semantics.  Another technical difference is that Aggregation doesn’t allow loops, meaning that you can’t relate a class to it self via an aggregation, you have to use an Association for that (e.g. A Person object is related to one or more Person objects, that is represented with an association from the class to it self on the diagram).

Ok i am still confused, so what !, ok the mind opener on Aggregations for me happened when i came across this quote from Martin Fowler’s Book: UML Distilled

In the pre-UML days, people were usually rather vague on what was aggregation and what was association. Whether vague or not, they were always inconsistent with everyone else. As a result, many modelers think that aggregation is important, although for different reasons. So the UML included aggregation but with hardly any semantics. As Jim Rumbaugh says, “Think of it as a modeling placebo” [Rumbaugh, UML Reference].

 

So for me i rarely use Aggregation as i am very much happy to “Think of it as a modeling placebo”.

Summary

  • I use associations for relations between objects in different aggregates.
  • I use composition for relations between an aggregate root and objects in the aggregate that it roots.
  • I don’t like to use Aggregations as they don’t provide any real semantics for me and they confuse things.

Sniffer
[Thursday, February 28, 2013] [03:01]

Yet Another UoW, Repository Article

This is my first ever blog post. for this post i have chosen something that i read about too much and still find questions and exclamation points. with that being said and so we don’t waist too much valuable time, let’s dig in.

If you are reading this then you have probably heard about the UoW and Repository patterns. What i will try to do in this post is provide you with my view point on how to implement those pattersn in WPF desktop applications, with Entity Framework Code First as our data access layer.

First of all, i am assuming that you prefer to use an IoC container in your applications, plus you already know about UoW, Repository, a bit of DDD and EF Code First and that you structure your solutions the way DDD proposes like this:Image[IMAGE TAKEN FROM http://archfirst.org/books/layered-architecture]

NOTE: I put my data access layer in the infrastructure layer and i make depend on the Domain Model, that way you can switch out the entire DAL with no problem.

ok, so we know that EF Code First was developed to help DDD developers focus on their domain model and forgot about their DAL, and to support this behavior EF Code First (EFCF from here one) provides us with the DbContext base class which resembles a typical UoW  because it provides the basic functionality a real UoW implementation my provide, and that is Change Tracking plus the ability to commit our changes. EFCF also provides us with a basic Repository implementation via the DbSet class. now that’s all well and good, but i prefer to hide the technology i am using in the DAL behind ABSTRACTIONS, this helps in testing and in case you decide to switch to a different platform or replace you DAL with NHibernate for example, you could do that without touching the other layers.

Before i show you how i chose to do that i need to mention a couple of concerns:

  • DbContexts implement the IDisposable interface and they tend to consume up resources, especially memory if they stay alive for a long period of time.
  • Repositories should don’t preferably commit changes when they make them, for example if a repository has a method called AddEntity, that method shouldn’t call DbContext.SaveChanges() after it adds the entity to the DbSet, that should be the job of the code in the application layer which does it via the UoW.
  • I assume that you will register the repositories as “Transient“, and you will register the “IUoW_Manager” (coming ahead) as a “Singleton” with your favorite IoC container.
  • Based on my previous assumption, i guess you will have the “IUoW_Manager” and Repository implementations injected into those objects which need them by our beloved IoC.

ok, off to some code (the following code goes in the Domain Layer):


public interface IUoW {

void Commit();
void BeginTransaction();
void EndTransaction();

}

public interface ICustomerRepositry {

void AddCustomer(Customer customer);

}

public interface IUoW_Manager {

IUoW GetUnitOfWork();

void DisposeUnitOfWork();
}

I think the IUoW and ICustomerRepository interfaces are obvious so i won’t explain them. you might wonder why the IUoW_Manager is there and i will leave this question until we see how i have implemented those classes in the DAL (you might notice that this is an application of the Separated Interface pattern), well let’s see how i have done that:


internal class MyDbContext : DbContext, IUoW {
// implemntation obvious, for Transaction handling you can use the TransactionScope class.
}

public class CustomerRepositry : ICustomerRepositry {

private MyDbContext _context;

public CustomerRepository(IUoW_Manager manager) {
if (factory == null)
throw new ArgumentNullException("manager");
_uow = (MyDbContext) manager.GetUnitOfWork();
}

public void AddCustomer(Customer customer) {
_context.Customers.Add(customer);
}
}

internal class UoW_ManagerImpl : IUoW_Manager {

private bool _exceptionCaught = false;
private MyDbContext _context;
private readonly Object _lock = new Object();

public IUoW GetUnitOfWork() {
lock (_lock) {
try {
if (_context == null)
_context = new DbContext();
return _context;
} catch (Exception ex) {
_exceptionCaught = true;
throw new Exception("Coudln't create unit of work", ex); // you might want to customize this exception based on your needs
}
finally {
if (_exceptionCaught) {
DisposeUnitOfWork();
_exceptionCaught = false;
}
}
}
}

public void DisposeUnitOfWork() {
lock (_lock) {
_context.Dispose();
_context = null;
}
}

}

// in the client code
var uow = _uowFactory.GetUnitOfWork();
_customerRepository.AddCustomer(new Customer());
_anotherRepository.RemoveEntity(entity);
.
.
.
uow.Commit();
_uowFactory.DipsoseUnitOfWork();

CODE EXPLANATION

First you see that the IUoW interface is implemented in the DAL by our concrete context, easy stuff so let’s move on.
As you can see, each repository implementation is injected with an IUoW_Manager which is registered with the IoC container as a singleton. This way when we have an application layer function that is trying to use different repositories, all of those repositories will have to call IUoW_Manager.GetUnitOfWork(), that way they will all receive the same IUoW instance. another thing, you might notice is that the repositories cast the IUoW interface to our concrete DbContext implementation and i think that is OK because those repositories will be tightly coupled to the DbContext anyway. these are concrete implementations and they will be replaced completely if we switched to a different ORM framework.

I think it is now obvious why i have chosen to use the IUoW_Manager, that way i can guarantee that all of the repositories involved in a single operation or functionality will receive the same IUoW instance and at the same time the manager will enable us to get rid (Dispose) of the IUoW implenetation (the context) once we have finished using it so it won’t live for a long time.

Well i am tired of writing, i hope you aren’t tired as well :).

Just one last thing, i haven’t used this code in any production project yet, but i am going to use it in my next application, and for that i decided to share it with the rest of you so i can know before hand of any problems, or issues that you might think is present with this sample code.

Thank you so much for reading.

Sniffer

First Published: Wednesday, February 20, 2013 [02:38]

Modified: Wednesday, February 26, 2013 [01:12]
(Corrected various spelling mistakes and improved the implementation).

Modified: Friday, March 16, 2013 [01:23]
(The sample is now thread safe and handles exceptions that might get thrown when creating a new DbContext implementation).

Follow

Get every new post delivered to your Inbox.