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 Liskov Substitution Principle

Introduction

After visiting the letters ‘S‘ and ‘O‘ in SOLID it’s time to discuss what ‘L’ has to offer. L stands for the Liskov Substitution Principle (LSP) and states that you should be able to use any derived class in place of a parent class and have it behave in the same manner without modification. It ensures that a derived class does not affect the behaviour of the parent class, i.e. that a derived class must be substitutable for its base class.

The principle is named after Barbara Liskov who first described the problem in 1988.

More specifically substitutability means that a caller that communicates with an abstraction, i.e. a base class or an interface, should not be aware of and should not be concerned with the different concrete types of those abstractions. The client should be able to call BaseClass.DoSomething() and get a perfectly usable answer regardless of what the concrete class is in place of BaseClass. For this to work the derived class must also “behave well”, meaning:

  • They must not remove any base class behaviour
  • They must not violate base class invariants, i.e. the rules and constraints of a class, in order to preserve its integrity

The first point means the following: if a base class defines two abstract methods then a derived class must give meaningful implementations of both. If a derived class implements a method with ‘throw new NotImplementedException’ then it means that the derived class is not fully substitutable for its base class. It is a sign that the base class is ‘NOT-REALLY-A’ base class type. In that case you’ll probably need to reconsider your class hierarchy.

All who study OOP must at some point come across the ‘IS-A’ relationship between a base class and a derived class: a Dog is an Animal, a Clerk is an Employee which is a Person, a Car is a vehicle etc. LSP refines this relationship with ‘IS-SUBSTITUTABLE-FOR’, meaning that an object is substitutable with another object in all situations without running into exceptions and unexpected behaviour.

Demo

As usual in this series on SOLID we’ll start with some code which violates LSP. We’ll then see why it’s bad and then correct it. The demo is loosely connected to the one we worked on in the SRP and OCP posts: an e-commerce application that can refund your money in case you send back the item(s) you purchased. At this company you can pay using different services such as PayPal. Consequently the refund will happen through the same service as well.

Open Visual Studio and create a new console application. We’ll start off with an enumeration of the payment services:

public enum PaymentServiceType
{
	PayPal = 1
	, WorldPay = 2
}

It would be great to explore the true web services these companies have to offer to the public but the following mockup APIs will suffice:

public class PayPalWebService
	{
		public string GetTransactionToken(string username, string password)
		{
			return "Hello from PayPal";
		}

		public string MakeRefund(decimal amount, string transactionId, string token)
		{
			return "Auth";
		}
	}
public class WorldPayWebService
	{
		public string MakeRefund(decimal amount, string transactionId, string username,
			string password, string productId)
		{
			return "Success";
		}
	}

We concentrate on the Refund logic which the two services carry out slightly differently. What’s common is that the MakeRefund methods return a string that describes the result of the action.

We’ll eventually need a refund service that interacts with these API’s somehow but it will need some object that represents the payments. As the payments can go through the two services mentioned above, and possible others in the future, we’ll need an abstraction for them. An abstract base class seems appropriate:

public abstract class PaymentBase
	{
		public abstract string Refund(decimal amount, string transactionId);
	}

We can now create the concrete classes for the PayPal and WorldPay payments:

public class PayPalPayment : PaymentBase
	{
		public string AccountName { get; set; }
		public string Password { get; set; }

		public override string Refund(decimal amount, string transactionId)
		{
			PayPalWebService payPalWebService = new PayPalWebService();
			string token = payPalWebService.GetTransactionToken(AccountName, Password);
			string response = payPalWebService.MakeRefund(amount, transactionId, token);
			return response;
		}
	}
public class WorldPayPayment : PaymentBase
	{
		public string AccountName { get; set; }
		public string Password { get; set; }
		public string ProductId { get; set; }

		public override string Refund(decimal amount, string transactionId)
		{
			WorldPayWebService worldPayWebService = new WorldPayWebService();
			string response = worldPayWebService.MakeRefund(amount, transactionId, AccountName, Password, ProductId);
			return response;
		}
	}

Each concrete Payment class will communicate with the appropriate payment service to log on and request a refund. This follows the Adapter pattern in that we’re wrapping the real API:s in our own classes. We’ll need to be able to identify the correct payment type. In the previous post we used a variable called IsMatch in each concrete type – here we’ll take the Factory approach just to see another way of selecting a concrete class:

public class PaymentFactory
	{
		public static PaymentBase GetPaymentService(PaymentServiceType serviceType)
		{
			switch (serviceType)
			{
				case PaymentServiceType.PayPal:
					return new PayPalPayment();
				case PaymentServiceType.WorldPay:
					return new WorldPayPayment();
				default:
					throw new NotImplementedException("No such service.");
			}
		}
	}

The factory selects the correct implementation using the incoming enumeration. Read the blog post on the Factory pattern if you’re not sure what’s happening here.

We’re ready for the actual refund service which connects the above ingredients:

public class RefundService
{
	public bool Refund(PaymentServiceType paymentServiceType, decimal amount, string transactionId)
	{
		bool refundSuccess = false;
		PaymentBase payment = PaymentFactory.GetPaymentService(paymentServiceType);
		if ((payment as PayPalPayment) != null)
		{
			((PayPalPayment)payment).AccountName = "Andras";
			((PayPalPayment)payment).Password = "Passw0rd";
		}
		else if ((payment as WorldPayPayment) != null)
		{
			((WorldPayPayment)payment).AccountName = "Andras";
			((WorldPayPayment)payment).Password = "Passw0rd";
			((WorldPayPayment)payment).ProductId = "ABC";
		}

		string serviceResponse = payment.Refund(amount, transactionId);

		if (serviceResponse.Contains("Auth") || serviceResponse.Contains("Success"))
		{
			refundSuccess = true;
		}

		return refundSuccess;
	}
}

We get the payment type using the factory. We then immediately need to check its type in order to be able to assign values to the the different properties in it. There are multiple problems with the current implementation:

  • We cannot simply take the payment object returned by the factory, we need to check its type – therefore we cannot substitute the subtype for its base type, hence we break LSP. Such if-else statements where you branch your logic based on some object’s type are telling signs of LSP violation
  • We need to extend the if-else statements as soon as a new provider is implemented, which also violates the Open-Closed Principle
  • We need to extend the serviceResponse.Contains bit as well if a new payment provider returns a different response, such as “OK”
  • The client, i.e. the RefundService object needs to intimately know about the different types of payment providers and their internal setup which greatly increases coupling
  • The client needs to know how to interpret the string responses from the services and that is not the correct approach – the individual services should be the only ones that can do that

