SOLID design principles in .NET: the Dependency Inversion Principle Part 3, DI anti-patterns

In the previous post we discussed the various techniques how to implement Dependency Injection. Now it’s time to show how NOT to do DI. Therefore we’ll look at a couple of anti-patterns in this post.

The main source in the series on Dependency Injection is based on the work of Mark Seemann and his great book on DI.

Lack of DI

The most obvious DI anti-patterns is the total absence of it where the class controls it dependencies. It is the most common anti-pattern in DI to see code like this:

public class ProductService
{
	private ProductRepository _productRepository;

	public ProductService()
	{
		_productRepository = new ProductRepository();
	}
}

Here the consumer class, i.e. ProductService, creates an instance of the ProductRepository class with the ‘new’ keyword. Thereby it directly controls the lifetime of the dependency. There’s no attempt to introduce an abstraction and the client has no way of introducing another type – implementation – for the dependency.

.NET languages, and certainly other similar platforms as well, make this extremely easy for the programmer. There is no automatic SOLID checking in Visual Studio, and why would there be such a mechanism? We want to give as much freedom to the programmer as possible, so they can pick – or even mix – C#, VB, F#, C++ etc., write in an object-oriented way or follow some other style, so there’s a high degree of control given to them within the framework. So it feels natural to new up objects as much as we like: if I need something I’ll need to go and get it. If the ProductService needs a product repository then it will need to fetch one. So even experienced programmers who know SOLID and DI inside out can fall into this trap from time to time, simply because it’s easy and programming against abstractions means more work and a higher degree of complexity.

The first step towards salvation may be to declare the private field as an abstract type and mark it as readonly:

public class ProductService
{
	private readonly IProductRepository _productRepository;

	public ProductService()
	{
		_productRepository = new ProductRepository();
	}
}

However, not much is gained here yet, as at runtime _productRepository will always be a new ProductRepository.

A common, but very wrong way of trying to resolve the dependency is by using some Factory. Factories are an extremely popular pattern and they seem to be the solution to just about anything – besides copy/paste of course. I’m half expecting Bruce Willis to save the world in Die Hard 27 by applying the static factory pattern. So no wonder people are trying to solve DI with it too. You can see from the post on factories that they come in 3 forms: abstract, static and concrete.

The “solution” with the concrete factory may look like this:

public class ProductRepositoryFactory
{
	public ProductRepository Create()
	{
		return new ProductRepository();
	}
}
public ProductService()
{
	ProductRepositoryFactory factory = new ProductRepositoryFactory();
	_productRepository = factory.Create();
}

Great, we’re now depending directly on ProductRepositoryFactory and ProductRepository is still hard-coded within the factory. So instead of just one hard dependency we now have two, well done!

What about a static factory?

public class ProductRepositoryFactory
{
	public static ProductRepository Create()
	{
		return new ProductRepository();
	}
}
public ProductService()
{
	_productRepository = ProductRepositoryFactory.Create();
}

We’ve got rid of the ‘new’, yaaay! Well, no, if you recall from the introduction using static methods still creates a hard dependency, so ProductService still depends directly on ProductRepositoryFactory and indirectly on ProductRepository.

To make matters worse the static factory can be misused to produce a sense of freedom to the client to control the type of dependency as follows:

public class ProductRepositoryFactory
{
	public static IProductRepository Create(string repositoryTypeDescription)
	{
		switch (repositoryTypeDescription)
		{
			case "default":
				return new ProductRepository();
			case "test":
				return new TestProductRepository();
			default:
				throw new NotImplementedException();
		}
	}
}
public ProductService()
{
	_productRepository = ProductRepositoryFactory.Create("default");
}

Oh, brother, this is a real mess. ProductService still depends on the ProductRespositoryFactory class, so we haven’t eliminated that. It is now indirectly dependent on the two concrete repo types returned by factory. Also, we now have magic strings flying around. If we ever introduce a third type of repository then we’ll need to revisit the factory and inform all actors that there’s a new magic string. This model is very difficult to extend. The ability to configure in code, or possibly in a config file, gives a false sense of security to the developer.

You can create a mock Product repository for a unit test scenario, extend the switch-case statement in the factory and maybe introduce a new magic string “mock” only for testing purposes. Then you can put “mock” in the Create method, recompile and run your test just for unit testing. Then you forget to put it back to “sql” or whatever and deploy the solution… Realising this you may want to overload the ProductService constructor like this:

public ProductService(string productRepoDescription)
{
	_productRepository = ProductRepositoryFactory.Create(productRepoDescription);
}

That only moves the magic string problem up the stacktrace but does nothing to solve the dependency problems outlined above.

Let’s look at an abstract factory:

public interface IProductRepositoryFactory
{
	IProductRepository Create(string repoDescription);
}

ProductRepositoryFactory can implement this interface:

public class ProductRepositoryFactory : IProductRepositoryFactory
{
	public IProductRepository Create(string repositoryTypeDescription)
	{
		switch (repositoryTypeDescription)
		{
			case "default":
				return new ProductRepository();
			case "test":
				return new TestProductRepository();
			default:
				throw new NotImplementedException();
		}
	}
}

You can use it from ProductService as follows:

private IProductRepositoryFactory _productRepositoryFactory;
private IProductRepository _productRepository;

public ProductService(string productRepoDescription)
{
	_productRepositoryFactory = new ProductRepositoryFactory();
	_productRepository = _productRepositoryFactory.Create(productRepoDescription);
}

We need to new up a ProductRepositoryFactory, so we’re back at square one. However, abstract factory is still the least harmful of the factory patterns when trying to solve DI as we can refactor this code in the following way:

private readonly IProductRepository _productRepository;

public ProductService(string productRepoDescription, IProductRepositoryFactory productRepositoryFactory)
{
	_productRepository = productRepositoryFactory.Create(productRepoDescription);
}

This is not THAT bad. We can provide any type of factory now but we still need to provide a magic string. A way of getting rid of that string would be to create specialised methods within the factory as follows:

public interface IProductRepositoryFactory
{
	IProductRepository Create(string repoDescription);
	IProductRepository CreateTestRepository();
	IProductRepository CreateSqlRepository();
	IProductRepository CreateMongoDbRepository();
}

…with ProductService using it like this:

private readonly IProductRepository _productRepository;

public ProductService(IProductRepositoryFactory productRepositoryFactory)
{
	_productRepository = productRepositoryFactory.CreateMongoDbRepository();
}

This is starting to look like proper DI. We can inject our own version of the factory and then pick the method that returns the necessary repository type. However, this is a false positive impression again. The ProductService still controls the type of repository returned by the factory. If we wanted to test the SQL repo then we have to revisit the product service – and all other services that need a repository – and select CreateSqlRepository() instead. Same goes for unit testing. You can certainly create a mock repository factory but you’ll need to make sure that the mock implementation returns mock objects for all repository types the factory returns. That breaks ISP in SOLID.

No, even in the above case the caller cannot control type of IProductRepository used within ProductRepository. You can certainly control the concrete implementation of IProductRepositoryFactory, but that’s not enough.

Conclusion: factories are great for purposes other than DI. Use one of the strategies outlined in the previous post.

Lack of DI creates tightly coupled classes where one cannot exist without the other. You cannot redistribute the ProductService class without the concrete ProductRepository so it diminishes re-usability.

Overloaded constructors

Consider the following code:

private readonly IProductRepository _productRepository;

public ProductService() : this(new ProductRepository())
{}

public ProductService(IProductRepository productRepository)
{
        _productRepository = productRepository;
}

It’s great that we have can inject an IProductRepository but what’s the default constructor doing there? It simply calls the overloaded one with a concrete implementation of the repository interface. There you are, we’ve just introduced a completely unnecessary coupling. Matters get worse if the default implementation comes from an external source such as a factory seen above:

private readonly IProductRepository _productRepository;

public ProductService() : this(new ProductRepositoryFactory().Create("sql"))
{}

public ProductService(IProductRepository productRepository)
{
	_productRepository = productRepository;
}

