Mediator Pattern using MediatR and Unity

MediatRIn a couple previous posts I’ve discussed using Query Objects instead of Repositories and the Mediator pattern.  I find creating query objects being used with the command pattern much cleaner than polluting repositories with a ton of query methods.

The concept is nothing new as many people already use the command pattern in the context of executing commands/behavior following CQRS.   However, there is nothing wrong with using the same patterns for the query side.

I’ve been using my own home grown solution of the mediator pattern in a few different projects but had nothing really formalized.  I was thinking about creating a simple library until I stumbled upon MediatR created by Jimmy Bogard.

It is incredibly simple and only has one dependency, CommonServiceLocator.

The Github repo has a good set of docs and some examples with different dependency injection containers.

Unity RegisterType

I did notice the Unity example didn’t quiet work as described in the example.

The Mediator class takes a ServiceLocatorProvider in its constructor which was not being resolved properly by Unity.

In order to get it functioning correctly, I defined an injection factory and created the Mediator and passed in the UnityServiceLocator.

My complete Unity configuration which is also using MediatR to publish events from NEventStore:

MediatR v2.0

Although v1 has a dependency on CommonServiceLocator, it appears that v2.0 will not have any external dependencies.

MediatR

 

 

Read More

Domain Driven Design: “What” not “How”

Common LanguageMany years have past since Eric Evans release the blue book: Domain Driven Design.  A lot has changed over the years but I find the core ideas still hold very true.

In some ways, I think some of the concepts outlined are even more prevalent now than they have ever been.

Ubiquitous Language

The Ubiquitous Language is a shared language developed by the team.  The team is everyone working on the project: developers, domain experts, QA, BA.

Everyone on the team.

The ubiquitous language isn’t developed by the domain expert(s) alone.  If you have more than one domain expert, they may struggle with language between each other to define concepts.

Everyone apart of the team is building, growing and refining the language.

Language is critical to not only verbal communication but how it’s represented in the software we are writing.  It represents the concepts and terms specific to the core business domain we are trying to model.

All the expressions, nouns and verbs are what the team is formally defining with an ubiquitous language.

Bounded Context

Boundaries

One of my favorite concepts is of the bounded context.  Bounded context should be autonomous.

Meaning, a bounded context should be independent and self governing.

It defines a set of business capabilities within the domain and represents a conceptual boundary.

One way of determining where the boundaries lie is with the ubiquitous language.

If a term or phrase has a different meaning in another context, you may have discovered a boundary and therefor another bounded context.

“What”, not “How”

With the rise/hype of microservices, the concept of a bounded context continues to hold true.

How do functional languages impact domain driven design?  As I’m leaning F#, I’m not overly concerned about the “how”.

The important part modeling a domain for me is the verbs, not the state.  I do think that will translate well to a functional language.

Focusing on the what not the how is what makes Domain Driven Design still very important and applicable so many years later.

 

Read More

Clean up your Domain Model with Event Sourcing

Vacuum cleaner - Workers collectionI recently had a discussion with a developer who was new to Domain Driven Design, CQRS and Event Sourcing.  They were using Greg Young’s Simple CQRS Example to create there own simple app as learning exercise.

After taking a quick look at their aggregate root, one thing that immediately stood out to me was a class field that contained current state.  Why this is interesting is because this field was not in any invariant.

When I first started reading and exploring Event Sourcing, this was a big “ah ha!” moment for me.

The realization that only certain data within my domain model was really important.

We will use a simple shopping cart example.

First, lets look at what our shopping cart would look like without being event sourced. We would be probably persisting this to a relational database using an ORM or perhaps storing it in a NoSQL document store.

public class ShoppingCart
{
    public Guid Id { get; set; }
    public IList<ShoppingCartLineItem> LineItems { get; set; }
    public bool IsComplete { get; set; }
    public DateTime CompleteDate { get; set; }

    public ShoppingCart(Guid id)
    {
        Id = id;
        LineItems = new List<ShoppingCartLineItem>();
    }

