December 9, 2008

Using Singletons Safely

The singleton is probably the best known of the GoF Design Patterns, it’s also the most controversial. I try avoid using singletons in my code when I can but since the singleton is a very simple but powerful pattern I sometimes sin against the decoupling gods and use one or two of them. Lots of stuff has been written about creating singletons. In this post I want to show you how properly use a singleton and contain most of the damage singletons do.

This post was inspired by a Twitter discussion I had with @LaTtEX who blogs here

First lets talk about all the reasons not to use a singleton. The objection I hear most against singletons is thread safety. The problem here is that if two threads access the the singleton simultaneously when the singleton isn’t created yet the singleton might accidentally create two instances of itself. The naive implementation has this problem and even some solutions that have been suggested like double checked locking aren’t completely thread safe. This isn’t why I dislike singletons though. I think the biggest problem with singletons is coupling.

Singletons are accessed through static methods. Calling a static method couples your code to the implementation of that method so every call to the Instance property or method of a singleton makes your code harder to test and harder to maintain. A call to a singleton by definition has side effects. Usually these are very large, singletons are usually used for resource intensive objects that you only want to create once. You don’t want to be coupled to code with severe side effects.

My strategy for defusing singletons is actually quite simple. Reduce the number of MySingleton.Instance calls. Lets say we have a singleton for logging that we want to use in a repository class, something like this.

   1: public class Repository
   2: {
   3:     public IEnumerable<MyClass> ReadObjects()
   4:     {
   5:         Logger.Instance.LogMessage("ReadObjects started");
   6:  
   7:         // ..code..
   8:  
   9:         Logger.Instance.LogMessage("ReadObjects finished");
  10:     }
  11:  
  12:     public void StoreObject(MyClass anObject)
  13:     {
  14:         Logger.Instance.LogMessage(String.Format("StoreObject {0} started", anObject.Id));
  15:         
  16:         // ..code..
  17:         
  18:         Logger.Instance.LogMessage("StoreObject finished");
  19:     }
  20: }

 

Coupling-wise things can’t get much worse than this. Every time something is logged Logger.Instance gets called making our Repository object depend not only on the Logger class but also on it’s implementation as a singleton. This is not something we want our repository to be aware of. We can easilly make this a bit better by creating the instance once and reusing it.

 


   1: public class Repository
   2: {
   3:     private Logger logger = Logger.Instance;
   4:  
   5:     public IEnumerable<MyClass> ReadObjects()
   6:     {
   7:         logger.LogMessage("ReadObjects started");
   8:  
   9:         // ..etc..

 

The code is a little bit better because I’m not repeating my mistake over and over but I’m still not satisfied. Let’s see how I can improve this even further.

 


   1: public class Repository
   2: { 
   3:     private Logger logger;
   4:  
   5:     public class Repository(Logger logger)
   6:     {
   7:         this.logger = logger;
   8:     }
   9:  
  10:     public IEnumerable<MyClass> ReadObjects()   
  11:     {   
  12:         logger.LogMessage("ReadObjects started");
  13:  
  14:         // ..etc..
  15:  

Here I used the constructor to inject the logger instance into my class. This is a simple concept but it has a big impact on the flexibility of your code. Your classes aren’t aware of how objects need to be instantiated anymore. This makes code more testable and maintainable. You can inject a class that derives from Logger, as long as it works the same as its base class this will just work. Usually I even hide classes that provide a common service like logging or caching behind an interface to decouple usage of instances even more from their implementation.


If you really paid attention you probably noticed that by having the Logger injected into the Repository in its constructor you have made the instantiation of the singleton a bit less lazy. You might never even call ReadObjects and never need the Logger. If you really need instantiation to be that lazy you could inject the Logger as a parameter into the ReadObjects method, I found that usually injecting in the constructor is fine.


You might say that by pushing the call to Instance out of my repository into the code that creates the repository I have only moved the problem somewhere else, and you would be right. But this problem can actually be solved by moving it. As long as you move it in the right direction. I’ve put the code that creates the repository and the code that gets an instance of the Logger together. If you do this for more of your code you’ll end up with creation and usage of your classes nicely separated with all the code that’s responsible for wiring up your application nicely centralized.

No comments:

Post a Comment