By now you know why factories are not suitable for solving DI so I won’t repeat myself. Even if clients always call the overloaded constructor the class still cannot exist without either the ProductRepository or the ProductRepositoryFactory class.

The solution is easy: get rid of the default constructor and force clients to provide their own implementations.

Service locator

I’ve already written a post on this available here, so I won’t repeat the whole post. In short: a Service Locator resembles a proper IoC container such as StructureMap but it introduces easily avoidable couplings between objects.

Conclusion

We’ve discussed some of the ways how not to do DI. There may certainly be more of those but these are probably the most frequent ones. The most important variant to get rid of is the lack of DI which is exacerbated by the use of factories. That’s also the easiest to spot – look for the ‘new’ keyword in conjunction with dependencies.

The use of static method and properties can also be indicators of DIP violation:

DateTime.Now.ToString();
DataAccess.SaveCustomer(customer);
ProductRepositoryFactory.Create("sql");

We’ve seen especially in the case of factories that static methods and factories only place the dependencies one step down the execution ladder. Static methods are acceptable if they don’t themselves have concrete dependencies but only use the parameters already used by the object that’s calling the static method. However, if those static methods new up other dependencies which in turn may instantiate their own dependencies then that will quickly become a tightly coupled nightmare.

View the list of posts on Architecture and Patterns here.

SOLID design principles in .NET: the Dependency Inversion Principle Part 2, DI patterns

In the previous post we went through the basics of DIP and DI. We’ll continue the discussion with the following questions: how to implement DI?

The main source in the series on Dependency Injection is based on the work of Mark Seemann and his great book on DI.

Flavours of DI

I hinted at the different forms of DI in the previous post. By far the most common form is called Constructor Injection:

public ProductService(IProductRepository productRepository)
{
	_productRepository = productRepository;
}

Constructor injection is the perfect way to ensure that the necessary dependency is always available to the class. We force the clients to supply some kind of implementation of the interface. All you need is a public constructor that accepts the dependency as a parameter. In the constructor we save the incoming concrete class for later use, i.e. assign to a private variable.

We can introduce a second level of security by introducing a guard clause:

public ProductService(IProductRepository productRepository)
{
       if (productRepository == null) throw new ArgumentNullException("ProductRepo");
	_productRepository = productRepository;
}

It is good practice to mark the private field readonly, in this case the _productRepository, as it guarantees that once the initialisation logic of the constructor has executed it cannot be modified by any other code:

private readonly IProductRepository _productRepository;

This is not required for DI to work but it protects you against mistakes such as setting the value to null someplace else in your code.

Constructor injection is a good way to document your class to the clients. The clients will see that ProductService will need an IProductRepository to perform its job. There’s no attempt to hide this fact.

When the constructor is finished then the object is guaranteed to have a valid dependency, i.e. the object is in a consistent state. The following method will not choke on a null value where _productRepository is called:

public IEnumerable<Product> GetProducts()
{
	IEnumerable<Product> productsFromDataStore = _productRepository.FindAll();	
	return productsFromDataStore;
}

We don’t need to test for null within the GetProducts method as we know it is guaranteed to be in a consistent state.

Constructor injection should be your default DI technique in case your class has a dependency and no reasonable local defaults exist. A local default is an acceptable local implementation of an abstract dependency in case none is injected by the client. We’ll talk more about this a bit later. Also, try to avoid overloaded constructors because then you’ll need to rely on those local defaults if an empty constructor is used. In addition, having just one constructor greatly simplifies the usage of automated DI containers, also called IoC containers. If you don’t know what they are, then don’t worry about them for now. They are not a prerequisite for DIP and DI and they cannot magically turn tightly coupled code into a loosely coupled one. Make sure that you first understand how to do DI without such tools.

You can read briefly about them here. In short they are ‘magic’ tools that can initialise dependencies. In the above example you can configure such a container, such as StructureMap to magically inject a MyDefaultProductRepository when it sees that an IProductRepository is needed.

The next DI type in line is called Property injection. Property injection is used when your class has a good local default for a dependency but still want to enable clients to override that default. It is also called Setter injection:

public IProductRepository ProductRepository { get; set; }

In this case you obviously cannot mark the backing field readonly.

This implementation is fragile as by default all object types are set to null so ProductRepository will also be null. You’ll need to extend the property setter as follows:

public IProductRepository ProductRepository 
{
	get
	{
		return _productRepository;
	}
	set
	{
		if (value == null) throw new ArgumentNullException("ProductRepo");
		_productRepository = value;
	}
}

We’re still not done. There’s nothing forcing the client to call this setter so the GetProducts method will throw an exception. At some point we must initialise the dependency, maybe in the constructor:

public ProductService()
{
	_productRepository = new DefaultProductRepository();
}

By now we know that initialising an object with the ‘new’ keyword increases coupling between two objects so whenever possible accept the dependency in form of an abstraction instead.

Alternatively you can take the Lazy Initialisation approach in the property getter:

public IProductRepository ProductRepository 
{
	get
	{
		if (_productRepository == null)
		{
			_productRepository = new ProductRepository();
		}
		return _productRepository;
	}
	set
	{
		if (value == null) throw new ArgumentNullException("ProductRepo");
		_productRepository = value;
	}
}

We can go even further. If you want that the client should only set the dependency once without the possibility to alter it during the object’s lifetime then the following approach can work:

public IProductRepository ProductRepository 
{
	get
	{
		if (_productRepository == null)
		{
			_productRepository = new ProductRepository();
		}
		return _productRepository;
	}
	set
	{
		if (value == null) throw new ArgumentNullException("ProductRepo");
		if (_productRepository != null) throw new InvalidOperationException("You are not allowed to set this dependency more than once.");
		_productRepository = value;
	}
}

BTW this doesn’t mean that from now on you must never again use the new keyword to initialise objects. At some point you’ll HAVE TO use it as you can’t connect the bits and pieces using abstractions only. E.g. this is invalid code:

ProductService ps = new ProductService(new IProductRepository());

No, unless you have some IoC Container in place you’ll need to go with what’s called the poor man’s dependency injection:

ProductService ps = new ProductService(new DefaultProductRepository());

Where DefaultProductRepository implements IProductRepository.

Coming back to Property injection, you can use it whenever there’s a well functioning default implementation of a dependency but you still want to let your users provide their own implementation. In other words the dependency is optional. However, this choice must be a conscious one. As there’s nothing forcing the clients to call the property setter your code shouldn’t complain if the dependency is null when it’s needed. That’s a sign saying that you need to turn to constructor injection instead. In case you don’t really need a local default then the Null Object pattern can come handy. If the local default is part of the .NET base class library then it may be an acceptable approach to use it.

As you see the last version of the property getter-setter is considerably more complex than taking the constructor injection approach. It looks easy at first, just insert a get;set; type of property but you soon notice that it’s a fragile structure.

A third way of doing DI is called method injection. It is used when we want to ensure that we can inject a different implementation every time the dependency is used:

public IEnumerable<Product> GetProducts(IProductDiscountStrategy productDiscount)
{
	IEnumerable<Product> productsFromDataStore = _productRepository.FindAll();
	foreach (Product p in productsFromDataStore)
	{
		p.AdjustPrice(productDiscount);
	}
	return productsFromDataStore;
}

Here we apply a discount strategy on each product in the iteration. The actual strategy may change a lot, it can depend on the season, the loyalty scheme, the weather, the time of the day etc. As usual you can include a guard clause:

public IEnumerable<Product> GetProducts(IProductDiscountStrategy productDiscount)
{
	if (productDiscount == null) throw new ArgumentNullException("Discount strategy");
	IEnumerable<Product> productsFromDataStore = _productRepository.FindAll();
	foreach (Product p in productsFromDataStore)
	{
		p.AdjustPrice(productDiscount);
	}
	return productsFromDataStore;
}