    public void AddProduct(string productSku, int quantity)
    {
        if (string.IsNullOrEmpty(productSku)) throw new ArgumentException("productSku");
        if (quantity <= 0) throw new ArgumentException("quantity");

        LineItems.Add(new ShoppingCartLineItem(productSku, quantity));
    }

    public void Complete()
    {
        if (IsComplete) throw new InvalidOperationException("Already completed.");
        if (LineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

        IsComplete = true;
        CompleteDate = DateTime.UtcNow;
    }
}

There are a few things to point out in the above code.

Take note of the public properties which represent our current state.  These are the pieces of data that we be persisted to data storage.

Notice we have a IList<ShoppingCartLineItem> which is our collection of products that are in our shopping cart.  The ShoppingCartLineItem class contains the Product SKU and the quantity ordered.

One invariant in this example to mention is in the Complete() method.  There must be at least one product added to the shopping cart in order to mark it as complete.

if (LineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

Next, let’s implement the above with event sourcing.

public class ShoppingCart : AggregateRoot
{
    private Guid _id;
    private bool _completed;
    private DateTime _completedDate;
    private readonly IList _lineItems;
 
    public override Guid Id
    {
        get { return _id; }
    }

    private void Apply(ShoppingCartCreated e)
    {
        _id = e.Id;
    }

    private void Apply(ProductAdded e)
    {
        _lineItems.Add(new ShoppingCartLineItem(e.ProductSku, e.Quantity));
    }

    private void Apply(Completed e)
    {
        _completed = true;
        _completedDate = e.DateCompleted;
    }

    public ShoppingCart(Guid id)
    {
        _lineItems = new List();

        ApplyChange(new ShoppingCartCreated(id));
    }

    public void AddProduct(string productSku, int quantity)
    {
        if (string.IsNullOrEmpty(productSku)) throw new ArgumentException("productSku");
        if (quantity <= 0) throw new ArgumentException("quantity");

        ApplyChange(new ProductAdded(_id, productSku, quantity));
    }

    public void Complete()
    {
        if (_completed) throw new InvalidOperationException("Already completed.");
        if (_lineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

        ApplyChange(new Completed(_id, DateTime.UtcNow));
    }
}

In our event sourced implementation above we still are holding current state in the same fashion as our non event sourced version.  I’ve changed them from public properties to private fields since they are not being persisted to data storage.  Instead our events raised through ApplyChange() are what are persisted to data storage.

The example above is typical of a first implementation of event sourcing.  We are taking the concept we know and use of persisting current state along with this new idea of using events as state transitions.

There is actually a lot of code that can be removed from our event sourced example above.

ShoppingCartLineItem class is no longer needed because the data it encapsulates is now encapsulated in our ProductAdded event.  So if we delete that class, then we have the issue with:

private readonly IList<ShoppingCartLineItem> _lineItems;

This private member will no longer be valid since we just deleted the ShoppingCartLineItem class.  So we can remove this private member as well.

Now let’s go back to that invariant that we have:

if (_lineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

How can we maintain this invariant since we are no longer keep track of the line items?

You only need the data applicable to an invariant

Because of this, we don’t really care what products or quantities are on the shopping cart, just that there is at least one.

Any data that is not used by an invariant does not need to be in your aggregate.

private DateTime _completedDate;

We also no longer need the date the shopping cart was completed because it is not used by an invariant and it is also contained in the Completed event.

Now let’s take a look at our shopping cart with these ideas applied:

public class ShoppingCart : AggregateRoot
{
    private Guid _id;
    private bool _containsProducts;
    private bool _completed;

    public override Guid Id
    {
        get { return _id; }
    }

    private void Apply(ShoppingCartCreated e)
    {
        _id = e.Id;
    }

    private void Apply(ProductAdded e)
    {
        _containsProducts = true;
    }

    private void Apply(Completed e)
    {
        _completed = true;
    }

    public ShoppingCart(Guid id)
    {
        ApplyChange(new ShoppingCartCreated(id));
    }

    public void AddProduct(string productSku, int quantity)
    {
        if (string.IsNullOrEmpty(productSku)) throw new ArgumentException("productSku");
        if (quantity <= 0) throw new ArgumentException("quantity");

        ApplyChange(new ProductAdded(_id, productSku, quantity));
    }

    public void Complete()
    {
        if (_completed) throw new InvalidOperationException("Already completed.");
        if (_containsProducts == false) throw new InvalidOperationException("Cannot complete with no products.");

        ApplyChange(new Completed(_id, DateTime.UtcNow));
    }
}

The invariant is now based on a boolean set when a product has been added.  The aggregate does not care about what products were added or their quantity.  It doesn’t even need to have them in a collection.

With the implementation of event sourcing in our aggregate, we get a much clearer view of what data drives business logic and is important in our domain model.

Read More

Bounded Context and Subdomains

CarpetIn a previous blog, I discussed how I recently discovered through eventual consistency that I had poor business alignment.  With more thoughts and insights, I wanted to extend that post by discussion bounded contexts and how they fit within subdomains.

1 to 1?

I’ve often thought of a bounded context as being a one-to-one relationship with a subdomain.   To take that further, you may get the impression that they are indeed the same thing.  When I was first introduced to the concept many years ago, I was under the impression that they mapped directly one to one.

I’m not entirely sure why I had this perception early on.  It may be due examples or just the assumption I made.  I do not remember actually ever reading how a subdomain and a bounded context don’t map directly one to one.

Over the years I’ve realized this not to be the case, but always had a tough time giving an explanation that others could visualize.

I heard Eric Evans gave a great example that I will paraphrase, which should help you visualize the difference.

Living Room Floor

Imagine a room in your house.  It may have a closet or some different length walls which makes it not totally uniform.  Imagine there is carpet in this room.  The carpet covers every inch of the floor.  Wall to wall carpet.

This carpet represents your bounded context.

Underneath the carpet, say the cement, is your subdomain.

By Design

It just so happens that your bounded context is mapped to your subdomain exactly.  However, that is just because the bounded context (carpet) was designed that way.

A bounded context doesn’t necessarily need to cover the entire subdomain.  It only needs to cover the aspects of the subdomain which help solve the problem space.

To use the carpet analogy again, I mentioned that the room wasn’t completely uniform as maybe it had a closet in it.  The carpet doesn’t need to cover the entire floor beneath it.  There may be bare floor exposed in the closet because that portion of the subdomain doesn’t require to be modeled as it isn’t needed for problem you are trying to solve.

More Than One?

I’m still trying to determine if a subdomain can have more than one bounded context.  I do think it may be possible if you are implementing something technical apart of that subdomain.  I would love to hear others thoughts on this.

Read More

Eventual Consistency and Business Alignment

mapI recently discovered through eventual consistency that my bounded contexts were not properly aligned with the business.   I won’t lie, it took me quite a while to make this realization.

This was most likely the case in many situations I’ve had in the past.  Because of this realization, I wanted to let out some of my thoughts about eventual consistency and business alignment.

Dependent Bounded Context

I’ve often encounter situations where a bounded context requires information that another bounded context is responsible for.  I’d like to use a simple example I’ve heard from Udi Dahan.  In the context of an Ecommerce site.

  • A customer can be a defined as a “preferred” customer.
  • Preferred customers receive a 10% discount on all orders.

Based on the above, the “preferred” flag and any business rules associated to it, most likely exists in some sort of the CRM bounded context.  However, this detail is required in the Sales bounded context in order to apply a discount if eligible.

As you can see, there is information that needs to be shared between bounded contexts.

Publish / Subscribe Domain Events

One approach for decoupling your bounded context is to publish domain events from your domain model.  This allows other bounded contexts to subscribe to those events and handle them accordingly.

Let’s use our example above to see how this would be implemented.  In our CRM bounded context, when a customer is defined as preferred in our domain model, we would publish a CustomerIsPreferred event.

class CustomerIsPreferred
{
	public Guid CustomerId { get; private set; }
	public DateTime Date { get; private set; }
	
	public CustomerIsPreferred(Guid customerId, DateTime date)
	{
		CustomerId = customerId;
		Date = date;
	}
}

In our Sales bounded context, we would subscribe to this event and update our customer model with a preferred flag. This piece of information is used as a local cache in our Sales bounded context.

During our checkout process in Sales, we would then use the preferred flag on the concept of a customer in Sales to determine if they should receive a 10% discount.

However, remember that this preferred flag is not owned by Sales.

Because of the publish / subscribe model (assuming asynchronicity), at any given time, our preferred flag in Sales could be out of sync with current state in our CRM bounded context. Eventually consistency doesn’t mean our data is wrong, it just means it is stale.

Business Alignment

There are many situations where data being eventually consistent is totally acceptable.  I’ve found in the real world we often make decisions with stale data all the time.

However, there are times where full consistency is required.  When describing the example above to the business, does the eventual consistency of the preferred flag have true business impact?  If it truly does matter and the data must be fully consistent, then you may have bad business alignment with your bounded contexts.

Re-evaluate your bounded context and the boundaries as you may have an wrong interpretation of responsibilities.

I’ve found that drawing a context map and the events which are published and subscribed with a domain expert should flush out any of these incorrect interpretations and help you re-align boundaries and responsibilities.

Read More

My F# Journey – F# Learning Resources

F# CloudThinking about learning functional programming with F#?  Here is a list of F# learning resources that will help you on your own F# journey.

Robert C. Martin – Functional Programming: What? Why? When?

Why is functional programming becoming such a hot topic? Just what is functional programming anyway? And when am I going to have to know about it? In this talk Uncle Bob will walk you through the rationale that is driving the current push towards functional programming. He’ll also introduce you to the basics by walking through some simple Clojure code.

F# Software Foundation

http://fsharp.org/

A wealth of information.  There are some very useful walkthrus on how to use F# on various platforms (Windows, Linux, Mac).  As well, there are many guides on how to use F# for Web Programming, Mobile, Cloud, Financial, etc.

Try F#

http://www.tryfsharp.org/

There is an interactive window that allows you to write and execute F# directly in your browser.  This is nice if you want to experiement with F# without having installing F# or an IDE.

F# for fun and profit

http://fsharpforfunandprofit.com/

I found this site very approachable coming from an enterprise and line of business development background.  I found it to be an easier read than most.

Domain Driven Design, Event Sourcing and CQRS with F#

Ever since I discovered the “blue book” by Eric Evans, I’ve been immersed in Domain Driven Design, Event Sourcing, CQRS, and Messaging.  If you are familiar with these concepts than this talk by Lev Gorodinski is worth a watch.

 

ToDo-Backend

https://github.com/panesofglass/TodoBackendFSharp

When you are ready to jump into some real code take a look at the Todo MVC app written in F#.

More…

If you have any suggestions, please comment and let me know which sites/resources you have found helpful.

Read More

My F# Journey – What I’ve learned so far

fsharpThis is a first blog post in a series to document my experiences while learning functional programming. This is my F# Journey.

During my 15 year career that started in the late 90’s, I have not made very many conscious decisions about learning a specific language or technology.  The path I’ve taken and the experience I’ve gained seems like it just happened naturally.

As someone always wanting to learn, I usually find some interesting topics and start going down the rabbit hole (Domain Driven Design, CQRS, Event Sourcing… thanks Greg Young), however I never usually set out on a “I’m going to learn X” journey.

That’s about to change.

As with anyone that keeps up with the latest trends, functional programming is all the rage.  And I do believe for good reason (more on that later),  which is why I’ve decided to take on the journey of learning with F#.   I’ve chosen F# because of my .NET/C# background and feel it can help my career to keep it in the .NET ecosystem.

What I’ve learned so far…

Stop comparing it to C#

apple-vs-orange

It’s natural when looking at another imperative language that you are unfamiliar with, to compare it to the language you know best.   The concepts are all transferable.  How do I perform a loop?  How do I define a variable?  How do I assign a variable?

With a quick search and reading a few examples,  you are off to the races writing some basic code in a new imperative language.  Stop trying to compare concepts.

Let it go!

Open up your mind to new ideas and try and forget everything you know.

Think like a beginner.

Just because you can, doesn’t mean you should

Because F# is a hybrid language and supports some of the concepts of an imperative language, doesn’t mean you should use them.  In pure functional languages, there are no loops or objects.

Let it go!

Just because you can use F# in a non-functional way, doesn’t mean you should (especially while learning).

When reading intro articles, you will see the following statements over and over again: “start thinking functionally” or “start thinking differently”.  It’s hard at first to really grasp what this really means.  Once you finally let go of the imperative way of thinking, you will get an “AH HA!” moment.

Read & Play

Anytime I’ve ever learned a new language it has always been through practical use in a small app.  However, I do find that learning the basics of F#, understanding F# types, and thinking like a beginner before jumping into real code has been helpful.  I’m using Visual Studio and writing code, but more as a playground than attempting actually write an app.  Once I feel comfortable enough and actually feel like I fully “get it”, I’m going to start writing a simple app.

Read More

Query Objects with a Mediator

Mediator

In my previous blog Query Objects instead of Repositories, I demonstrated creating query objects and handlers to encapsulate and execute query logic instead of polluting a repository with both read and write methods.  Since we have moved away from repositories and are now using query objects, we will introduce the Mediator pattern. It will allows have a common interface that can be injected into our controller or various parts of our application. The mediator will delegate our query objects to the appropriate handler that will perform the query and return the results.

First we will create an interface that will be used on all of our query objects.

public interface IQuery<out TResponse> { }

Now we need to create an interface that all of our query handlers will implement.

public interface IHandleQueries<in TQuery, out TResponse>
	where TQuery : IQuery<TResponse>
{
	TResponse Handle(TQuery query);
}

Next we will create our Mediator interface. Most examples you will see that are implementing command handlers generally are showing an IFakeBus or something similar. The difference being that generally in the Bus implementation there is no return type. On the query side, our intent is to return data.

public interface IMediate
{
	TResponse Request<TResponse>(IQuery<TResponse> query);
}

There are many ways you can implement your mediator. As an example:

public class Mediator : IMediate
{
	public delegate object Creator(Mediator container);

	private readonly Dictionary<Type, Creator> _typeToCreator = new Dictionary<Type, Creator>();

	public void Register<T>(Creator creator)
	{
		_typeToCreator.Add(typeof(T), creator);
	}

	private T Create<T>()
	{
		return (T)_typeToCreator[typeof(T)](this);
	}

	public TResponse Request<TResponse>(IQuery<TResponse> query)
	{
		var handler = Create<IHandleQueries<IQuery<TResponse>, TResponse>>();
		return handler.Handle(query);
	}
 }

Now that we have our interfaces and mediator implementation, we need to modify our existing queries and handlers.

public class ProductDetailsQuery : IQuery<ProductDetailModel>
{
	public Guid ProductId { get; private set; }

	public ProductDetailsQuery(Guid productId)
	{
		ProductId = productId;
	}
}

public class ProductDetailQueryHandler : IHandleQueries<ProductDetailsQuery, ProductDetailModel>
{
	private DbContext _db;
 
	public ProductDetailQueryHandler(DbContext db)
	{
		_db = db;
	}
 
	public ProductDetailModel Handle(ProductDetailsQuery query)
	{
		var product = (from p in _db.Products where p.ProductId == query.ProductId).SingleOrDefault();
		if (product == null) {
			throw new InvalidOperationException("Product does not exist.");
		}
 
 		var relatedProducts = (from p in _db.RecommendedProducts where p.PrimaryProductId == query.ProductId);
 
 		return new ProductDetailsModel
		{
			Id = product.Id,
			Name = product.Name,
			Price = product.Price,
			PriceFormatted = product.Price.ToString("C"),
			RecommendedProducts = (from x in relatedProducts select new ProductDetailModel.RecommendedProducts {
				ProductId = x.RecommendedProductId,
				Name = x.Name,
				Price = x.Price,
				PriceFormatted = x.Price.ToString("C")
			})
		};
	}
 }

Now in our controller, instead of either creating a new instance of the query handler in our controllers or having all them injected into the constructor, we now simply inject the mediator.

public class ProductController : Controller
{
	private IMediate _mediator;
	
	public ProductController(IMediate mediator)
	{
		_mediator = mediator;
	}
	
	public ViewResult ProductDetails(ProductDetailQuery query)
	{
		var model = _mediator.Request(query);
		return View(model);
	}
}

As before, we have encapsulated the generation of our view model into its own object but now a common interface in a mediator to handle the incoming query object requests.

Read More

Query Objects instead of Repositories

QueryThe repository pattern is often used to encapsulate simple and sometimes rather complex query logic.   However, it has also been morphed into handling persistence and is often used as another layer of abstraction from your data mapping layer.   This blog post show you how to slim down and simplify your repositories or possibly eliminate them all together by using query objects.

A typical repository will look something like this:

public interface IProductRepository
{
	void Insert(Product product);
	void Delete(Product product);
	IEnumerable<Product> GetById(Guid id);
	IEnumerable<Product> GetAllActive();
	IEnumerable<Product> FindByName(string name);
	IEnumerable<Product> FindBySku(string name);
	IEnumerable<Product> Find(string keyword, int limit, int page);
	IEnumerable<Product> GetRelated(Guid id);
}

Each of the Get/Find methods implemented above would encapsulate a specific a query.  This type of repository would most likely be used to then transform the data returned from a set of methods into a View Model which would then be passed to our view or serialized and sent back to the caller (browser).  As an example of passing the model to a view in ASP.NET MVC, it would look something like this:

public ViewResult ProductDetails(Guid productId)
{
	var product = _productRepository.GetById(productId);
	var relatedProducts = _productRepository.GetRelated(productId);
	
	var model = new ProductDetailsModel
	{
		Id = product.Id,
		Name = product.Name,
		Price = product.Price,
		PriceFormatted = product.Price.ToString("C"),
		RecommendedProducts = (from x in relatedProducts select new ProductDetailModel.RecommendedProducts {
				ProductId = x.RecommendedProductId,
				Name = x.Name,
				Price = x.Price,
				PriceFormatted = x.Price.ToString("C")
			})
	};

	return View(model);
}

As I’ve mentioned before, I believe you should think of your MVC framework as an HTTP interface to your application.  Regardless if you are returning HTML or JSON, the generation of your View Model should not be coupled to your MVC framework.

Query Objects

In the example above, I want to extract the generation of my view model info a query object.  A query object is similar to a command object for processing behavior in our domain.  Our query object will now look like this:

public class ProductDetailsQuery
{
	public Guid ProductID { get; private set; }
	
	public ProductDetailQuery(Guid productId)
	{
		ProductId = productId
	}
}

In order to execute our query, we will implement in a query handler.

public class ProductDetailQueryHandler
{
	private DbContext _db;
	
	public ProductDetailQueryHandler(DbContext db)
	{
		_db = db;
	}
	
	public ProductDetailModel Handle(ProductDetailQuery query)
	{
		var product = (from p in _db.Products where p.ProductId == query.ProductId).SingleOrDefault();
		if (product == null) {
			throw new InvalidOperationException("Product does not exist.");
		}
		
		var relatedProducts = (from p in _db.RecommendedProducts where p.PrimaryProductId == query.ProductId);
		
		return new ProductDetailsModel
		{
			Id = product.Id,
			Name = product.Name,
			Price = product.Price,
			PriceFormatted = product.Price.ToString("C"),
			RecommendedProducts = (from x in relatedProducts select new ProductDetailModel.RecommendedProducts {
				ProductId = x.RecommendedProductId,
				Name = x.Name,
				Price = x.Price,
				PriceFormatted = x.Price.ToString("C")
			})
		};
	}
}

Now we have encapsulated the generation of our view model which can be used in our controller.

public ViewResult ProductDetails(ProductDetailQuery query)
{
	var model = _queryHandler(query);
	return View(model);
}

Now our controller is responsible for delegating the call to generate the model and action result or serialization.  In my next post I will take this a step further by introducing a common interface for our query handler in order to accept multiple query objects and  return types.

Read More

Throw Out Your Dependency Injection Container

Dependency Injection

Dependency injection containers (aka inversion of control containers) seem to be common in most modern applications.  There is no argument against the value dependency injection, but I do have a couple arguments against using a dependency injection container.  Like many other design patterns and practices, over time the development community seems to forget the original problem the pattern or practice was solving.

Constructor & Setter Injection

Passing your dependencies via the constructor is generally a better way of injecting dependencies instead of  setters. Constructor injection gives you a much clearer definition of what dependencies are needed in order to construct the object into a valid state.  My dependencies fields are usually readonly, to prevent them from being externally set after object creation.

Regardless if you use constructor or setter injection with your container of choice, there is often one injection method that is seemingly rarely used or mentioned.  Pass your dependency to the method that requires it.

How often have you seen a constructor take a pile of dependencies via it’s constructor, to which those dependencies were used in a limited amount of methods.  I often see this when looking at CQRS Command Handlers.

class InventoryHandler
{
	private readonly IRepository _repository;
	private readonly IBus _bus;
	private readonly IValidateInventory _validation;
	
	public InventoryHandler(IRepository repository, IBus bus, IValidateInventory validation)
	{
		_repository = repository;
		_bus = bus
		_validation = validation;
	}

	public void Handle(ReceiveInventory cmd)
	{
		if (!_validation.IsAvailable(cmd.ProductId)) {
			throw new InvalidOperationException("Cannot receive inventory");
		}

		// Receive Product into Inventory
		var inventory = _repository.GetById(cmd.ProductId);
		inventory.Receive(cmd.Quantity, cmd.UnitCost);
	}

	public Handle(RemoveInventory cmd)
	{
		// Remove product from inventory
		var inventory = _repository.GetById(cmd.ProductId);
		inventory.RemoveInventory(cmd.Quantity);

		// Pub/Sub to notify other bounded context of inventory removal
		_bus.Send(new InventoryRemovedMessage(cmd.InventoryId));
	}
}

In this simplified example, IRepository is used in both Handle() methods. However, IBus & IValidateInventory are both only used in one method each.

Instead of passing the dependencies via constructor, pass the required dependencies to the method that requires it.

class InventoryHandler
{
	private readonly IRepository _repository;
	
	public InventoryHandler(IRepository repository)
	{
		_repository = repository;
	}

	public void Handle(IValidateInventory validation, ReceiveInventory cmd)
	{
		if (!validation.IsAvailable(cmd.ProductId)) {
			throw new InvalidOperationException("Cannot receive inventory");
		}

		// Receive Product into Inventory
		var inventory = _repository.GetById(cmd.ProductId);
		inventory.Receive(cmd.Quantity, cmd.UnitCost);
	}

	public Handle(IBus bus, RemoveInventory cmd)
	{
		// Remove product from inventory
		var inventory = _repository.GetById(cmd.ProductId);
		inventory.RemoveInventory(cmd.Quantity);

		// Pub/Sub to notify other bounded context of inventory removal
		bus.Send(new InventoryRemovedMessage(cmd.InventoryId));
	}
}

 

Nested Dependencies

The primary reason why I prefer not to use a dependency injection container is because it potentially masks a code smell.  Nested dependencies or over abstraction can add complexity by adding unnecessary layers.

Have you seen something similar to this before?

public class MyService(IRepository repostiory) { ... }
public class Repository(IUnitOfWork unitOfWork) { ... }
public class UnitOfWork(IDbContext dbContext) { ... }
public class DbContext(IDbConnection dbConnection) { ... }
public class DbConnection(string connectionString) { ... }

Code SmellIf you are using a dependency injection container, you may not have noticed the excessive and unneeded abstraction layers in parts of you application.  If you had to manually wire up up these nested dependencies through all the layers, it would be really painful.

Masking the pain by using a dependency injection container is making your application more complex.

Take a look at your application and see if you can remove your dependency injection container.   If you can, then what benefits did it provide?  If you can’t, ask yourself if you really need all those layers.

Read More