The goal is to be able to take the payment object returned by the factory and call its Refund method without worrying about its exact type.

First of all let’s introduce a constructor in each Payment class that force the clients to provide all the necessary parameters:

public class PayPalPayment : PaymentBase
	{
		public PayPalPayment(string accountName, string password)
		{
			AccountName = accountName;
			Password = password;
		}

		public string AccountName { get; set; }
		public string Password { get; set; }

		public override string Refund(decimal amount, string transactionId)
		{
			PayPalWebService payPalWebService = new PayPalWebService();
			string token = payPalWebService.GetTransactionToken(AccountName, Password);
			string response = payPalWebService.MakeRefund(amount, transactionId, token);
			return response;
		}
	}
public class WorldPayPayment : PaymentBase
	{
		public WorldPayPayment(string accountId, string password, string productId)
		{
			AccountName = accountId;
			Password = password;
			ProductId = productId;
		}

		public string AccountName { get; set; }
		public string Password { get; set; }
		public string ProductId { get; set; }

		public override string Refund(decimal amount, string transactionId)
		{
			WorldPayWebService worldPayWebService = new WorldPayWebService();
			string response = worldPayWebService.MakeRefund(amount, transactionId, AccountName, Password, ProductId);
			return response;
		}
	}

We need to update the factory accordingly:

public class PaymentFactory
	{
		public static PaymentBase GetPaymentService(PaymentServiceType serviceType)
		{
			switch (serviceType)
			{
				case PaymentServiceType.PayPal:
					return new PayPalPayment("Andras", "Passw0rd");
				case PaymentServiceType.WorldPay:
					return new WorldPayPayment("Andras", "Passw0rd", "ABC");
				default:
					throw new NotImplementedException("No such service.");
			}
		}
	}

The input parameters are hard-coded to keep things simple. In reality these can be read from a configuration file or sent in as parameters to the GetPaymentService method. We can now improve the RefundService class as follows:

public class RefundService
{
	public bool Refund(PaymentServiceType paymentServiceType, decimal amount, string transactionId)
	{
		bool refundSuccess = false;
		PaymentBase payment = PaymentFactory.GetPaymentService(paymentServiceType);			

		string serviceResponse = payment.Refund(amount, transactionId);

		if (serviceResponse.Contains("Auth") || serviceResponse.Contains("Success"))
		{
			refundSuccess = true;
		}

		return refundSuccess;
	}
}

We got rid of the downcasting issue. We now need to do something about the need to inspect the strings in the Contains method. This if statement still has to be extended if we introduce a new payment service and the client still has to know what “Success” means. If you think about it then ONLY the payment service objects should be concerned with this type of logic. The Refund method returns a string from the payment service but instead the string should be evaluated within the payment service itself, right? Let’s update the return type of the PaymentBase object:

public abstract class PaymentBase
{
	public abstract bool Refund(decimal amount, string transactionId);
}

We can transfer the response interpretation logic to the respective Payment objects:

public class WorldPayPayment : PaymentBase
{
	public WorldPayPayment(string accountId, string password, string productId)
	{
		AccountName = accountId;
		Password = password;
		ProductId = productId;
	}

	public string AccountName { get; set; }
	public string Password { get; set; }
	public string ProductId { get; set; }

	public override bool Refund(decimal amount, string transactionId)
	{
		WorldPayWebService worldPayWebService = new WorldPayWebService();
		string response = worldPayWebService.MakeRefund(amount, transactionId, AccountName, Password, ProductId);
		if (response.Contains("Success"))
			return true;
		return false;
	}
}
public class PayPalPayment : PaymentBase
{
	public PayPalPayment(string accountName, string password)
	{
		AccountName = accountName;
		Password = password;
	}

	public string AccountName { get; set; }
	public string Password { get; set; }

	public override bool Refund(decimal amount, string transactionId)
	{
		PayPalWebService payPalWebService = new PayPalWebService();
		string token = payPalWebService.GetTransactionToken(AccountName, Password);
		string response = payPalWebService.MakeRefund(amount, transactionId, token);
		if (response.Contains("Auth"))
			return true;
		return false;
	}
}

The RefundService has been greatly simplified:

public class RefundService
{
	public bool Refund(PaymentServiceType paymentServiceType, decimal amount, string transactionId)
	{
		PaymentBase payment = PaymentFactory.GetPaymentService(paymentServiceType);
		return payment.Refund(amount, transactionId);
	}
}

There’s no need to downcast anything or to extend this method if a new service is introduced. Strict proponents of the Single Responsibility Principle may argue that the Payment classes are now bloated, they should not know how to process the string response from the web services. However, I think it’s well worth refactoring the initial code this way. It eliminates the drawbacks we started out with. Also, in a Domain Driven Design approach it’s perfectly reasonable to include the logic belonging to a single object within that object and not anywhere else.

A related principle is called ‘Tell, Don’t Ask‘. We violated this principle in the initial solution where we asked the Payment object about its exact type: if you see that you need to interrogate an object about its internal state in order to branch your code then it may be a candidate for refactoring. Move that logic into the object itself within a method and simply call that method. Meaning don’t ask an object about its state, instead tell it to perform what you want it do.

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.

Design patterns and practices in .NET: the Service Locator anti-pattern

Introduction

The main responsibility of a Service Locator is to serve instances of services when consumers request them. The pattern is strongly linked to Dependency Injection and was introduced by Martin Fowler here.

The most common implementation of the pattern introduces a static factory. This factory can be configured with concrete services in the composition root of the application, such as global.asax, Main, etc., depending on the type of the application you’re developing. In other words the configuration happens before the first consumer can use it to extract a concrete service. Here you can think of a service as roughly equal to a dependency: the CustomerController has a dependency on ICustomerService. CustomerService has a dependency on ICustromerRepository etc. So when a concrete implementation of the abstraction is needed then the caller tries to grab it from the Service Locator.

A Service Locator is quite similar to Inversion-of-Control (IoC) containers at first. If you’re familiar with some IoCs such as StructureMap or CastleWindsor, then you’ll know that you can register your concrete types in the composition root. In StructureMap you can do this explicitly as follows:

x.For<ICustomerService>().Use<ConcreteCustomerService>();

The Service Locator configuration starts off in a similar manner. It’s essentially a dictionary of abstractions and their desired concrete types: ICustomerRepository – CustomerRepository; IProductService – ProductService. This is perfectly legitimate to do from the composition root. As we will see later consulting the service locator elsewhere in the application for concrete services is an anti-pattern.

Demo