In this approach it’s easy to vary the concrete discount strategy every time we call the GetProducts method. If you had to inject this into the constructor then you’d need to create a new ProductService class every time you want to apply some pricing strategy. In case the method doesn’t use the injected dependency you won’t need a guard clause. This may sound strange at first; why have a dependency in the signature if it is not used in the method body? Occasionally you’re forced to implement an interface where the interface method defines the dependency – more on that in the post about the Interface Segregation Principle.

Patterns related to method injection are Factory and Strategy. Choosing the proper implementation to be injected into the GetProducts method will almost certainly depend on other inputs such as the choices the user makes on the UI. These patterns will help you solve that problem.

An example of method injection from .NET is the Contains extension method from LINQ:

bool IEnumerable<T>.Contains(T object, IEqualityComparer<T> comparer);

You can then provide your own version of the equality comparer.

The last type of DI we’ll discuss is making dependencies available through a static accessor. It is also called injection through the ambient context. It is used when implementing cross-cutting concerns.

What are cross-cutting concerns? Operations that may be performed in many unrelated classes and that are not closely related to those classes. A classic example is logging. You may want to log exceptions, performance data etc. I may want to log the time it takes the GetProducts method to return in the ProductService class. You could inject an ILogger interface to every class that needs logging but it introduces a large amount of pollution across your objects. Also, an ILogger interface attached to a constructor is not truly necessary for the dependent object to perform its real job. Logging is usually not part of the core job of services and repositories.

If you’re a web developer then you must have come across the HttpContext object at some point. It is an application of the ambient context pattern. You can always try and access that object and get hold of the current HTTP context which may or may not be available right there and then by its Current static property. You can construct your own Context object where you retrieve the current context using threads. A time provider context may look as follows:

public abstract class TimeProviderContext
{
	public static TimeProviderContext Current
	{
		get
		{
			TimeProviderContext timeProviderContext = Thread.GetData(Thread.GetNamedDataSlot("TimeProvider")) as TimeProviderContext;
			if (timeProviderContext == null)
			{
				timeProviderContext = TimeProviderContext.DefaultTimeProviderContext;
				Thread.SetData(Thread.GetNamedDataSlot("TimeProvider"), timeProviderContext);
			}
			return timeProviderContext;
		}
		set
		{
			Thread.SetData(Thread.GetNamedDataSlot("TimeProvider"), value);
		}
	}
	public static TimeProviderContext DefaultTimeProviderContext = new DotNetTimeProvider();

	public abstract DateTime GetTime { get; }
}

…where DotNetTimeProvider looks as follows:

public class DotNetTimeProvider : TimeProviderContext
{
	public override DateTime GetTime
	{
		get { return DateTime.Now; }
	}
}

The TimeProviderContext is abstract and has a static Current property to get hold of the current context. That’s the classic setup of the ambient context. Using the Thread object like that will ensure that each thread has its own context. There’s a default implementation which is the standard DateTime class from .NET. It’s important to note that the Current property must be writable so that clients can assign their own time providers by deriving from the TimeProviderContext object. This can be helpful in unit testing where ideally you want to control the time instead of waiting for some specific date. The local default makes sure that the client doesn’t get a null reference exception when calling the Current property.

For simplicity’s sake I only put a single abstract method in this class to get the date but ambient context classes can provide as many properties as you need.

You can then use this context in client classes as follows:

public DateTime TestTime()
{
	return TimeProviderContext.Current.GetTime;
}

Ambient context should be used with care. Use it only if you want to make sure that a cross-cutting concern is available anywhere throughout your application. In that case it may be futile to force objects to take on dependencies they may not need now but might do so at some point in the future:

public IProductRepository ProductRepository 
{
	get
	{
		if (_productRepository == null)
		{
			_productRepository = new ProductRepository(TimeProviderContext.Current);
		}
		return _productRepository;
	}
}

…where ProductRepository looks as follows:

public class ProductRepository : IProductRepository
{	

	public ProductRepository(TimeProviderContext timeProviderContext)
	{
		//do nothing with the time provider context right now but it may be needed later
	}

	public IEnumerable<Product> FindAll()
	{
		return new List<Product>();
	}
}

That only increases the coupling between objects and pollutes your object structure.

A disadvantage with the ambient context approach is that the consuming class carries an implicit dependency. In other words it hides from the clients that it needs a time provider in order to perform its job. If you put the TestTime() method shown above in the ProductService class then there’s no way for the client to tell just by looking at the interface that ProductService uses this dependency. Also, callers of the TestTime method will get different results depending on the actual context and it may not be transparent to them why this happens without looking at the source code.

There’s actually a technical term to describe this “openness” that Eric Evans came up with: Intention-revealing interfaces. An API should communicate what it does by its public interface alone. A class using the ambient context does exactly the opposite. Clients may know of the existence of a TimeProviderContext class but will probably not know that it is used in ProductService.

There are cross cutting concerns that only perform some task without returning an answer: logging exceptions and performance data are such cases. If you have that type of scenario then a technique called Interception is something to consider. We’ll look at interception briefly it the blog post after the next one.

Conclusion

Of the four techniques discussed your default choice should always be Constructor Injection in case there’s a dependency within your class. If the dependency varies from operation to operation then Method Injection is good candidate.

Then you can ask the question if the dependency represents a cross-cutting concern. If not and a good local default exists then you can go down the Property Injection path. Otherwise if you need some return value from the cross-cutting concern dependency and you have a good local default in case Context.Current is null then Ambient Context can help. Else if this dependency only has void methods then take a look at Interception.

When in doubt, especially if you are trying to pick a strategy between Constructor Injection and another variant then pick Constructor injection. Things can never go fatally wrong with that option.

View the list of posts on Architecture and Patterns here.

SOLID design principles in .NET: the Dependency Inversion Principle and the Dependency Injection pattern

Introduction

The Dependency Inversion Principle (DIP) helps to decouple your code by ensuring that you depend on abstractions rather than concrete implementations. Dependency Injection (DI) is an implementation of this principle. In fact DI and DIP are often used to mean the same thing. A key feature of DIP is programming to abstractions so that consuming classes can depend on those abstractions rather than low-level implementations. DI is the act of supplying all classes that a service needs rather than letting the service obtain its concrete dependencies. The term Dependency Injection may first sound like some very advanced technology but in reality there are absolutely no complex techniques behind it. As long as you understand abstractions and constructors and methods that can accept parameters you’ll understand DI as well.

Another related term is Inversion of Control, IoC. IoC is an older term than DI. Originally it meant a programming style where a framework or runtime controlled the programme flow. Sticking to this definition software that is developed with .NET uses IoC – in this case .NET is the controlling framework. You hook up to its events, lifetime management etc. You are in control of your methods and references but .NET provides the ultimate glue. Nowadays we’re so used to working with frameworks that we don’t care – we’re actually happy that we don’t need to worry about tedious infrastructure stuff. With time IoC drifted away to mean Inversion of Control Containers which are mechanisms that control dependencies. Martin Fowler was the one who came up with the term Dependency Injection to mean this particular flavour of IoC. Thus, DI is still the correct term to describe the control over dependencies although people often use IoC instead.

DIP is a large topic so it will span several posts to discuss it thoroughly. However, one important conclusion up front is the following:

The frequency of the ‘new’ keyword in your code is a rough estimate of the degree of coupling in your object structure.

A side note: in the demo I’ll concentrate on interfaces but DI works equally well with abstract classes.

The main source in the series on Dependency Injection is based on the work of Mark Seemann and his great book on DI.

What are dependencies?

Dependencies can come in different forms.

A framework dependency is your choice of the development framework, such as .NET. You as a .NET developer are probably comfortable with that dependency as it’s unlikely to change during the product’s lifetime. Most often if you need the product to run on a different framework then it will be rewritten for that platform in a different language without discarding the original product. As this dependency is very unlikely to change and it’s a very high level dependency we don’t worry about it in this context.

Third party libraries introduce a lower level dependency that may well change over time. If a class depends on an external dll then that class may be difficult to test as we need that library to be in a consistent state when testing. However, some of those dependencies may never change. E.g. if I want to communicate with the Amazon cloud in code then it’s best to download and reference the Amazon .NET SDK and use that for entire lifetime of the product. It’s unlikely that I will write my own SDK to communicate with the Amazon web services.

