Introducing Griffin.Decoupled

I recommend that you read my other post first, since it describes the rationale behind Griffin.Decoupled. This post will only demonstrate how you use the framework.

Griffin.Decoupled allows you to execute commands and domain events within your application to reduce coupling between classes. In future versions you’ll also be able to scale out the application using different servers. And that without having to rewrite a single line of code. That’s one of the most important aspects of the framework: Start small and scale when required.

Application structure

But before we get into the actual usage I’ll like to propose an application structure that you can use in your projects. The proposed structure will aid you in creating applications with clean separation between the layers and for future scaling.

Each of the following headings represents a project in your Visual Studio solution.

Domain

This is your business layer. I usually use Domain Driven Design in this project. All of my classes in here is not depending on anything else than .NET. All classes is persistence ignorant and self validating (using methods and constructors). The domain events should also be placed in this project.

If you’re not using proper OOP classes (i.e. private setters and self validation) as in DDD you’ll probably be better off to merge this project with the Decoupled.Implementation project.

Should not be dependent on anything else but .NET.

Decoupled

Contains all command classes (not the command handlers). I do this separation since I try to follow Domain Driven Design. The commands is just one way of working with the Domain Model. Hence I want a clean separation between the domain model and the commands.

Should not be dependent on anything else but .NET.

Decoupled.Implementation

This project contains the command handlers and everything that they require to work. It might be your OR/M setup or WCF client proxies. This is put in a separate project since the command handlers have a lot of dependencies that no other project should get (or be tempted to use).

Depends on Decoupled and Domain.

Your UI

Your UI project. Can be a WCF service, a MVC3 application or any other type of app where you expose the application to a group of users.

Should be dependent on the Decoupled project only.

Well. You also need to fetch data. How you do that is up to you (for now ;)).

Summary

Why should you use that structure?

When you start you’ll most likely have everything in the same application. But if your application grow you’ll likely want to split it into several parts. For instance, if you want to move the command handling to other servers you can just create a new Windows Service application and reference the CommandHandlers & Domain projects in it (and simply remove the them and reconfigure Griffin.Decoupled in the UI project).

Commands

Let’s move forward and get some command samples.

Getting started with commands

Let’s make a very quick example. Create a new console application and install the nuget package “griffin.decoupled.container”. It will install Griffin.Decoupled and Griffin.Container. Do note that you don’t have to use my IoC container, I’ve just created an adapter for it. You can do the same for your favorite container, it’s super easy (two small interfaces).

Let’s start by configuring Griffin.Container:

private static Container ConfigureGriffinContainer()
{
	var registrar = new ContainerRegistrar(Lifetime.Scoped);
	registrar.RegisterComponents(Lifetime.Default, Assembly.GetExecutingAssembly());
	var container = registrar.Build();
	return container;
}

That piece of code is everything required. All we need to do know is to tag everything that should be registered in the container with a special attribute called [Component]. Let’s move on and configure Griffin.Decoupled:

private static void Main(string[] args)
{
	var container = ConfigureGriffinContainer();
	container.DispatchCommands();
}

Done. We can now start dispatching commands. But to be able to do that, we got to create a command first, right? What about a hello world command? A classic! ;)

public class SayHello : CommandBase
{
}

CommandBase is just a base class with generates the command id. You could implement ICommand instead if you don’t want to use it.

To invoke that command we need a handler. The separation of the execution and the context is explained in the previous article. A handler of that command could look like:

[Component]
public class SayHelloHandler : IHandleCommand<SayHello>
{
	public void Invoke(SayHello command)
	{
		Console.WriteLine("Hello");
	}
}

The [Component] attribute will make the handler get registered automatically in Griffin.Container. The only thing we are missing now is the command invocation. Let’s modify the Main() method a bit:

private static void Main(string[] args)
{
	var container = ConfigureGriffinContainer();
	container.DispatchCommands();

	// Let's say hello
	CommandDispatcher.Dispatch(new SayHello());

	Console.ReadLine();
}

You should now be able to run the example application.

This sample application can be found here.

Asynchronous commands

The IocDispatcher is pretty basic, it can only dispatch commands but nothing more.