We’ll simulate a dependency between the CustomerService and CustomerRepository classes where CustomerService requires a customer repository to consult the database for queries on the customer domain. Open Visual Studio and add the following standard generic implementation of a ServiceLocator:

public static class ServiceLocator
{
	private readonly static Dictionary<Type, object> _configuredServices = new Dictionary<Type, object>();

	public static T GetConfiguredService<T>()
	{
		return (T)ServiceLocator._configuredServices[typeof(T)];
	}

	public static void Register<T>(T service)
	{
		ServiceLocator._configuredServices[typeof(T)] = service;
	}
}

This is a very minimalistic implementation of the Service Locator. It’s void of exception handling, guard clauses, loading the dependency graph from an XML file but those features only add noise to the main discussion. The dependency map is stored in the private dictionary and the Register method is used, as you’ve probably guessed it, to register dependencies. It is analogous to the .For and .Use extension methods in the StructureMap example above. Let’s add the following interfaces and classes to see how the locator can be used:

public class Customer
{
}
public interface ICustomerService
{
	Customer GetCustomer(int id);
}
public interface ICustomerRepository
{
	Customer GetCustomerFromDatabase(int id);
}
public class CustomerRepository : ICustomerRepository
{
	public Customer GetCustomerFromDatabase(int id)
	{
		return new Customer();
	}
}
public class CustomerService : ICustomerService
{
	private ICustomerRepository _customerRepository;

	public CustomerService()
	{
		_customerRepository = ServiceLocator.GetConfiguredService<ICustomerRepository>();
	}

	public Customer GetCustomer(int id)
	{
		return _customerRepository.GetCustomerFromDatabase(id);
	}
}

You should be able to follow along this far. The CustomerService class resolves its own dependency using the ServiceLocator. You can configure the locator in Main as follows:

static void Main(string[] args)
{
	ServiceLocator.Register<ICustomerRepository>(new CustomerRepository());
	Customer c = new CustomerService().GetCustomer(54);
}

Main represents the composition root of a Console application so that’s where you can register the dependency graph. Step through the app with F11 and you’ll see that CustomerRepository is registered and retrieved as expected.

The CustomerService class can resolve its own dependency on ICustomerRepository, so what’s the problem? We can register our concrete implementations, retrieve the stored implementation where it’s needed, register Mock objects as concrete types in a Test Driven Design scenario, program against abstractions, write maintainable code, support late binding by changing the registration, so you’re a happy bunny, right? You shouldn’t be as the ServiceLocator class has a negative effect on the re-usability of the classes that consume it:

  • The ServiceLocator dependency will drag along if you try to re-use a class with a call to the locator
  • It is not obvious for external clients calling CustomerService() that Dependency Injection is used

The CustomerService will loosely depend on CustomerRepository through the ICustomerRepository interface. This is perfectly legitimate and valid. However, it will be tightly coupled to the ServiceLocator class. Here’s the dependency graph:

Dependency graph with service locator

If you want to distribute the CustomerService class then you’ll have to attach the ServiceLocator class to the package. It must come along even if the person that wants to use your class is not intending to use the ServiceLocator class in any way because they have their own Dependency Injection solution, such as StructureMap or CastleWindsor. Also, the consumer will need to set up ServiceLocator in the composition root otherwise they will get an exception. As the ServiceLocator may well reside in a different module, even that module must be redistributed for the CustomerService to be usable.

ProductService forces its users to follow the Dependency Injection strategy employed within it. There’s no room for other strategies unfortunately. Developers must simply accept the existence of the service locator. Also, there’s no way of telling that there’s a direct dependency just by looking at its signature which is what consumers will see first when creating a new CustomerService object. If the consumer doesn’t set up ServiceLocator appropriately then they will get an exception when using the CustomerService constructor. Depending on the exception handling strategy all they may get is a KeyNotFoundException. The consumer will then ask the questions: what key? Why is it not found? What are you talking about? WHY YOU NO WORK!!??? The consumer must know about the internals of the ConsumerService class which usually indicates a higher-than-desired level of coupling.

We can therefore rule out this patterns as it brings with it a fully redundant dependency which we can get rid of easily using constructor injection:

public CustomerService(ICustomerRepository customerRepository)
{
	_customerRepository = customerRepository;
}

There’s simply no advantage with this pattern that cannot be solved with an alternative solution such as constructor injection coupled with an IoC container. ProductService as it stands is not self-documenting. Its signature does not reveal anything about its dependency needs. Imagine that you download this API from NuGet and call CustomerService service = new CustomerService(). Your assumption would be that this is a fairly simple class that does not have any external dependencies which is not true as it turns out.

You can misuse IoC containers in the same way actually. It’s fine to use IoCs to resolve your dependencies “behind the scenes” but they – or at least some of them – allow the users to fetch concrete types from the container. In StructureMap you’d do it as follows:

StructureMap.ObjectFactory.Container.GetInstance<CustomerRepository>()

You should avoid using this type of dependency resolution for the same reasons why you wouldn’t use a ServiceLocator and its GetConfiguredService method.

Note that this pattern being an anti-pattern is a controversial topic. You can check out this post that offers another viewpoint and argues that Service Locator is indeed a proper design pattern.

View the list of posts on Architecture and Patterns here.

Design patterns and practices in .NET: the Prototype pattern

Introduction

The formal definition of the prototype pattern is the following: specify the kinds of objects to create using a prototypical instance and create new objects by copying this prototype.

What this basically says is instead of using ‘new’ to create a new object we’re going to use a prototype, an existing object to specify the new objects we’re going to create. Then we create new objects by copying from this prototype. So the prototype is a master, a blueprint and the other objects we create will be copies of that object. Another word that can be used instead of ‘copy’ is ‘clone’. So this pattern is very much about cloning objects. A real life example could be a photocopy machine that can get you exact copies of the original document instead of asking the original source to send you a brand new one. Making a copy in this case is a cheaper and a lot more efficient way of getting a copy of the object, i.e. the document.

The implementation of the pattern is very easy as you’ll see, almost confusingly easy. You may even ask yourself the question: is this really a pattern??

Demo

Open Visual Studio and create a new console application. We’ll simulate a reader that analyses the contents of web pages. You’ll need a reference to the System.Net.Http library. Insert the following class:

public class DocumentReader
{
	private string _pageTitle;
	private int _headerCount;
	private string _bodyContent;

	public DocumentReader(Uri uri)
	{
		HttpClient httpClient = new HttpClient();
		Task<string> contents = httpClient.GetStringAsync(uri);
		string stringContents = contents.Result;
		Analyse(stringContents);
	}