Databases store your data and they can come in many different forms: SQL Server, MySQL, MongoDb, RavenDb, Oracle etc. You may think that an application will never change its storage mechanism, but you’ll better be prepared and abstract it away behind a repository as we’ll see in the demo.

Some other less obvious dependencies include the File System, Emails, Web services and other networking technologies.

System resources such as the Clock to get the current time. You may think that’s unnecessary to abstract that away. After all, why would you ever write your own time provider if the System Clock is available? Think of unit testing a method that depends on time: a price discount is given between 5pm and 6pm on every Friday. How would you unit test that logic? Do you really wait until 5pm on a Friday and hope that you can make the test pass before 6pm? That’s not too clever, as your unit test can only run during that time. So there’s a valid point in abstracting away system resources as well.

Configuration in general, such as the app settings you read from the config file.

The new keyword, as hinted at in the introduction, generally points to tighter coupling and an introduction of an extra dependency. As soon as you write var o = new MyObject() in your class MyClass then MyClass will be closely dependent on MyObject(). If MyObject() changes its behaviour then you have to be prepared for changes and unexpected behaviour in MyClass as well. Using static methods is no way out as your code will depend on the object where the static method is stored, such as MyFactory.GetObject(). You haven’t newed up a MyFactory object but your code is still dependent on it.

Depending on threading-related objects such as Thread or Task can make your methods difficult to test as well. If there’s a call to Thread.Sleep then even your unit test will need to wait.

Anytime you introduce a new library reference you take on an extra dependency. If you have a 4 layers in your solution, a UI, Services, Domains and Repository then you can glue them together by referencing them in Visual Studio: UI uses Services, Services use the Repo etc. The degree of coupling is closely related to how painful it is to replace those layers with new ones. Do you have to sit for days in front of your computer trying to reconnect all the broken links or does it go relatively fast as all you need to do is inject a different implementation of an abstraction?

Getting random numbers using the Random object also introduces an extra dependency that’s hard to test. If your code depends on random numbers then you may have to run the unit test many times before you get to test all branches. Instead, you can provide a different implementation of generating random numbers where you control the outcome of this mechanism so that you can easily test your code.

I’ve provided a hint on how to abstract away built-in .NET objects in your code at the end of this post.

Demo

In the demo we’ll use a simple Product domain whose price can be adjusted using a discount strategy. The Products will be retrieved using a ProductRepository. A ProductService class will depend on ProductRepository to communicate with the underlying data store. We’ll first build the classes without DIP in mind and then we’ll refactor the code. We’ll keep all classes to a minimum without any real implementation so that we can concentrate on the issues at hand. Open Visual Studio and create a new console application. Add the following Product domain class:

public class Product
{
	public void AdjustPrice(ProductDiscount productDiscount)
	{
	}
}

…where ProductDiscount looks even more simple:

public class ProductDiscount
{
}

ProductRepository will help us communicate with the data store:

public class ProductRepository
{
	public IEnumerable<Product> FindAll()
	{
		return new List<Product>();
	}
}

We connect the above objects in the ProductService class:

public class ProductService
{
	private ProductDiscount _productDiscount;
	private ProductRepository _productRepository;

	public ProductService()
	{
		_productDiscount = new ProductDiscount();
		_productRepository = new ProductRepository();
	}

	public IEnumerable<Product> GetProducts()
	{
		IEnumerable<Product> productsFromDataStore = _productRepository.FindAll();
		foreach (Product p in productsFromDataStore)
		{
			p.AdjustPrice(_productDiscount);
		}
		return productsFromDataStore;
	}
}

A lot of code is still written like that nowadays. This is the traditional approach in programming: high level modules call low level modules and instantiate their dependencies as they need them. Here ProductService calls ProductRepository, but before it can do that it needs to new one up using the ‘new’ keyword. The client, i.e. the ProductService class must fetch the dependencies it needs in order to carry out its tasks. Two dependencies are created in the constructor with the ‘new’ keyword. This breaks the Single Responsibility Principle as the class is forced to carry out work that’s not really its concern.

The ProductService is thus tightly coupled to those two concrete classes. It is difficult to use different discount strategies: there may be different discounts at Christmas, Halloween, Easter, New Year’s Day etc. Also, there may be different strategies to retrieve the data from the data store such as using an SQL database, a MySql database, a MongoDb database, file storage, memory storage etc. Whenever those strategies change you must update the ProductService class which breaks just about every principle we’ve seen so far in this series on SOLID.

It is also difficult to test the product service in isolation. The test must make sure that the ProductDiscount and ProductRepository objects are in a valid state and perform as they are expected so that the test result does not depend on them. If the ProductService sends an email then even the unit test call must send an email in order for the test to pass. If the emailing service is not available when the test runs then your test will fail regardless of the true business logic of the method under test.

All in all it would be easier if we could provide any kind of strategy to the ProductService class without having to change its implementation. This is where abstractions and DI enters the scene.

As we can have different strategies for price discounts and data store engines we’ll need to introduce abstractions for them:

public interface IProductDiscountStrategy
{
}
public interface IProductRepository
{
	IEnumerable<Product> FindAll();
}

Have the discount and repo classes implement these interfaces:

public class ProductDiscount : IProductDiscountStrategy
{
}
public class ProductRepository : IProductRepository
{
	public IEnumerable<Product> FindAll()
	{
		return new List<Product>();
	}
}

When we program against abstractions like that then we introduce a seam into the application. It comes from seams on cloths where they can be sewn together. Think of the teeth – or whatever they are called – on LEGO building blocks. You can mix and match those building blocks pretty much as you like due to the standard seams they have. In fact LEGO applied DIP and DI pretty well in their business idea.

Let’s update the ProductService class step by step. The first step is to change the type of the private fields:

private IProductDiscountStrategy _productDiscount;
private IProductRepository _productRepository;

You’ll see that the AdjustPrice method of Product now breaks so we’ll update it too:

public void AdjustPrice(IProductDiscountStrategy productDiscount)
{
}

Now the Product class can accept any type of product discount so we’re on the right track. See that the AdjustPrice accepts a parameter of an abstract type? We’ll look at the different flavours of DI later but that’s actually an application of the pattern called method injection. We inject the dependency through a method parameter. We’ll employ constructor injection to remove the hard dependency on the ProductRepository class within ProductService:

public ProductService(IProductRepository productRepository)
{
	_productDiscount = new ProductDiscount();
	_productRepository = productRepository;
}

Here’s the final version of the ProductService class:

public class ProductService
{
	private IProductRepository _productRepository;

	public ProductService(IProductRepository productRepository)
	{
		_productRepository = productRepository;
	}

	public IEnumerable<Product> GetProducts(IProductDiscountStrategy productDiscount)
	{
		IEnumerable<Product> productsFromDataStore = _productRepository.FindAll();
		foreach (Product p in productsFromDataStore)
		{
			p.AdjustPrice(productDiscount);
		}
		return productsFromDataStore;
	}
}

Now clients of ProductService, possibly a ProductController in an MVC app, will need to provide these dependencies so that the ProductService class can concentrate on its job rather than having to new up dependencies. Obtaining the correct pricing and data store strategy should not be the responsibility of the ProductService. This relates well to the Open-Closed Principle in that you can create new pricing strategies without having to update the ProductService class.

It’s important to note that the ProductService class is now honest and transparent. It is honest about its needs and doesn’t try to hide the external objects it requires in order to fulfil its job, i.e. its dependencies are explicit. Clients using the ProductService class will know that it requires a discount strategy and a product repository. There are no hidden side effects and unexpected results.

The opposite case is a class having implicit dependencies such as the first version of the ProductService class. It’s not obvious for the caller that ProductService will use external libraries and it does not have any control whatsoever over them. In the best case if you have access to the code then you can inspect it and maybe even refactor it. The first version of ProductService tells the client that it suffices to simply create a new ProductService object and then it will be able to fetch the products. However, what do we do if the database is not present? Or if the prices are not correct due to the wrong discount strategy? Then comes the part where ProductService says ‘oh, sorry, I need database access before I can do anything, didn’t you know that…?”.

