Singleton vs Dependency Injection

By Vladimir Khorikov

This post is a showcase for the Singleton design pattern. In contrast to the common belief, Singleton is not inherently bad and I’ll try to show you in what circumstances it is a good choice.

Singleton

Let me give a refresher regarding what Singleton is about. It is one of the most basic design patterns from the GoF book and I’m sure most of you knows it, but it’s still a good place to start.

Singleton is a design pattern which stands for having only one instance of some class during the whole application lifetime. A typical implementation of a Singleton looks like this:

public class BankGateway

{

    public readonly static BankGateway Instance = new BankGateway();

 

    private BankGateway()

    {

    }

 

    public void TransferMoney()

    {

        /* Transferring money */

    }

}

Note that the constructor is private and the only way to get an instance of it is to refer to the Instance property. And as this property is static, it will live for as long as the application process is still running (more precisely, it’s bound to the application domain lifetime).

Also, note that this implementation doesn’t support lazy loading, so the instance will be instantiated at the type load regardless of whether you need it or not. (Actually, the behavior is more complex and depends on the presence of the beforefieldinit IL flag for that class, which in turn depends on the specific .NET Framework version and the existence of a static constructor. These details are not essential for us.) And of course, we can easily implement a version that supports lazy loading.

The main complaint about Singleton is that it contradicts the Dependency Injection principle and thus hinders testability. It essentially acts as a global constant, and it is hard to substitute it with a test double when needed.

So, if you have a method like this one:

public class Processor

{

    public void Process()

    {

        BankGateway.Instance.TransferMoney();

    }

}

It would be difficult to test it because each time you run the Process method, it calls the actual bank gateway. And that is something we should avoid during unit tests execution.

Dependency Injection

Dependency Injection is a design pattern that stands for passing dependencies to objects using them. The code above can be rewritten using this pattern in the following way:

public interface IBankGateway

{

    void TransferMoney();

}

 

public class BankGateway : IBankGateway

{

    public void TransferMoney()

    {

        /* Transferring money */

    }

}

 

public class Processor

{

    private readonly IBankGateway _gateway;

 

    public Processor(IBankGateway gateway)

    {

        _gateway = gateway;

    }

 

    public void Process()

    {

        _gateway.TransferMoney();

    }

}

The code above is testable. We can create a fake bank gateway, pass it to the Processor and make sure it uses it to transfer money. At the same time, no calls to the actual bank gateway are made.

Singleton vs Dependency Injection

The latter design is preferable in the vast majority of cases. If you’ve got a non-stable dependency, it’s always a good practice to inject that dependency to the dependent class. Aside from greater testability, this practice helps the class explicitly specify everything it needs in order to perform properly. A non-stable dependency is a dependency which refers to or affects the global state, such as external service, file system, or a database.

However, there still are dependencies which are better represented using Singleton. They are ambient dependencies. Ambient dependencies are dependencies which span across multiple classes and often multiple layers. They act as cross-cutting concerns for your application.

It doesn’t really make sense to apply the Dependency Injection design pattern for such dependencies as they are going to be everywhere anyway. Here’s how we can diagram one:

Singleton: Repeating dependencies.

Repeating dependencies.

The dependency #1 is present in each of the three services. Hence, it’s a good candidate for extracting it to a Singleton:

Repeating dependency is extracted to a Singleton.

Repeating dependency is extracted to a Singleton.

What we are doing here is we are essentially removing that dependency from the “dependency equation” making the overall graph simpler. Without doing this, the code base would be flooded with the excessive number of the same dependencies traversing most of your classes.

The heuristic to determine whether you need to introduce a singleton is simple. If a dependency cross-cuts most of your classes and/or several layers in your application, extract it using the Singleton pattern. Otherwise, use the standard Dependency Injection technique. The ultimate goal is to make sure that you don’t use DI for ambient dependencies.

Singleton examples

A good example here is a logger service. If you tend to log a lot of activities throughout your code base, it’s just not practical to pass the logger instance to every class that needs it as a dependency. A better way is to introduce a Singleton.

Another example is the DateTime.Now property. It’s often the case that you want to fake it in unit tests to make sure your code works with current date and time correctly. However, wrapping this functionality in a dependency and injecting it all over your code base would turn it into a mess. Singleton is a viable option here as well.

So instead of code like this:

public interface ISystemDateTime

{

    DateTime Now { get; }

}

 

public class SystemDateTime : ISystemDateTime

{

    public DateTime Now

    {

        get { return DateTime.UtcNow; }

    }

}

 

// Implement a fake SystemDateTime and pass it in unit tests