	private void Analyse(string stringContents)
	{
		_pageTitle = "Homepage";
		_headerCount = 2;
		_bodyContent = "Welcome to my homepage";
	}

	public void PrintPageData()
	{
		Console.WriteLine("Page title: {0}, header count: {1}, body: {2}", _pageTitle, _headerCount, _bodyContent);
	}
}

So we send in a URI to the constructor which downloads the string content of that URI. The Analyse method then fakes a true string content analysis. PrintPageData simply prints these findings in the console.

You can use this reader from Main as follows:

static void Main(string[] args)
		{
			DocumentReader reader = new DocumentReader(new Uri("http://bbc.co.uk"));
			reader.PrintPageData();
			Console.ReadKey();
		}

In a true implementation of the document reader we would probably parse the HTML document and try to find the real title, the body contents, the headers and lot more properties. However, even a true implementation of the Analyse method would run a lot faster than the actual download in the httpClient.GetStringAsync(uri) call. You’ll see that there’s a delay before we see the printout. The delay is not very significant as the HttpClient object coupled with the Task library is very efficient. However, we don’t want to cause the same delay if we need a copy of the page data.

The first solution is of course to create a new copy of the document reader, pass in bbc.co.uk and let it get the page data again. In other words we need to make the web request twice which is probably not very clever if we need a copy of the data that’s already been constructed. This is where the prototype pattern comes into the picture: we can make a copy of the document reader without having to perform the HTTP web request.

As it turns out the prototype pattern can be implemented using an interface available in .NET, the IClonable interface. The interface itself represents the abstract prototype; by the implementing object will itself be of type IClonable, i.e. a concrete prototype. The prototype will need to define a method which makes a copy of the object. The IClonable interface has a Clone() method which has this very purpose. The concrete prototype will have the ability to copy itself in the Clone() method where you can choose between creating a deep copy or a shallow copy, more on this later.

Let’s see how it’s done:

public class DocumentReader : ICloneable
{
	private string _pageTitle;
	private int _headerCount;
	private string _bodyContent;

	public DocumentReader(Uri uri)
	{
		HttpClient httpClient = new HttpClient();
		Task<string> contents = httpClient.GetStringAsync(uri);
		string stringContents = contents.Result;
		Analyse(stringContents);
	}

	private void Analyse(string stringContents)
	{
		_pageTitle = "Homepage";
		_headerCount = 2;
		_bodyContent = "Welcome to my homepage";
	}

	public void PrintPageData()
	{
		Console.WriteLine("Page title: {0}, header count: {1}, body: {2}", _pageTitle, _headerCount, _bodyContent);
	}

	public object Clone()
	{
		return MemberwiseClone();
	}
}

The interface has one member to be implemented which is the Clone method. Every object in .NET has built-in method called MemberwiseClone which suits our purposes just fine. It is going to copy all the data that exist in the original object, i.e. the prototype. It returns an object with the same data inside. However, be careful with this method as it cannot copy complex objects. Say that the DocumentReader had another object, like WebPage which in turn has its own private members, then MemberwiseClone will not copy those. In other words it creates a shallow copy as opposed to a deep copy. It copies the reference of complex objects instead of the objects themselves. However, it may be enough depending on what you want to achieve. Probably reading data from the same reference is OK, but not making changes to that reference. If you want perform a deep copy then you’ll have to manually make a memberwise clone of the entire object graph.

You can use this code in Main as follows:

static void Main(string[] args)
{
	DocumentReader reader = new DocumentReader(new Uri("http://bbc.co.uk"));
	reader.PrintPageData();

	DocumentReader readerClone = reader.Clone() as DocumentReader;
	readerClone.PrintPageData();

	Console.ReadKey();
}

Go ahead and run this and you’ll see that there’s no delay at all before the second printout appears in the console window.

This is the easiest implementation of the prototype pattern in .NET. It doesn’t make any sense to go through the object construction again and make the second web request.

Another similar scenario would have been making the same database calls. Often this is not necessary if all you need is the same set of data.

Yet another example is when you need a copy of an object with the same state. Imagine an object which has several private fields and those fields can be manipulated with public objects such as the following:

  1. TurnRight(int speed)
  2. GoStraightAhead()
  3. Stop()
  4. BuySomethingInTheShop(int productNumber)

These methods can modify the internal state of the object. In case you need another object with the same internal state then you’d need to go through the same steps as above. You’ll need to keep track of these steps and the user inputs as well.

A better solution is to implement the IClonable interface and clone the original object. You’ll then have access to the same state as in the prototype.

View the list of posts on Architecture and Patterns here.

Design patterns and practices in .NET: the Observer pattern

Introduction

As its name implies the pattern has to do with the interaction between two or more objects. The objects may or may not be related, but one object is interested in the changes of the other object. In other words there’s some kind of dependency between them. Changing one object may require changing one or more other objects. The most interesting case, however, is when changing an object should allow notification to others without any knowledge of them.

The pattern is used extensively in .NET:

  • GUI controls: events such as OnClick are handled through event handlers which are waiting for changes in the control
  • Data binding of controls: e.g. a GridView control in ASP.NET web forms can be bound to a data source upon which its item templates will be filled with data from the source
  • File watchers: you can monitor folders and files for changes. You can wire up the events so that you get notified if somebody has added a file to a certain folder

Starting point

Open Visual Studio and start a new Console application. We’ll simulate a financial application where people trade commodities, like in the Kansas City Board of Trade and similar exchanges. Create a new object called Commodity:

public class Commodity
{
	public string Name { get; set; }
	public decimal Price { get; set; }
}

Insert the following rudimentary repository:

public class CommodityRepository
{
	public IEnumerable<Commodity> GetAllCommodities()
	{
		return new List<Commodity>()
		{
			new Commodity(){Name = "milk", Price= 1}
			, new Commodity() {Name = "milk", Price = 1.2m}
			, new Commodity() {Name = "milk", Price = 1.3m}
			, new Commodity() {Name = "cocoa", Price = 2.1m}
			, new Commodity() {Name = "milk", Price = 3.2m}
			, new Commodity() {Name = "cocoa", Price = 2.9m}
			, new Commodity() {Name = "milk", Price = 1.8m}
			, new Commodity() {Name = "cocoa", Price = 1.7m} 
		};
	}
}

Insert the following in Main:

static void Main(string[] args)
{
	RunNaiveExample();
	Console.ReadKey();
}

private static void RunNaiveExample()
{
	IEnumerable<Commodity> commodities = new CommodityRepository().GetAllCommodities();
	foreach (Commodity commodity in commodities)
	{
		if (commodity.Name == "cocoa")
		{
			Console.WriteLine("The current price of cocoa is {0}", commodity.Price);
		}

		if (commodity.Name == "milk" && commodity.Price > 2m)
		{
			Console.WriteLine("The price of milk has now reached {0}", commodity.Price);
		}
	}
}