Imagine that you get a new job as a programmer. Normally all ‘dependencies’ that you need for your job are provided for you: a desk, a computer, the programming software etc. Now think how this would work without DI: you’ll have to buy a desk, get a computer within some specified price range, install the software yourself etc. That is the opposite of DI and that is how ProduceService worked before the refactoring.

A related pattern to achieve DI is the Adapter pattern. It provides a simple mechanism to abstract away dependencies that you have no control over, such as the built-in .NET classes. E.g. if your class sends emails then your default choice could be to use the built-in .NET emailing objects, such as MailMessage and SmtpClient. You cannot easily abstract away that dependency as you have no access to the source code, you cannot make it implement a custom interface, such as IEmailingService. The Adapter patter will help you solve that problem. Also, unit testing code that sends emails is cumbersome as even the test call will need to send out an email. Ideally we don’t test those external services so instead inject a mock object in place of the real one. How that is done? Start here.

View the list of posts on Architecture and Patterns here.

SOLID design principles in .NET: the Interface Segregation Principle

Introduction

The Interface Segregation Principle (ISP) states that clients should not be forced to depend on interfaces they do not use. ISP is about breaking down big fat master-interfaces to more specialised and cohesive ones that group related functionality. Imagine that your class needs some functionality from an interface but not all. If you have no direct access to that interface then all you can do is to implement the relevant bits and ignore the methods that are not relevant for your class.

The opposite is that an interface grows to allow for more functionality where there’s a chance that some methods in the interface are not related, e.g. CalculateArea() and DoTheShopping(). All implementing classes will of course need to implement all methods in the interface where the unnecessary ones may only have a throw new NotImplementedException as their method body.

For the caller this won’t be obvious:

Person.DoTheShopping();
Neighbour.DoTheShopping();

Triangle.CalculateArea();
Square.CalculateArea();

These look perfectly reasonable, right? However, if the interface they implement looks like this…:

public interface IMasterInterface
{
    void DoTheShopping();
    double CalculateArea();
}

…then the client may as well make the following method calls:

Person.CalculateArea();
Triangle.DoTheShopping();

…where the true implementations will probably throw a NotImplementedException or will have an empty body or return some default value such as 0 at best. Also, if you loop through an enumeration of IMasterInterface objects then the caller expects to be able to simply call the CalculateArea() on every object in the list adhering to the LSP principle of the previous post. Then they will see exceptions thrown or inexplicable 0’s returned where the method does not apply.

The above example is probably too extreme, nobody would do anything like that in real code I hope. However, there are more subtle differences between two ‘almost related’ objects than between a Person and a Triangle as we’ll see in the demo.

Often such master interfaces are a result of a growing domain where more and more properties and behaviour are assigned to the domain objects without giving much thought to the true hierarchy between classes. Adhering to ISP will often result in small interfaces with only 1-3 methods that concentrate on some very specific tasks. This helps you create subclasses that only implement those interfaces that are meaningful to them.

Big fat interfaces – and abstract base classes for that matter – therefore introduce unnecessary dependencies. Unnecessary dependencies in turn reduce the cohesion, flexibility and maintainability of your classes and increase the coupling between dependencies.

Demo

We’ll simulate a movie rental where movies can be rented in two formats: DVD and BluRay. The domain expert correctly recognises that these are indeed related products that both can implement the IProduct interface. Open Visual Studio, create a new Console app and add the following interface:

public interface IProduct
{
	decimal Price { get; set; }
	double Weight { get; set; }
	int Stock { get; set; }
        int AgeLimit { get; set; }
	int RunningTime { get; set; }
}

Here I take the interface approach but it’s perfectly reasonable to follow an approach based on an abstract base class instead, such as ProductBase.

The following two classes implement the interface:

public class DVD : IProduct
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
        int AgeLimit { get; set; }
	public int RunningTime { get; set; }
}
public class BluRay : IProduct
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
        int AgeLimit { get; set; }
	public int RunningTime { get; set; }
}

All is well so far, right? Now management comes along and says that they want to start selling T-Shirts with movie stars printed on them so the new product is more or less related to the main business. The programmer first thinks it’s probably just OK to implement the IProduct interface again:

public class TShirt : IProduct
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
        int AgeLimit { get; set; }
	public int RunningTime { get; set; }
}

Price, stock and weight are definitely relevant to the TShirt domain. Age limit? Not so sure… Running time? Definitely not. However, it’s still there and can be set even if it doesn’t make any sense. Also, the programmer may want to extend the TShirt class with the Size property so he adds this property to the IProduct interface. The DVD and BluRay classes will then also need to implement this property, but does it make sense to store the size of a DVD? Well, maybe it does, but it’s not the same thing as the size of a TShirt. The TShirt size may be a string, such as “XL” or an enumeration, e.g. Size.XL, but the size of a DVD is more complex. It is more likely to be a dimension with 3 values: width, length and depth. So the type of the Size property will be different. Setting the type to Object is a quick fix but it’s a horrendous crime against OOP I think.

The solution is to break up the IProduct interface into two smaller ones:

public interface IProduct
{
	decimal Price { get; set; }
	double Weight { get; set; }
	int Stock { get; set; }
}

The IProduct interface still fits the DVD and BluRay objects and it fits the new TShirt interface as well. The RunningTime property is only relevant to movie-related objects:

public interface IMovie
{
	int RunningTime { get; set; }
}

BluRay and DVD implement both interfaces:

public class BluRay : IProduct, IMovie
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
	public int RunningTime { get; set; }
}
public class DVD : IProduct, IMovie
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
	public int RunningTime { get; set; }
}

Now you can have a list of IProduct objects and call the Price property on all of them. You won’t have access to the RunningTime property which is a good thing. By default it will be 0 for all TShirt objects so you could probably get away with that in this specific scenario, but it still goes against ISP. As soon as you’re dealing with IMovie objects then the RunningTime property makes perfect sense.

A slightly different solution after breaking out the IMovie interface is that IMovie implements the IProduct interface:

public interface IMovie : IProduct
{
	int RunningTime { get; set; }
}

We can change the implementing objects as follows:

public class TShirt : IProduct
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
}
public class BluRay : IMovie
{
	public decimal Price { get; set; }
	public double Weight { get; set; }
	public int Stock { get; set; }
	public int RunningTime { get; set; }
}
public class DVD : IMovie
{
	public double Weight { get; set; }
	public int Stock { get; set; }
	public int RunningTime { get; set; }
	public decimal Price { get; set; }
}

So the DVD and BluRay classes are still of IProduct types as well because the IMovie interface implements it.

A real life example

If you’ve worked with ASP.NET then you must have come across the MembershipProvider object in the System.Web.Security namespace. It is used within .NET for built-in membership providers such as SqlMembershipProvider which provides functions to create new users, authenticate your users, lock them out, update their passwords and much more. If the built-in membership types are not suitable for your purposes then you can create your own custom membership mechanism by implementing the MembershipProvider abstraction:

public class CustomMembershipProvider : MembershipProvider

I won’t show the implemented version because it’s too long. MembershipProvider forces you to implement a whole range of methods, e.g.:

public override bool ChangePassword(string username, string oldPassword, string newPassword)
public override bool DeleteUser(string username, bool deleteAllRelatedData)
public override bool EnablePasswordRetrieval
public override int MinRequiredPasswordLength

At the time of writing this post MembershipProvider includes 27 methods and properties for you to implement. It has been criticised due to its size and the fact that if you only need half of the methods then the rest will throw the dreaded NotImplementedException. If you’re building a custom Login control then all you might be interested in is the following method:

public override bool ValidateUser(string username, string password)

At best you can provide some null objects to quietly ignore the unnecessary methods but it may be confusing to the callers that expect a reasonable result from a method.

An alternative solution in cases where you don’t own the code is to follow the Adapter pattern to hide the unnecessary parts in the original abstraction.

View the list of posts on Architecture and Patterns here.