Let’s move on to the pipeline dispatcher. I’m going to explain the pipeline in detail in another post. For now let’s just say that a pipeline allows us to have several handlers take care of the command dispatching. Each handler can also communicate with all other handlers which gives us a lot of flexibility.

The pipeline is a bit more complex and it’s important that each handler is registered in the correct order. But don’t worry. I’ve abstracted away that complexity with the builder pattern. You can make the command dispatching asynchronous by configuring the pipeline dispatcher like this:

var dispatcher = new PipelineDispatcherBuilder(errorHandler)
	.AsyncDispatching(10) // allow 10 commands to be dispatched simultaneously
	.UseGriffinContainer(container) 
	.Build(); 
CommandDispatcher.Assign(dispatcher);

That’s it.

Dealing with errors in the pipeline

Note that the constructor in the previous sample takes something called errorHandler. It’s a class which will receive all messages that the pipeline generates when something have happened. It might be that a command have successfully been dispatched, that a handler failed or that a command could not be executed successfully.

The class itself looks something like:

public class ErrorHandler : IUpstreamHandler
{
	public void HandleUpstream(IUpstreamContext context, IUpstreamMessage message)
	{
		Console.WriteLine(message);
	}
}

All messages which are currently generated by the command pipeline handlers is specified here. Just take a quick look and you’ll probably understand what you will receive in that class.

For instance if you would like to retry a command you could simply send it back downstream:

public class ErrorHandler : IUpstreamHandler
{
	public void HandleUpstream(IUpstreamContext context, IUpstreamMessage message)
	{
		var msg = message as CommandFailed;
		if (msg != null)
			context.SendDownstream(msg.Message); 
	}
}

Voila! The command will be retried. You can find the complete sample here.

Retry commands automatically

There is already a pipeline handler included in the framework which can handle command retries for you. You configure it like this:

var dispatcher = new PipelineDispatcherBuilder(errorHandler)
	.RetryCommands(3) // the new stuff
	.UseGriffinContainer(container) 
	.Build(); 
	
CommandDispatcher.Assign(dispatcher);

It will try each command three times. It it fails a third time the error handler will get a message called CommandAborted. It’s up to you to deal with that. You could for instance send an email to the support department.

full sample

Storing commands

Since we’ve separated the command request from the actual invocation we can store our command in a database to either pick it up somewhere else (instead of using a message queue) or simply to execute it at a later time.

I’ve built a RavenDB package which takes care of all configuration for you. Simply install the griffin.decoupled.ravendb.embedded nuget package and then configure the pipeline like this:

var dispatcher = new PipelineDispatcherBuilder(errorHandler)
	.RetryCommands(3) 
	.UseGriffinContainer(container)
	.UseRavenDbEmbedded()  //the new stuff
	.Build(); 

CommandDispatcher.Assign(dispatcher);

Let’s do an experiment. Remember our hello world command handler?

public class SayHelloHandler : IHandleCommand<SayHello>
{
	public void Invoke(SayHello command)
	{
		Console.WriteLine("Hello");
	}
}

Configure that project to use RavenDB. Then put a break point on the Console.WriteLine() line. Run the application. When the break point is hit simply exit the application (i.e. stop debugging) to fake a system crash. Start the application again. The command which was being run during the system crash will automatically be run again. Storing commands will make sure that no user actions is lost no matter what happens.

A complete sample can be found at github.

Summary

The command handling helps us separate the business logic from our UI projects in a neat way. The actual command processing can be made now, tomorrow or at another computer. It doesn’t really matter since the dispatcher abstracts that away as an implementation/configuration detail.

Domain events

As with the command dispatcher we have an IoC dipatcher which can be used to get started quickly. It’s configured like this:

class Program
{
	static void Main(string[] args)
	{
		var container = ConfigureGriffinContainer();
		container.DispatchEvents();

		// invoke the domain event.
		DomainEvent.Publish(new UserRegistered("Arne"));

		Console.ReadLine();
	}

	private static Container ConfigureGriffinContainer()
	{
		var registrar = new ContainerRegistrar(Lifetime.Scoped);
		registrar.RegisterComponents(Lifetime.Default, Assembly.GetExecutingAssembly());
		var container = registrar.Build();
		return container;
	}
}

The domain event is a small POCO:

public class UserRegistered : DomainEventBase
{
	public UserRegistered(string displayName)
	{
		DisplayName = displayName;
	}

	public string DisplayName { get; private set; }
}

Again, the DomainEventBase just sets the EventId property to a new Guid. Implement the IDomainEvent interface directly if you prefer to do so.

You may have as many subscribers as you like on a domain event. Here are two subscribers for the event above:

[Component]
class LockFoulWordUsers : ISubscribeOn<UserRegistered>
{
	public void Handle(UserRegistered domainEvent)
	{
		if (domainEvent.DisplayName.ToLower().Contains("badword"))
		{
			Console.WriteLine("Lock the user since he's a lying bastard.");
		}
		else
		{
			Console.WriteLine("Easy peasy, no foul words where detected during this amazingly complex scanning");
		}
	   
	}
}

[Component]
class NotifyAdminUsingMessenger : ISubscribeOn<UserRegistered>
{
	public void Handle(UserRegistered domainEvent)
	{
		Console.WriteLine("I would use MSN Messenger to deliver the about " + domainEvent.DisplayName);
	}
}

Wait on transactions

When using domain events you’ll probably want to hold domain events until any active transaction have been completed. Without doing so, the events would probably generate side effects such as sending an invitation email to an user which will not be created successfully.

using (var uow = dbContext.CreateUnitOfWork())
{
	// do something in the transaction here
	
	// will publish no matter how the transaction go
	DomainEvent.Publish(new UserRegistered("Arne"));

	uow.SaveChanges();
}

To avoid that we can configure domain event handling to wait until your transactions have been successfully completed. The following samples are for RavenDb, but it could easily have been for any other database. The only thing you have to do is to implement the IUnitOfWorkAdapter which basically allows Griffin.Decoupled to monitor all transactions that you create.

Registration:

var builder = new EventPipelineBuilder(new ErrorHandler());
var dispatcher = builder
	.WaitOnTransactions(dbContext) //do not release events if a transaction is active
	.UseGriffinContainer(container)
	.Build(); 

DomainEvent.Assign(dispatcher);

So now when we invoke the event it will just be queued until the transaction is completed:

using (var uow = dbContext.CreateUnitOfWork())
{
	// do something in the transaction here
	
	// only queued here
	DomainEvent.Publish(new UserRegistered("Arne"));

	uow.SaveChanges();
}

// will be deleted here if the transaction failed,
// or published if the transaction succedded.

That applies to all domain events on the same thread, no matter where in your code they are dispatched.

Complete sample

Customizing the dispatching

I’m going to do a full article about the architecture behind the framework and why I picked the patterns I did. But just to give you a teaser let’s see how easy it is to customize the pipeline.

You have got a new audit requirement that says that all changes in the system must be documented. That’s easy now since we have our domain events. But we need to be able to log all events in a database.

To do what we can either implement the IDomainEventDispatcher and then assign it to the DomainEvent facade. Or you could create a IDownstreamHandler and inject it in the pipeline. Let’s go with the first alternative and use the decorator pattern:

public class SaveEventsToDb : IDomainEventDispatcher
{
	IDomainEventDispatcher _inner;
	
	public SaveEventstoDb(IDomainEventDispatcher inner)
	{
		_inner = inner;
	}
	
	public void Dispatch<T>(T domainEvent) where T : class, IDomainEvent
	{
		//connect to DB
		
		// save the event
		
		// and pass it on.
		_inner.Dispatch(domainEvent);
	}

	public void Close()
	{
		_inner.Close();
	}
}

You can assign it using something like this:

DomainEvent.Assign(
	new SaveEventsToDb(
		new IocDispatcher(yourContainer)
	)
);

Easy peasy.

Summary

You can find a sample which uses both events and commands here. I’m going to write a small reference application (for taking notes) as soon as the query part of the library is done.

I’ve refactored the framework a lot of times when building it so that it should be easy to use and extend. It’s up to you to decide if I succeeded or not.

Next framework update will be all about queries. Expect a blog post about it in the near future.

All packages are available at nuget, the code is available at github.


  • HoyaBaptiste

    This is a great series of posts. I look forward to reading about queries. Thanks for sharing your thoughts and experience with the community.

  • sbarnes

    I’d like to read your other post first