The intent is quite simple here, right? We’re looping through the list of commodities in the list and if we find something interesting then we print it out in the console. The multiple entries in the Commodities list simulates that we ask some service periodically, like in a ticker. This is probably the simplest version of commodity monitoring. We perform one or more actions based on the filtering in the if statements. Run the app to see the output: milk exceeds the target price of 2 once, and cocoa appears 3 times.

Even in this short application we can see several issues, particularly with the separation of concerns. The loop in Main corresponds to a ticker. However, a ticker doesn’t need to know that we’re monitoring specific commodities. It doesn’t need to know about the price of milk and cocoa to perform its job. All it needs to do is to read the commodities one by one and report on them. Also, we’re mixing prices in the loop: the milk price has nothing to do with the cocoa price – at least not from a software design point of view.

These are all independent actions that are mixed together in the same programme. In case we want to monitor a different commodity then we have to extend the foreach loop, i.e. we have to modify the main application.

The observer pattern allows us to separate out those filters, which are called observers, and the actions that they’re taking.

Events and delegates

.NET supports events and delegates which are excellent candidates for implementing the observer pattern. The event is created on the subject and allows for the registration of observers through a delegate callback mechanism. The observers will provide implementations for the delegate methods that will be called by the subject when the event is raised.

If you’re familiar with .NET desktop apps and ASP.NET web forms then you must have seen a lot of events: the standard button has a click event – among others – and a corresponding OnClick event handler. Event handlers are also called callbacks. As events and delegates are built-in objects in .NET there’s nothing stopping you from implementing the observer pattern using your own events and delegates. You can also pass event arguments to event handlers.

Let’s start our implementation with the event arguments. All such objects must derive from the EventArgs object:

public class CommodityChangeEventArgs : EventArgs
{
	public Commodity Commodity { get; set; }

	public CommodityChangeEventArgs(Commodity commodity)
	{
		this.Commodity = commodity;
	}
}

So when there’s a change in the commodity, its price, its name or any other property, then we can send it along with all other properties that can be interesting to the event handler waiting for such a change. An object waiting for such a change event might be the following CommodityMonitor object:

public class CommodityMonitor
{
	private Commodity _commodity;
	public event EventHandler<CommodityChangeEventArgs> CommodityChange;

	public Commodity Commodity
	{
		get
		{
			return _commodity;
		}
		set
		{
			_commodity = value;
			this.OnCommodityChange(new CommodityChangeEventArgs(_commodity));
		}
	}

	protected virtual void OnCommodityChange(CommodityChangeEventArgs e)
	{
		if (CommodityChange != null)
		{
			CommodityChange(this, e);
		}
	}
}

As the CommodityMonitor monitors commodities it will need a Commodity object. If you are new to events then the event declaration might look unusual but that is how we register an observer. The OnCommodityChange method has the notifier role in this setup and it accepts the appropriate event arguments. This method is called by the Commodity setter: if there’s a change then run the notification logic. The notifier then checks if the observer has been set, i.e. whether it’s null or not. If yes then it raises the event. Events have a common pair of arguments: the sender, i.e. the object that sends the change event and the event arguments. The sender will simply be “this”, i.e. the CommodityMonitor object. It sends out a signal saying that something has changed. What has changed? Anyone who’s interested can find it out from the event arguments. Any objects can sign up as observers and they will all be notified.

Here we only set up one event, but an object can raise many events. We may raise separate events for price changes, name changes, weather changes, football score changes etc. They can have their own event arguments as well. So this model provides a high level of granularity and object orientation.

The next thing we want to do is create our observers. We’re interested in milk and cocoa so we’ll insert two observers. We’ll start with MilkObserver:

public class MilkObserver
{
	public MilkObserver(CommodityMonitor monitor)
	{
		monitor.CommodityChange += monitor_CommodityChange;
	}

	void monitor_CommodityChange(object sender, CommodityChangeEventArgs e)
	{
		CheckFilter(e.Commodity);
	}

	private void CheckFilter(Commodity commodity)
	{
		if (commodity.Name == "milk" && commodity.Price > 2m)
		{
			Console.WriteLine("The price of milk has now reached {0}", commodity.Price);
		}
	}
}

The funny looking monitor.CommodityChange += monitor_CommodityChange part performs the registration. We want to register the milk observer to the CommodityChange event of the monitor. It is the monitor_CommodityChange that’s going to handle the event. Check its signature, it follows the sender + event args standard. The event handler must have this signature otherwise it cannot be registered as the event handler of the commodity change event. Furthermore the type of the event arguments must match the type declared in CommodityMonitor.

The plus sign declares that we want to register. We could revoke the registration with a minus: monitor.CommodityChange -= monitor_CommodityChange if we are not interested in the changes any more. In fact as you type ‘+’ then IntelliSense will give you the option to create a new event handler – or select an existing one if there’s any with the correct signature.

So what’s happening if the event is raised? The CheckFilter is run which accepts a Commodity object. The filter will be familiar to you from the first naive implementation: we check the name and the price and if it matches the criteria then we print out the message in the console.

What’s even more important I think is that we turned our original primitives-based solution into an object oriented one. We raised an if-statement in the client to a proper object acknowledging its importance in our domain model. It is now an independent object that can be tested separately.

The CocoaObserver looks similar:

public class CocoaObserver
{
	public CocoaObserver(CommodityMonitor monitor)
	{
		monitor.CommodityChange += monitor_CommodityChange;
	}

	void monitor_CommodityChange(object sender, CommodityChangeEventArgs e)
	{
		CheckFilter(e.Commodity);
	}

	private void CheckFilter(Commodity commodity)
	{
		if (commodity.Name == "cocoa")
		{
			Console.WriteLine("The current price of cocoa is {0}", commodity.Price);
		}
	}
}

Insert the following method in Program.cs and call it from Main:

private static void RunEventBasedExample()
{
	CommodityMonitor monitor = new CommodityMonitor();

	CocoaObserver cocoaObserver = new CocoaObserver(monitor);
	MilkObserver milkObserver = new MilkObserver(monitor);

	IEnumerable<Commodity> commodities = new CommodityRepository().GetAllCommodities();
	foreach (Commodity commodity in commodities)
	{
		monitor.Commodity = commodity;
	}
}