SOLID design principles in .NET: the Open-Closed Principle

Introduction

In the previous post we talked about the letter ‘S’ in SOLID, i.e. the Single Responsibility Principle. Now it’s time to move to the letter ‘O’ which stands for the Open-Closed Principle (OCP). OCP states that classes should be open for extension and closed for modification. You should be able to add new features and extend a class without changing its internal behaviour. You can always add new behaviour to a class in the future. At the same time you should not have to recompile your application just to make room for new things. The main goal of the principle is to avoid breaking changes in an existing class as it can introduce bugs and errors in other parts of your application.

How is this even possible? The key to success is identifying the areas in your domain that are likely to change and programming to abstractions. Separate out behaviour into abstractions: interfaces and abstract classes. There’s then no limit to the variety of implementations that the dependent class can accept.

Demo

In the demo we’ll first write some code that calculates prices and does not follow OCP. We’ll then refactor that code to a better design. The demo project is very similar to the e-commerce one in the previous post and partially builds upon it so make sure to check it out as well.

Open Visual Studio and create a new console application. Insert a new folder called Model. The following three basic domain objects are the same as in the previous demo:

public class OrderItem
{
	public string Identifier { get; set; }
	public int Quantity { get; set; }
}
public enum PaymentMethod
{
	CreditCard
	, Cheque
}
public class PaymentDetails
{
	public PaymentMethod PaymentMethod { get; set; }
	public string CreditCardNumber { get; set; }
	public DateTime ExpiryDate { get; set; }
	public string CardholderName { get; set; }
}

ShoppingCart looks a bit different. It now includes a price calculation function depending on the Identifier property:

public class ShoppingCart
{
	private readonly List<OrderItem> _orderItems;

	public ShoppingCart()
	{
		_orderItems = new List<OrderItem>();
	}

	public IEnumerable<OrderItem> OrderItems
	{
		get { return _orderItems; }
	}

	public string CustomerEmail { get; set; }

	public void Add(OrderItem orderItem)
	{
		_orderItems.Add(orderItem);
	}

	public decimal TotalAmount()
	{
		decimal total = 0m;
		foreach (OrderItem orderItem in OrderItems)
		{
			if (orderItem.Identifier.StartsWith("Each"))
			{
				total += orderItem.Quantity * 4m;
			}
			else if (orderItem.Identifier.StartsWith("Weight"))
			{
				total += orderItem.Quantity * 3m / 1000; //1 kilogram
			}
			else if (orderItem.Identifier.StartsWith("Spec"))
			{
				total += orderItem.Quantity * .3m;
				int setsOfFour = orderItem.Quantity / 4;
				total -= setsOfFour * .15m; //discount on groups of 4 items
			}
		}
		return total;
	}
}

The TotalAmount function counts the total price in the cart. You can imagine that shops use many different strategies to calculate prices:

  • Price per unit
  • Price per unit of weight, such as price per kilogram
  • Special discount prices: buy 3, get 1 for free
  • Price depending on the Customer’s loyalty: loyal customers get 10% off

And there are many other strategies out there. Some of these are represented in the TotalAmount function by magic strings retrieved from the Identifier of the product. The decimals ‘5m’ etc. are the dollar prices. So here every product has the same price for simplicity.

Such pricing rules are probably changing a lot in a real word business. Meaning that programmer will need to revisit this if-else statement quite often to extend it with new rules and modify the existing ones. That type of code gets quickly out of hand. Imagine 100 else-if statements with possibly nested ifs with more complex rules. If it’s Christmas AND you are a loyal customer AND you have a special coupon then the final price may depend on each of these conditions. Debugging and maintaining that code would soon become a nightmare. It would be a lot better if this particular method didn’t have to be modified at all. In other words we’d like to apply OCP so that we don’t need to extend this particular code every time there’s a change in the pricing rules.

Extending the if-else statements can introduce bugs and the application must be re-tested. We’ll need to test the ShoppingCart whereas we’re only interested in testing the pricing rule(s). Also, the pricing logic is tightly coupled with the ShoppingCart domain. Therefore if we change the pricing logic in the ShoppingCart object we’ll need to test all other objects that depend on ShoppingCart even if they absolutely have nothing to do with pricing rules. A more intelligent solution is to separate out the pricing logic to different classes and hide them behind an abstraction that ShoppingCart can refer to. The result is that you’ll have a higher number of classes but they are typically small and concentrate on some very specific functionality. This idea refers back to the Single Responsibility Principle of the previous post.

There are other advantages to creating new classes: they can be tested in isolation, there’s no other class that’s dependent on them – at least to begin with-, and as they are NEW classes in your code they have no legacy coupling to make them hard to design or test.

There are at least two design patterns that can come to the rescue: the Strategy Pattern and the Template Pattern. We’ll solve our particular problem using the strategy pattern. If you don’t know what it is about then make sure to check out the link I’ve provided, I won’t introduce the pattern from scratch here.

Let’s first introduce an abstraction for a pricing strategy:

public interface IPriceStrategy
{
	bool IsMatch(OrderItem item);
	decimal CalculatePrice(OrderItem item);
}

The purpose of the IsMatch method will be to determine which concrete strategy to pick based on the OrderItem. This could be performed by a factory as well but it would probably make the solution more complex than necessary.

Let’s translate the if-else statements into concrete pricing strategies. We’ll start with the price per unit strategy:

public class PricePerUnitStrategy : IPriceStrategy
{
	public bool IsMatch(OrderItem item)
	{
		return item.Identifier.StartsWith("Each");
	}

	public decimal CalculatePrice(OrderItem item)
	{
		return item.Quantity * 4m;
	}
}

We still base the strategy selection strategy on the product identifier. This may be good or bad, but that’s a separate discussion. The main point is that the strategy selection and price calculation logic is encapsulated within this separate class. We’ll do something similar to the other strategies:

public class PricePerKilogramStrategy : IPriceStrategy
{
	public bool IsMatch(OrderItem item)
	{
		return item.Identifier.StartsWith("Weight");
	}

	public decimal CalculatePrice(OrderItem item)
	{
		return item.Quantity * 3m / 1000;
	}
}
public class SpecialPriceStrategy : IPriceStrategy
{
	public bool IsMatch(OrderItem item)
	{
		return item.Identifier.StartsWith("Spec");
	}

	public decimal CalculatePrice(OrderItem item)
	{
		decimal total = 0m;
		total += item.Quantity * .3m;
		int setsOfFour = item.Quantity / 4;
		total -= setsOfFour * .15m;
		return total;
	}
}

The next step is to introduce a calculator that will calculate the correct price. We’ll hide the calculator behind an interface to follow good programming practices:

public interface IPriceCalculator
{
	decimal CalculatePrice(OrderItem item);
}

That’s quite minimalistic but it will suffice. Often good OOP software will have many small classes and interfaces that concentrate on very specific tasks.

The implementation will select the correct strategy and calculate the price:

public class DefaultPriceCalculator : IPriceCalculator
{
	private readonly List<IPriceStrategy> _pricingRules;

	public DefaultPriceCalculator()
        {
            _pricingRules = new List<IPriceStrategy>();
            _pricingRules.Add(new PricePerKilogramStrategy());
            _pricingRules.Add(new PricePerUnitStrategy());
            _pricingRules.Add(new SpecialPriceStrategy());
        }

	public decimal CalculatePrice(OrderItem item)
	{
		return _pricingRules.First(r => r.IsMatch(item)).CalculatePrice(item);
	}
}

We store the list of possible strategies in the constructor. In the CalculatePrice method we select the suitable pricing strategy based on LINQ and the IsMatch implementations and we call its CalculatePrice method.

Now we’re ready to simplify the ShoppingCart object:

public class ShoppingCart
{
	private readonly List<OrderItem> _orderItems;
        private readonly IPriceCalculator _priceCalculator;

        public ShoppingCart(IPriceCalculator priceCalculator)
        {
            _priceCalculator = priceCalculator;
            _orderItems = new List<OrderItem>();
        }

