When Singletons are allowed

Cover image for Singleton are not always bad article

Like all tools in the programmer bag, Singletons are allowed in some cases and we should know how to use them. Singletons are often discriminated as the root of all evil, and for a good reason. However they are not as bad as one can think, and I’ll show here when their use is allowed.

A small recap on why Singleton’s usage can be is evil (I’ll not explain stuff that is already covered by dozens of other blogs):

  • Undefined initialization order
  • They can’t be mocked
  • They maintain state on a global scope
  • They are usually tightly coupled with your code

With a so big list of side effects, one don’t really expects they can still be used.

Let’s address all points in the bullet list…

  • Initialization order: it matters only when they are depending theirselves on global data or other singletons, especially in C++, (where we can place a global variable anywhere in the code) this can become quickly a problem. Initialization order is “well defined” for the compiler but it is not obvious for us, and may suddenly change as long as the code base evolve.

The solution to that is initializing the singletons in the Main, or have lazy Singletons that are initialized only when needed, or even better they must not have dependencies on other global/static stuff. Relying on initialization order is the first symptom that a Singleton is the wrong tool.

  • Can’t be mocked: singletons are usually concrete classes, and thus it is hard to test code that depends on them.

The solution to that is exposing singletons through a interface,  basically the global instance type’s should be an interface type, not a concrete class.

Concrete singleton:


private static AssetsService _instance = null;

public static AssetsService Instance
{
	get
	{
		if (_instance == null)
		{
			_instance = new AssetsService();
		}

		return _instance;
	}
}

Singleton through interface (BEWARE: Dangerous Setter):


private static IAssetsService _instance = null; // Interface

public static IAssetsService Instance
{
	set  // BEWARE: DANGEROUS SETTER HERE <<----!!!!!
	{
		_instance = value; // allows mocking for testing.. a bit dangerous.
	}

	get
	{
		if (_instance == null)
		{
			_instance = new AssetsService();
		}

		return _instance;
	}
}

Image showing a Setter dog, a obvious word play that I hope will help remember you to not use setters over static Singleton instances.
Dangerous Setter looking at you. Courtesy from Wikipedia.

Let’s see how to deal with the last points

  • Globally accessible: if we are using Singletons, we are implicitly accepting they are globally accessible, Singleton state could be changed at any point of the program.
  • Tightly coupled with our code: When we use “Something.Instance” inside our code, then our code is tightly coupled to the existence of “Something.Instance”, and tightly coupled code is harder to change.

There is no one preventing us from accessing the Singleton instance once we have it. We just need some discipline about its usage. Luckily todays IDEs have pretty powerful refactoring and search tools. In example in Visual Studio we could find all the places where a Singleton is used:

find-references-singletons

And then refactor get rid of all the “Something.Instance” that infect our code and move towards a more proper solution: Constructor Injection.

Before:

public class StationWagonFactory: ICarFactory
{
	public ICar Create()
	{
		// tightly coupling over "Instance"
		var prefab = AssetsService.Instance.Load("StationWagon");
		var car = Cloner.Instance.Clone(prefab) as ICar;
		return car;
	}
}

After:

public class StationWagonFactory: ICarFactory
{
	// we no longer know AssetsService and Cloner are singletons...
	private IAssetsService _assets;
	private ICloner _cloner; //... even better we access them using a interface

	// if later we need to drop the Singletons =&gt; we don't have to touch this class
	public StationWagonFactory( IAssetsService assets, ICloner cloner)
	{
		// constructor dependency injection
		_assets = assets;
		_cloner = cloner;
	}

	public ICar Create()
	{
		var prefab = _assets.Load("StationWagon");
		var car = _cloner.Clone(prefab) as ICar;
		return car;
	}
}

At this point you can mock your class easily: good-bye dangerous Setter! 

Final recap

As long as we don’t abuse Singletons we could allow their usage in our code, the most important part is to understand why they are evil so that we can deliberately choose when and how to use them. Using too much Singletons turns our code into a mess, instead we should try to use as few of them as possible, and where we want to save us some typing they are needed, Inject them through constructor using their interface type.

The reason to accept existence of Singletons is that there are places where Singleton usage makes code much more easy to understand and faster to write. In example in Unity3D there are many good frameworks that have to resort to Singletons usage, because otherwise they would simply become much more harder to use. Just to name one: DOTween.

As you can see everything in DOTween is accessed through static methods and a Singleton, however you will also notice that DOTween is not dependent on other global stuff. Its author did a pretty good framework (Actually one of the few frameworks that should be present in every Unity3D project), but for doing so, he used a Singleton.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s