We create a new commodity monitor and then sign up our two observers. We could add as many observers as we want to. Then we run through our list of commodities and set them as the Commodity property of the monitor object. The property setter then raises the event as explained above. Run through the code by setting breakpoints and pressing F11 in order to follow the exact code execution.

IObserver-based solution

.NET4 introduced a new type of interface: IObserver of T and IObservable of T. As the names of the interfaces imply the CommodityMonitor class will have something to do with the IObservable interface as it can be observed. In fact CommodityMonitor will implement this interface. The Milk and CocoaObservers will implement the IObserver interface.

The IObserver interface will force us to implement several methods:

  • OnCompleted: indicates that there will be no more changes to the subject
  • OnError: when there’s an error in processing the subject
  • OnNext: when getting the next value of the subject, equivalent to the Commodity setter in the event-based solution

IObservable has a Subscribe method that must be implemented. It represents the registration of observers and returns an IDisposable object. As it returns an IDisposable it will be easier for us to release an observer from the subject properly. This is actually a drawback of the event-based method above as we only subscribe to the event but never release the observer. We think that the garbage collector will take care of that but that’s not the case; there’s still a reference to the observer from the subject so this resource is not released for garbage collection. With the Subscribe method we get a reference to the IDisposable method so that we can keep track of it and release it when we don’t use it any longer.

We’ll see in the demo how this is done.

This setup implements the “push” approach of the pattern: whenever there’s a change in the subject we push them out to the observers.

Let’s implement the pattern using these interfaces.

Here come the updated observers first. They are very simple; they implement the three methods in IObserver mentioned above. You’ll recognise the usual filter in the OnNext method. Recall that this runs when we get an update from the subject.

public class CocoaObserverModern : IObserver<Commodity>
{
	public void OnCompleted()
	{
		Console.WriteLine("Shop closed.");
	}

	public void OnError(Exception error)
	{
		Console.WriteLine("Oops: {0}", error.Message);
	}

	public void OnNext(Commodity commodity)
	{
		if (commodity.Name == "cocoa")
		{
			Console.WriteLine("The current price of cocoa is {0}", commodity.Price);
		}
	}
}

We send in the updated Commodity to the OnNext method so that we can check its properties. We’re also prepared to handle exceptions that occur in the commodity monitor during the update of the subject. Lastly we tell the user when we’re done updating the subjects.

public class MilkObserverModern : IObserver<Commodity>
{
	public void OnCompleted()
	{
		Console.WriteLine("Shop closed.");
	}

	public void OnError(Exception error)
	{
		Console.WriteLine("Oops: {0}", error.Message);
	}

	public void OnNext(Commodity commodity)
	{
		if (commodity.Name == "milk" && commodity.Price > 2m)
		{
			Console.WriteLine("The price of milk has now reached {0}", commodity.Price);
		}
	}
}

Insert a class called ObservableCommodity which is the IObservable version of the previous CommodityMonitor object:

public class ObservableCommodity : IObservable<Commodity>
{
        private List<IObserver<Commodity>> _observers = new List<IObserver<Commodity>>();
	private Commodity _commodity;
	public Commodity Commodity
	{
		get
		{
			return _commodity;
		}
		set
		{
			_commodity = value;
			this.Notify(_commodity);
		}
	}

	private void Notify(Commodity commodity)
	{
		foreach (IObserver<Commodity> observer in _observers)
		{
			if (commodity.Name == null || commodity.Price < 0)
			{
				observer.OnError(new Exception("Bad Commodity data"));
			}
			else
			{
				observer.OnNext(commodity);
			}
		}
	}

	private void Stop()
	{
		foreach (IObserver<Commodity> observer in _observers)
		{
			if (_observers.Contains(observer))
			{
				observer.OnCompleted();
			}
		}
		_observers.Clear();
	}


	public IDisposable Subscribe(IObserver<Commodity> observer)
	{
		if (!_observers.Contains(observer))
		{
			_observers.Add(observer);
		}
		return new Unsubscriber(_observers, observer);
	}

	private class Unsubscriber : IDisposable
	{
		private List<IObserver<Commodity>> _observers;
		private IObserver<Commodity> _observer;

		public Unsubscriber(List<IObserver<Commodity>> observers, IObserver<Commodity> observer)
		{
			_observers = observers;
			_observer = observer;
		}
		public void Dispose()
		{
			if (_observer != null && _observers.Contains(_observer))
			{
				_observers.Remove(_observer);
			}
		}
	}
}

This is more complicated than the CommodityMonitor class. As before we have the Commodity getter and setter. We call the Notify method in the setter. This method will notify each observer in some way: it calls the OnError method of the observer if the Commodity object has an invalid property. It also sends along an Exception object. Otherwise it just calls the OnNext method and sends in the commodity object.

Now check out the Subscribe method. As we said before it returns an IDisposable object. We add the incoming observer to the collection of observers, but we check first if the observer has been added before. We return an object which is the unsubscriber of the observer from the observers collection.

Check out the private Unsubscriber class. It implements the IDisposable interface meaning it has to implement the Dispose method. It holds a reference to the list of observers and the observer, both populated from the Subscribe method. In the Dispose method we check if the observer is not null and if it is contained by the observers list. If both conditions apply then we remove the observer from the observers list.

The Stop method of ObservableCommodity is not actually used. I’ve included it for your reference; it could be used when there are no more commodity objects in the collection. In that case we can call the OnCompleted method of each observer.

Let’s run our code. Insert the following method into Program.cs and call it from Main:

private static void RunModernObserableBasedApproach()
{
	ObservableCommodity oc = new ObservableCommodity();
	MilkObserverModern milkObserver = new MilkObserverModern();
	CocoaObserverModern cocoaObserver = new CocoaObserverModern();
	IEnumerable<Commodity> commodities = new CommodityRepository().GetAllCommodities();
	using (oc.Subscribe(milkObserver))
	{
		using (oc.Subscribe(cocoaObserver))
		{
			foreach (Commodity commodity in commodities)
			{
				oc.Commodity = commodity;
			}
		}
	}
}

This looks pretty much like the RunEventBasedExample method. We have our observable object and the two observers. We don’t need to send in the commodity monitor to the constructor of the observers this time. Observer registration is taken care of by the Subscribe method. We’re using “using” statements as Subscribe returns an IDisposable object. This technique will make sure that we release the observer from the subject.

Run the app and you’ll see that even the modern approach works fine and returns the same output as before.

View the list of posts on Architecture and Patterns here.

Design patterns and practices in .NET: the Bridge pattern

Introduction

This pattern was originally defined by the Gang of Four as follows: decouple an abstraction from its implementation so the two can vary independently.