        public IEnumerable<OrderItem> OrderItems
        {
            get { return _orderItems; }
        }

        public string CustomerEmail { get; set; }

        public void Add(OrderItem orderItem)
        {
            _orderItems.Add(orderItem);
        }

        public decimal TotalAmount()
        {
            decimal total = 0m;
            foreach (OrderItem orderItem in OrderItems)
            {
                total += _priceCalculator.CalculatePrice(orderItem);
            }
            return total;
        }
}

All the consumer of the ShoppingCart class needs to do is to specify a concrete IPriceCalculator object, such as the DefaultPriceCalculator one and let it calculate the price based on the items in the shopping cart. The ShoppingCart is no longer responsible for the actual price calculation. That has been factored out to abstractions and smaller classes that are easy to test and carry out very specific tasks.

What if the domain owner comes along and tell you that there’s a new pricing rule? Now instead of having to go through the if-else statements you can simply create a new pricing strategy:

public class BuyThreeGetOneFree : IPriceStrategy
{
	public bool IsMatch(OrderItem item)
	{
		return item.Identifier.StartsWith("Buy3OneFree");
	}

	public decimal CalculatePrice(OrderItem item)
	{
		decimal total = 0m;
		total += item.Quantity * 1m;
		int setsOfThree = item.Quantity / 3;
		total -= setsOfThree * 1m;
		return total;
	}
}

Add this new concrete class to the DefaultPriceCalculator class constructor and it will be found by the LINQ statement.

Alternative solution for the calculator

Based on the message by Frederik in the comments section here comes another, refactored solution of the price calculator:

public class DefaultPriceCalculator : IPriceCalculator
{
    private readonly IEnumerable<IPriceStrategy> _priceStrategies;

    public DefaultPriceCalculator(IEnumerable<IPriceStrategy> priceStrategies)
    {
        _priceStrategies = priceStrategies;
    }

    public decimal CalculatePrice(OrderItem item)
    {
        return _priceStrategies.First(r => r.IsMatch(item)).CalculatePrice(item);
    }
}

Conclusion

Now you may think that you’ll need to introduce abstractions everywhere in your code for every little task. That’s not entirely correct. If you have a domain whose functionality changes a lot then you can apply OCP right away. Otherwise you may be better off not to introduce abstractions at first because they also make your code somewhat more complex. This may be the case with brand new domains in your application where you just don’t have enough experience and the domain expert cannot help you either. In such a case start off with the simplest possible design, even if it involves an if statement with a magic string. It may even be acceptable to later introduce an else statement with another magic string to accommodate a change in the logic. However, as soon as you see that you have to change and/or extend that particular functionality then factor it out to an abstraction. The following motto applies here:

“Fool me once, shame on you;fool me twice, shame on me.”

OCP doesn’t come for free. Implementing OCP will cost you some hours of refactoring and will add complexity to your design. Also, keep in mind that there’s probably no design that guarantees that you won’t have to change it at some point. The key is to identify those areas in your domain that are volatile and likely to change over time.

View the list of posts on Architecture and Patterns here.

SOLID design principles in .NET: the Single Responsibility Principle

The SOLID design principles are a collection of best practices for object oriented software design. The abbreviation comes from the first letter of each of the following 5 constituents:

  • Single responsibility principle (SRP)
  • Open-Closed principle (OCP)
  • Liskov substitution principle (LSP)
  • Interface segregation principle (ISP)
  • Dependency inversion principle (DIP)

Each of these terms are meant to make your code base easier to understand and maintain. They also ensure that your code does not become a mess with a large degree of interdependency that nobody wants to debug and extend. Of course you can write functioning software without adhering to these guidelines but they are a good investment in the future development of your product especially as far as maintainability and extensibility are concerned. Also, by following these points your code will become more object oriented instead of employing a more procedural style of coding with a lot of magic strings and enumerations and other primitives.

However, the principles do not replace the need for maintaining and refactoring your code so that it doesn’t get stale. They are a good set of tools to make your future work with your code easier. We will look at each of these in this series.

You can view these principles as guidelines. You should write code with these guidelines in mind and should aim to get as far as possible to reach each of them. You won’t always succeed of course, but even a bit of SOLID is more than the total lack of it.

SRP introduction

The Single Responsibility Principle states that every object should only have one reason to change and a single focus of responsibility. In other words every object should perform one thing only. You can apply this idea at different levels of your software: a method should only carry out one action; a domain object should only represent one domain within your business; the presentation layer should only be responsible for presenting your data; etc. This principle aims to achieve the following goals:

  • Short and concise objects: avoid the problem of a monolithic class design that is the software equivalent of a Swiss army knife
  • Testability: if a method carries out multiple tasks then it’s difficult to write a test for it
  • Readability: reading short and concise code is certainly easier than finding your way through some spaghetti code
  • Easier maintenance

A responsibility of a class usually represents a feature or a domain in your application. If you assign many responsibilities to a class or bloat your domain object then there’s a greater chance that you’ll need to change that class later. These responsibilities will be coupled together in the class making each individual responsibility more difficult to change without introducing errors in another. We can also call a responsibility a “reason to change”.

SRP is strongly related to what is called Separation of Concerns (SoC). SoC means dissecting a piece of software into distinct features that encapsulate unique behaviour and data that can be used by other classes. Here the term ‘concern’ represents a feature or behaviour of a class. Separating a programme into small and discrete ‘ingredients’ significantly increases code reuse, maintenance and testability.

Other related terms include the following:

  • Cohesion: how strongly related and focused the various responsibilities of a module are
  • Coupling: the degree to which each programme module relies on each one of the other modules

In a good software design we are striving for a high level of cohesion and a low level of coupling. A high level of coupling, also called tight coupling, usually means a lot of concrete dependency among the various elements of your software. This leads to a situation where changing the design of one class leads to the need of changing other classes that are dependent on the class you’ve just changed. Also, with tight coupling changing the design of one class can introduce errors in the dependent classes.

One last related technique is Test Driven Design or Test Driven Development (TDD). If you apply the test first approach of TDD and write your tests carefully then it will help you fulfil SRP, or at least it is a good way to ensure that you’re not too far from SRP. If you don’t know what TDD is then you can read about it here.

Demo

In the demo we’ll simulate an e-commerce application. We’ll first deliberately introduce a bloated Order object with a lot of responsibilities. We’ll then refactor the code to get closer to SRP.

Open Visual Studio and create a new console application. Insert a new folder called Model and insert a couple of basic models into it:

public class OrderItem
{
	public string Identifier { get; set; }
	public int Quantity { get; set; }
}
public class ShoppingCart
{
	public decimal TotalAmount { get; set; }
	public IEnumerable<OrderItem> Items { get; set; }
	public string CustomerEmail { get; set; }
}
public enum PaymentMethod
{
	CreditCard
	, Cheque
}
public class PaymentDetails
{
	public PaymentMethod PaymentMethod { get; set; }
	public string CreditCardNumber { get; set; }
	public DateTime ExpiryDate { get; set; }
	public string CardholderName { get; set; }
}

This is all pretty simple up this point I believe. Now comes the most important domain object, Order, which has quite many areas of responsibility:

public class Order
{
	public void Checkout(ShoppingCart shoppingCart, PaymentDetails paymentDetails, bool notifyCustomer)
	{
		if (paymentDetails.PaymentMethod == PaymentMethod.CreditCard)
		{
			ChargeCard(paymentDetails, shoppingCart);
		}

		ReserveInventory(shoppingCart);

		if (notifyCustomer)
		{
			NotifyCustomer(shoppingCart);
		}
	}

	public void NotifyCustomer(ShoppingCart cart)
	{
		string customerEmail = cart.CustomerEmail;
		if (!String.IsNullOrEmpty(customerEmail))
		{
			try
			{
				//construct the email message and send it, implementation ignored
			}
			catch (Exception ex)
			{
				//log the emailing error, implementation ignored
			}
		}
	}