You can introduce a static class in the following way:

public static class SystemDateTime

{

    private static Func<DateTime> _func;

 

    public static DateTime Now

    {

        get { return _func(); }

    }

 

    public static void Init(Func<DateTime> func)

    {

        _func = func;

    }

}

 

// Initialization code for production

SystemDateTime.Init(() => DateTime.UtcNow);

 

// Initialization code for unit tests

SystemDateTime.Init(() => new DateTime(2016, 5, 3));

Here, Instead of passing around instances of the ISystemDateTime interface, we make the SystemDateTime class static and define an Init method in it that accepts a factory for producing the current date and time. We then use different factories for test and production environments.

Note that such implementation leaves a whole in our code base as we need not forget to initialize Singletons before using them. In other words, we introduce a temporal coupling here. However, it’s pretty easy to track an error in case you forget to initialize a Singleton as it would show up close to the application start-up. And it’s still cleaner than passing huge amount of repeating dependencies all over your code base. Moreover, as all such initializations are usually gathered in a single place – Composition Root – it’s pretty easy to manage them anyway.

Ultimately, you need to reach a balance between dependencies injected using the DI principles and the ones introduced as singletons. You don’t want ambient dependencies to be passed around as they would flood your dependency graph. At the same time, you don’t want to represent occasional dependencies as Singletons.

Domain singletons

A separate type of singletons which I also would like to mention here is the one which is intrinsic to your domain model. Sometimes, a concept just fits the Singleton pattern even if it’s not an ambient dependency. For example, if you have an Organization entity and there can be only one such entity in your domain model, it’s just fine to represent it as a Singleton as well:

public class Organization

{

    public static Organization Instance { get; private set; }

 

    private Organization(int id, string name)

    {

        /* … */

    }

 

    public static void Init(int id, string name)

    {

        Instance = new Organization(id, name);

    }

}

Summary

It’s important to keep a balance between the dependencies represented as Singletons and the ones injected using the DI principles. The following heuristic will help you to determine which pattern to use:

  • If a dependency is ambient, meaning that it is used by many classes and/or multiple layers, use Singleton.
  • Otherwise, inject it to the dependent classes using the Dependency Injection pattern.
LinkedInRedditTumblrBufferPocketShare




  • Dennis

    Nice post! it’s important to note that you can achieve Singletons with dependency injection using IOC.
    Inside the container definitions you can specify the lifestyle of each component. Some can be made transient, some per thread and some cam be made Singletons.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      You are right. I probably stretch the definition of Singleton here a bit and actually mean “Singleton implemented as a static property”. Singletons can be used in conjunction with DI.

  • http://mdbs99.com Marcos Douglas Santos

    Do not you think that this code is more a Factory than a Singleton?
    SystemDateTime.Init(() => DateTime.UtcNow);

    You can passa a function them return a new instance of an object.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      It’s more like Singleton accepting a Factory in order to initialize itself.

  • Margus Martsepp

    Not quite yet.

    First, your choice for interface name is poor. A better option would be ‘IDateTimeProvider’.

    Second, in code, your IoC container will create an instance just by using default conventions. If you want to resolve them to a single instance you would use (using structuremap) :

    x.For().Singleton().Use();

    Finally, you would not use IoC for tests. If you write tests in test driven development you would mock it – because, well you should not wait for the implementation to write the tests. It is same for domain/behavior/pain or … driven development.

    For example, you can create a mock in test setup with (using moq)

    _dateTimeProvider = Mock.Of(o => o.Now == time);

    or specify in tests directly with

    Mock.Get(_dateTimeProvider)
    .Setup(o => o.Now)
    .Returns(time);

  • Michael G.

    Maybe for desktop applications, having the logger be a Singleton works well. But for any web application, you typically wish to log what happened on each request. For that purpose all logging on a request has to be grouped into a single log entry with several log events. The only way to do that is to use IoC to create a new instance of the logger per request. Otherwise it becomes impossible to differentiate which log event was tied to which request.

    A good article none-the-less. I just felt it was important to point that issue out, so someone building web applications don’t fall into that trap of having a static logger (which I have done) and all the headaches that creates.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      Good point. Indeed, system requirements can necessitate the use of DI even when Singleton seems like a viable option.

  • Ben

    Why do you need IBankGateway? Why can’t Processor’s constructor be `public Processor(BankGateway gateway)` instead?

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      That’s for the purpose of substituting it with a test double during unit testing. You can do the same without an interface but you’ll need to declare the methods on BankGateway virtual. Basically, whether to have an interface of virtual methods comes down to a matter of taste.