You probably know what abstractions are: base classes and interfaces, i.e. objects to generalise our code and/or make a group of objects related in some way. We abstract away ideas that can have multiple concrete implementations. Normally if a class implements an interface or derives from an abstract superclass then the abstraction and the implementation are tightly coupled. If you change the structure of the interface, such as add a new method to it, then all implementations will need to change as well. The bridge pattern aims to decouple them so that we get rid of this coupling. We’ll introduce a higher level of abstraction to abstract away the implementation from the original abstraction. We’ll end up with two levels of abstraction instead of just one.

Let’s try and imagine a real-world example: a travel agent putting together different types of holiday in a brochure. The agency organises trips to 4 countries: Cyprus, Turkey, Greece and Italy. It also offers a couple of extras: private pool, free gym, all-inclusive and massage. The agency wants to show the full programme as follows:

  • Italy – private pool – free gym
  • Cyprus – private pool – free gym
  • Turkey – private pool – free gym
  • Greece – private pool – free gym
  • Italy – all inc – massage
  • Cyprus – all inc – massage
  • Turkey – all inc – massage
  • Greece – all inc – massage
  • …so on and so forth

In other words the agency wants to show the full combos as single items. You’ll see a lot of duplication here: the combination of extras is repeated several times, such as ‘all inc – massage’. However, the person putting together this brochure was committed to show all the options in one place. We can think of the concept ‘trip’ as the abstraction and the combos as the implementations: we can have Italy with private-pool-and-free-gym; we can have Italy with all-inclusive-and-massage; we can have Cyprus with private-pool-and-free-gym etc.

Another agent looks at this and ‘refactors’ the brochure. She realises that the offers can be simplified greatly to:

  • Cyprus
  • Turkey
  • Greece
  • Italy

with

  • private pool – free gym
  • all inc – massage

Now it’s easier to build combos: we can add new countries and new combinations of extras. In the first example if we introduce a new combination of extras, such as private-pool-with-massage then the agent will need to create 4 new items in the brochure, one for each country. We have a similar problem if we add a new country. In the second solution the client can choose how to combine the destination with the extra combos. It is not the agent, i.e. the developer, that builds all the combos, but the client.

Demo

In the demo we’ll simulate a building management application. Imagine that some authority is responsible for maintaining state-owned buildings and they need help with creating a manager application. Open Visual Studio and create a new console application. We’ll start with 3 basic domain objects with their own properties and a Print method in common:

public class Apartment
{
	public string Description { get; set; }
	public Dictionary<string, string> Rooms { get; set; }

	public Apartment()
	{
		Rooms = new Dictionary<string, string>();
	}

	public void Print()
	{
		Console.WriteLine("Apartment: ");
		Console.WriteLine(Description);
		foreach (KeyValuePair<string, string> room in Rooms)
		{
			Console.WriteLine(string.Concat("Room: ", room.Key, ", room description: ", room.Value));
		}
	}
}
public class House
{
	public string Description { get; set; }
	public string Owner { get; set; }
	public string Address { get; set; }

	public void Print()
	{
		Console.WriteLine("House: ");
		Console.WriteLine(string.Concat("Description: ", Description, " owner:  ", Owner, " address: ", Address));
	}
}
public class TrainStation
{
	public int NumberOfTrains { get; set; }
	public string Location { get; set; }
	public int NumberOfPassangers { get; set; }
	public string Director { get; set; }

	public void Print()
	{
		Console.WriteLine("Train station: ");
		Console.WriteLine(string.Concat("Number of trains: ", NumberOfTrains, ", Location: ", Location, ", number of passangers: ", NumberOfPassangers
			, ", director: ", Director));
	}
}

We construct and print the objects in Main as follows:

class Program
{
	static void Main(string[] args)
	{
		Apartment apartment = new Apartment();
		apartment.Description = "Nice apartment.";
		apartment.Rooms.Add("1/A", "Cozy little room");
		apartment.Rooms.Add("2/C", "To be renovated");
		apartment.Print();

		House house = new House();
		house.Address = "New Street";
		house.Description = "Large family home.";
		house.Owner = "Mr. Smith.";
		house.Print();

		TrainStation trainStation = new TrainStation();
		trainStation.Director = "Mr. Kovacs";
		trainStation.Location = "Budapest";
		trainStation.NumberOfPassangers = 100000;
		trainStation.NumberOfTrains = 100;
		trainStation.Print();

		Console.ReadKey();
	}
}

Run the app to see the output. Up to now this is extremely basic I guess. All domain objects have a different set of properties and structure. Also, there are a couple of similarities. They are definitely all buildings and they can be printed. The first step towards an abstraction – and so the bridge pattern – is to introduce an interface in the domain:

public interface IBuilding
{
	void Print();
}

Make the 3 domain objects implement the interface. In Main we can then have a list of IBuilding objects and call their Print method in a loop:

static void Main(string[] args)
{
	List<IBuilding> buildings = new List<IBuilding>();
	Apartment apartment = new Apartment();
	apartment.Description = "Nice apartment.";
	apartment.Rooms.Add("1/A", "Cozy little room");
	apartment.Rooms.Add("2/C", "To be renovated");
	buildings.Add(apartment);

	House house = new House();
	house.Address = "New Street";
	house.Description = "Large family home.";
	house.Owner = "Mr. Smith.";
	buildings.Add(house);

	TrainStation trainStation = new TrainStation();
	trainStation.Director = "Mr. Kovacs";
	trainStation.Location = "Budapest";
	trainStation.NumberOfPassangers = 100000;
	trainStation.NumberOfTrains = 100;
	buildings.Add(trainStation);

	foreach (IBuilding building in buildings)
	{
		building.Print();
	}

	Console.ReadKey();
}

Run the app and you should see the same output as before.

If the requirements stop here then we don’t need the bridge pattern. We only introduced a bit of abstraction to generalise our domain model. However, note that this is the first step towards the pattern: we now have the first level of abstraction and we’ll need a second if the requirements change.

As requirements do change in practice this is what we’ll simulate: the customer wants to be able to print out the objects in different styles and formats. A possible solution is to create a different type of House, or even derive from it, call it FormattedHouse and override the Print method according to the new requirements – need to make the Print method of House overridable. Make the same changes to the other 2 objects and then we end up with 6 domain objects. As we add new types of building we always have to create 2: one with a normal printout and one with the fancy style. And when the customer asks for yet another type of printout then we’ll have 9 domain objects where our domain should really only have 3.

We could prevent this with some kind of parameter, like “bool fancyPrint” leading to an if-else statement within the Print method. Then as we introduce new formatting types we may switch to an enumeration instead leading to an even longer if-else statement and the need to extend each and every Print() implementation as the enumeration grows. This is not good software engineering practice.