	public void ReserveInventory(ShoppingCart cart)
	{
		foreach (OrderItem item in cart.Items)
		{
			try
			{
				InventoryService inventoryService = new InventoryService();
				inventoryService.Reserve(item.Identifier, item.Quantity);

			}
			catch (InsufficientInventoryException ex)
			{
				throw new OrderException("Insufficient inventory for item " + item.Sku, ex);
			}
			catch (Exception ex)
			{
				throw new OrderException("Problem reserving inventory", ex);
			}
		}
	}

	public void ChargeCard(PaymentDetails paymentDetails, ShoppingCart cart)
	{
		PaymentService paymentService = new PaymentService();

		try
		{
			paymentService.Credentials = "Credentials";
			paymentService.CardNumber = paymentDetails.CreditCardNumber;
			paymentService.ExpiryDate = paymentDetails.ExpiryDate;
			paymentService.NameOnCard = paymentDetails.CardholderName;
			paymentService.AmountToCharge = cart.TotalAmount;

			paymentService.Charge();
		}
		catch (AccountBalanceMismatchException ex)
		{
			throw new OrderException("The card gateway rejected the card based on the address provided.", ex);
		}
		catch (Exception ex)
		{
			throw new OrderException("There was a problem with your card.", ex);
		}

	}
}

public class OrderException : Exception
{
	public OrderException(string message, Exception innerException)
		: base(message, innerException)
	{
	}
}

The Order class won’t compile yet, so add a new folder called Services with the following objects representing the Inventory and Payment services:

public class InventoryService
{
	public void Reserve(string identifier, int quantity)
	{
		throw new InsufficientInventoryException();
	}
}

public class InsufficientInventoryException : Exception
{
}
public class PaymentService
{
	public string CardNumber { get; set; }
	public string Credentials { get; set; }
	public DateTime ExpiryDate { get; set; }
	public string NameOnCard { get; set; }
	public decimal AmountToCharge { get; set; }
	public void Charge()
	{
		throw new AccountBalanceMismatchException();
	}
}

public class AccountBalanceMismatchException : Exception
{
}

These are two very simple services with no real implementation that only throw exceptions.

Looking at the Order class we see that it performs a lot of stuff: checking out after the customer has placed an order, sending emails, logging exceptions, charging the credit card etc. Probably the most important method here is Checkout which calls upon the other methods in the class.

What is the problem with this design? After all it works well, customers can place orders, they get notified etc.

I think first and foremost the greatest flaw is a conceptual one actually. What has the Order domain object got to do with sending emails? What does it have to do with checking the inventory, logging exceptions or charging the credit card? These are all concepts that simply do not belong in an Order domain.

Imagine that the Order object can be used by different platforms: an e-commerce website with credit card payments or a physical shop where you pick your own goods from the shelf and pay by cash. Which leads to several other issues as well:

  • Cheque payments don’t need card processing: cards are only charged in the Checkout method if the customer is paying by card – in any other case we should not involve the idea of card processing at all
  • Inventory reservations should be carried out by a separate service in case we’re buying in a physical shop
  • The customer will probably only need an email notification if they use the web platform of the business – otherwise the customer won’t even provide an email address. After all, why would you want to be notified by email if you buy the goods in person in a shop?

The problem here is that no matter what platform consumes the Order object it will need to know about the concepts of inventory management, credit card processing and emails. So any change in these concepts will affect not only the Order object but all others that depend on it.

Let’s refactor to a better design. The key is to regroup the responsibilities of the Checkout method into smaller units. Add a new folder called SRP to the project so that you’ll have access to the objects before and after the refactoring.

We know that we can process several types of Order: an online order, a cash order, a cheque order and possibly other types of Order that we haven’t thought of. This calls for an abstract Order object:

public abstract class Order
{
	private readonly ShoppingCart _shoppingCart;

	public Order(ShoppingCart shoppingCart)
	{
		_shoppingCart = shoppingCart;
	}

        public ShoppingCart ShoppingCart
	{
		get
		{
			return _shoppingCart;
		}
	}

	public virtual void Checkout()
	{
		//add common functionality to all Checkout operations
	}
}

We’ll separate out the responsibilities of the original Checkout method into interfaces:

public interface IReservationService
{
	void ReserveInventory(IEnumerable<OrderItem> items);
}
public interface IPaymentService
{
	void ProcessCreditCard(PaymentDetails paymentDetails, decimal moneyAmount);
}
public interface INotificationService
{
	void NotifyCustomerOrderCreated(ShoppingCart cart);
}

So we separated out the inventory management, customer notification and payment services into their respective interfaces. We can now create some concrete Order objects. The simplest case is when you go to a shop, place your goods into a real shopping cart and pay at the cashier. There’s no credit card process and no email notification. Also, the inventory has probably been reduced when the goods were placed on the shelf, there’s no need to reduce the inventory further when the actual purchase happens:

class CashOrder : Order
{
	public CashOrder(ShoppingCart shoppingCart)
		: base(shoppingCart)
	{ }
}

That’s all for the cash order which represents an immediate purchase in a shop where the customer pays by cash. You can of course pay by credit card in a shop so let’s create another order type:

public class CreditCardOrder : Order
{
	private readonly PaymentDetails _paymentDetails;
	private readonly IPaymentService _paymentService;

	public CreditCardOrder(ShoppingCart shoppingCart
		, PaymentDetails paymentDetails, IPaymentService paymentService) : base(shoppingCart)
	{
		_paymentDetails = paymentDetails;
		_paymentService = paymentService;
	}

	public override void Checkout()
	{
		_paymentService.ProcessCreditCard(_paymentDetails, ShoppingCart.TotalAmount);
		base.Checkout();
	}
}

The credit card payment must be processed hence we’ll need a Payment service to take care of that. We call upon its ProcessCreditCard method in the overridden Checkout method. Here the consumer platform can provide some concrete implementation of the IPaymentService interface, it doesn’t matter to the Order object.

Lastly we can have an online order with inventory management, payment service and email notifications:

public class OnlineOrder : Order
{
	private readonly INotificationService _notificationService;
	private readonly PaymentDetails _paymentDetails;
	private readonly IPaymentService _paymentService;
	private readonly IReservationService _reservationService;

	public OnlineOrder(ShoppingCart shoppingCart,
		PaymentDetails paymentDetails, INotificationService notificationService
		, IPaymentService paymentService, IReservationService reservationService)
		: base(shoppingCart)
	{
		_paymentDetails = paymentDetails;
		_paymentService = paymentService;
		_reservationService = reservationService;
		_notificationService = notificationService;
	}

	public override void Checkout()
	{
		_paymentService.ProcessCreditCard(_paymentDetails, ShoppingCart.TotalAmount);
		_reservationService.ReserveInventory(ShoppingCart.Items);
		_notificationService.NotifyCustomerOrderCreated(ShoppingCart);
		base.Checkout();
	}
}

The consumer application will provide concrete implementations for the notification, inventory management and payment services. The OnlineOrder object will not care what those implementations look like and will not be affected at all if you make a change in those implementations or send in a different concrete implementation. As you can see these are the responsibilities that are likely to change over time. However, the Order object and its concrete implementations won’t care any more.

Furthermore, a web platform will only concern itself with online orders now and not with point-of-sale ones such as CreditOrder and CashOrder. The platform that a cashier uses in the shop will probably use CashOrder and CreditOrder objects depending on the payment method of the customer. The web and point-of-sale platforms will no longer be affected by changes made to the inventory management, email notification and payment processing logic.

Also, note that we separated out the responsibilities into individual smaller interfaces and not a single large one with all responsibilities. This follows the letter ‘I’ in solid, the Interface Segregation Principle, that we’ll look at in a future post.

We are done with the refactoring, at least as far as SRP is concerned. We can still take up other areas of improvement such as making the Order domain object cleaner by creating application services that will take care of the Checkout process. It may not be correct to put all these services in a single domain object, but it depends on the philosophy you follow in your domain design. That leads us to discussions on DDD (Domain Driven Design) which is not the scope of this post.

View the list of posts on Architecture and Patterns here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

ARCHIVED: Bite-size insight on Cyber Security for the not too technical.