Instead we need another level of abstraction that takes care of the formatting of the printout. We still want to print the attributes of the domain objects but we want a formatter to take care of that. In addition as our objects have different structures we want to preserve the liberty of printing the specific properties of the domain objects. We don’t want to force the House object to have a NumberOfTrains property just to make the domains universal.

Let’s start out with the following formatter interface:

public interface IFormatter
{
    string Format(string key, string value);
}

This is quite simple and general: the key will be the formatting style, such as “Description: “, and the value is the value to be printed, such as House.Description.

We’ll need to inject this formatter to the Print method of each domain object, so update the IBuilding interface as follows:

public interface IBuilding
{
	void Print(IFormatter formatter);
}

Update each Print implementation to accept the IFormatter parameter, example:

public void Print(IFormatter formatter)

A short side note: if you want to force your domain objects to have a formatter then you will need to create an abstract base class that each domain object inherit from, such as BuildingBase. The constructor of the base class will accept an IFormatter so that you’ll need to update the constructor of each domain object to accept an IFormatter. However, here I’ll just stick to the interface solution.

Let’s update the Print method in each of the domain objects to use the formatter:

public class House : IBuilding
{
	public string Description { get; set; }
	public string Owner { get; set; }
	public string Address { get; set; }

	public void Print(IFormatter formatter)
	{
		Console.WriteLine(formatter.Format("Description: ", Description));
		Console.WriteLine(formatter.Format("Owner: ", Owner));
		Console.WriteLine(formatter.Format("Address: ", Address));
	}
}
public class TrainStation : IBuilding
{
	public int NumberOfTrains { get; set; }
	public string Location { get; set; }
	public int NumberOfPassangers { get; set; }
	public string Director { get; set; }

	public void Print(IFormatter formatter)
	{
		Console.WriteLine(formatter.Format("Number of trains: ", NumberOfTrains.ToString()));
		Console.WriteLine(formatter.Format("Location: ", Location));
		Console.WriteLine(formatter.Format("Number of passangers:", NumberOfPassangers.ToString()));
		Console.WriteLine(formatter.Format("Director: ", Director));
	}
}
public class Apartment : IBuilding
{
	public string Description { get; set; }
	public Dictionary<string, string> Rooms { get; set; }

	public Apartment()
	{
		Rooms = new Dictionary<string, string>();
	}

	public void Print(IFormatter formatter)
	{
		Console.WriteLine(formatter.Format("Description: ", Description));
		foreach (KeyValuePair<string, string> room in Rooms)
		{
			Console.WriteLine(string.Concat(formatter.Format("Room: ", room.Key), formatter.Format(", room description: ", room.Value)));
		}
	}
}

Now we’re ready for some implementations of the IFormatter interface. The most obvious choice is a standard formatter that prints the properties as in our previous solution:

class StandardFormatter : IFormatter
    {
        public string Format(string key, string value)
        {
            return string.Format("{0}: {1}", key, value);
        }
    }

The updated Main method looks like follows:

static void Main(string[] args)
{
	IFormatter formatter = new StandardFormatter();
	List<IBuilding> buildings = new List<IBuilding>();
	Apartment apartment = new Apartment();
	apartment.Description = "Nice apartment.";
	apartment.Rooms.Add("1/A", "Cozy little room");
	apartment.Rooms.Add("2/C", "To be renovated");
	buildings.Add(apartment);

	House house = new House();
	house.Address = "New Street";
	house.Description = "Large family home.";
	house.Owner = "Mr. Smith.";
	buildings.Add(house);

	TrainStation trainStation = new TrainStation();
	trainStation.Director = "Mr. Kovacs";
	trainStation.Location = "Budapest";
	trainStation.NumberOfPassangers = 100000;
	trainStation.NumberOfTrains = 100;
	buildings.Add(trainStation);

	foreach (IBuilding building in buildings)
	{
		building.Print(formatter);
	}
	Console.ReadKey();
}

Run the app and you’ll see that the properties of each object are printed out in the console.

Now if the customer wants new types of format then you can just say “ah, OK, give me five minutes!”. 5 minutes of programming can give you a fancy formatter such as this:

public class FancyFormatter : IFormatter
    {
        public string Format(string key, string value)
        {
            return string.Format("-=! {0} ----- !=- {1}", key, value);
        }
    }

Then just change the type of the formatter in the Main method to test the output. There you are, you have a new formatter without changing any of the domain objects. We change the formatting behaviour of each object without having to add extra parameters and inhering from existing classes to override the Print method. It’s now a breeze to add new types of formatters. The formatting behaviour is decoupled from the Print() method. We still print out each property of our objects but it is the formatter that takes care of formatting that printout. We can even apply a different formatter to each of our domain objects.

In the language of the pattern we have the following components:

  • IBuilding: the abstraction
  • Building types: the refined abstractions that implement the abstraction
  • IFormatter: the implementor which is the second level abstraction
  • Formatter types: the concrete implementors which implement the implementor abstraction

We’ve successfully abstracted away printing format mechanism and introduced a second level of abstraction required by the pattern. In fact we’re bridging the ability to print and the way the actual printing is carried out. You may not even want to print on the Console window but on a real printer. You can abstract away that logic using this pattern.

Let’s add yet another formatter:

public class UglyFormatter : IFormatter
{
	public string Format(string key, string value)
	{
		return string.Format("*^*_##@!!!!!!!&/(%&{0}:{1}", key, value);
	}
}

Again, change the formatter type in the Main method to see the effect. We can even have a menu list where the customer can pick the format.

Also, our formatters are proper objects, not primitives such as a boolean flag or an enumeration where we inspect the parameter in a long if-else statement.

We could even add other types of implementors, such as language formatters, colour formatters etc. to the Print method using this pattern. We can vary them as we wish: ugly formatting – English – red, fancy formatting – German – yellow.

Common usages of this pattern include:

  • Graphics: if you run a Java desktop application on Windows or a Mac then the GUI elements, such as the button, may be draw differently depending on the operating system
  • Persistence: database persistence, file persistence, memory persistence etc. where the object may have Persist method with an IPersistence interface taking care of the persistence logic
  • .NET providers: profiles and membership have their built-in providers in .NET that you may have used in your code. Those are also based on the bridge pattern: we bridge the ability to authorise a user and the actual way of performing the authorisation

In case you feel the need to build a large class hierarchy where the concrete classes only change some type of logic but are not truly different domain objects then you may have a candidate for the bridge pattern.

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.