Not All Singletons are Evil

by Алекс Руис on March 14, 2011

Among all the object-oriented design patterns, I think Singleton has the worst reputation. They have been called “evil,” “liars” and even “stupid,” and for good reasons:

  • singletons are global access points, making client APIs hide their dependencies on them
  • singletons make testing harder, mainly because they are hard to mock and inject

This is true, but only when Singletons are implemented and used in the “traditional” way:

  1. Singletons cannot be extended (note that the class is final and the constructor is private)

    public final class MySingleton {
     
      private static final MySingleton INSTANCE = new MySingleton();
     
      public static MySingleton instance() {
        return INSTANCE;
      }
     
      private MySingleton() {}
     
      public void doSomething() {
        // something here
      }
    }
  2. Singletons are called anywhere in your code

    public void someMethod() {
      MySingleton.instance().doSomething();
      // keep doing stuff
    }
  3. Nothing is completely evil

    Just like everything else, nothing is completely good or bad. I’ve been using Singletons in the next version of FEST-Assert in a way that avoids the problems mentioned earlier:

    1. Do not make the Singleton final, making creation of mocks from a Singleton possible (BTW, Mockito can mock non-final classes with private constructors.)
    2. Have the Singleton’s constructor package-protected. This is handy if your Singleton depends on other classes that need to be mocked during testing of the Singleton. This way, in your test, you can change the state of a new instance of the Singleton, without changing static state (that is, the state of the Singleton instance of a class.)
    3. Inject Singletons just like any other dependency, completely avoiding the “global access point” problem.

    Sounds good. Show me the code!

    The following code is similar to what we have done in FEST, but a lot shorter and simpler. You can also take a look at the code in the github repository.

    Here is the Singleton:

    public class MySingleton {
     
      private static final MySingleton INSTANCE = new MySingleton();
     
      public static MySingleton instance() {
        return INSTANCE;
      }
     
      @VisibleForTesting MySingleton() {}
     
      public void doSomething() {
        // something here
      }
    }

    Currently, I’m doing manual dependency injection, because I consider the project to be pretty small and I’m trying to keep external dependencies to a minimum. Of course, you can (and probably should) use Google Guice :)

    public class SomeClient {
     
      @VisibleForTesting final MySingleton mySingleton;
     
      public SomeClient() {
        this(MySingleton.instance());
      }
     
      @VisibleForTesting SomeClient(MySingleton mySingleton) {
        this.mySingleton = mySingleton;
      }
    }

    As you may guessed by now, the constructor SomeClient(MySingleton) is used in tests, passing a mock MySingleton (and of course I also test that the default constructor uses the Singleton instance.) Any non-test code just calls the default constructor SomeClient().

    Conclusion

    Despite the bad reputation that Singletons have, they can still be pretty useful. As long as Singletons are:

    1. extensible
    2. injected, and
    3. do not have static mutable state (state by itself is not bad)

    they are as good as any other tool.

{ 10 comments… read them below or add one }

Rogério March 14, 2011 at 1:48 pm

You can also mock the original “MySingleton” class quite easily, using the JMockit mocking API:

@Test
public void justMockIt(final @Mocked MySingleton s)
{
// If needed, record values to return, exceptions, etc:
new NonStrictExpectations() {{
s.getSomeValue(); result = “desired value”;
}};

// In tested code, entire singleton is mocked/stubbed:
MySingleton.instance().doSomething(); // stubbed out

// If desired, verify invocations at the end:
new Verifications() {{ s.doSomething(); }};
}

Reply

Stuart Marks March 14, 2011 at 8:29 pm

Hi Alex! Nice post. A question: after you’ve made all the changes you’re recommending, do you really have a Singleton any more? According to the GoF book, the intent of a Singleton (capital S) is: “Ensure a class only has one instance, and provide a global point of access to it.” It seems like you’re explicitly recommending against a global point of access (indeed, you refer to a global point of access as a problem) preferring injection instead. I agree! It seems to me that according to the GoF definition, the global point of access is essential to being a Singleton. So, you’ve fixed Singleton, but maybe you no longer have a Singleton anymore. If you want to call it a Singleton, that’s fine with me (though you might get some argument from GoF purists.)

To me, the essential point is whether the clients know whether the object they’re depending upon is a unique instance. Baking that into an API used throughout a system (global point of access) seems like a mistake. It seems preferable to have the dependency be injected or passed as a parameter or something, and clients don’t know or care whether they’re dealing with a unique instance, where it comes from, or who creates it.

Reply

Alex Ruiz March 14, 2011 at 8:51 pm

Hey Stuart!

I agree with you. I still want to call what I described a Singleton. It still has a global point of access (at least for non-test code.) What I have changed is where this global point of access is actually being called. This is, of course, my opinion. Like Obi-Wan said “many of the truths we cling to depend greatly on our own point of view.” :)

-Alex

Reply

Alexander March 15, 2011 at 3:23 am

Guten Tag Alex!

I supposed to think, that folks who’s really pondering a Singletons only like a stupid / evil, don’t take a closer look at the “Effective Java” book by Joshua Bloch (must to read for everybody). Hence, they maybe a proud C++/C# developers who’s still don’t understand what Java is and how to operate with it properly. Nonetheless, very good post Alex! Keep it up!
Despite “stupidity” of Singletons pattern, I have a small question: did you noticed a big problem of Google Guice to deal with Java Generics. It’s a nightmare…. how to circumvent it?

Reply

Alex Ruiz March 15, 2011 at 6:29 am

Thanks Alexander!

I haven’t gotten hit by the problem you mentioned yet. But! I’ll be using Guice in the project I mentioned in the post. If I find a solution I’ll let you know :)

AFAIK, Guice uses Neil Gafter’s “super type tokens” ( http://gafter.blogspot.com/2006/12/super-type-tokens.html ) to overcome the Generics problem.

Cheers!

Reply

Alexander March 15, 2011 at 12:24 pm

Just want to say you thanks for this link! Super helpful :)

Reply

Frank Smith March 15, 2011 at 3:47 am

This approach has some benefits, but it basically changes singletons from being evil to just being a very dubious technique. There are a few use cases where a singleton is beneficial, but in a majority of cases it’s a code smell and usually represents programmer laziness or ignorance. Making a singleton testable doesn’t eliminate the essential problems of global access (as you acknowledged). In your SomeClient class, for example, the class still depends on the global point of access and cannot be compiled or run without it when it could only depend on the abstraction implemented by the singleton class. Ironically, assuming the developer is using a dependency injection framework, it requires more effect to make the classes less flexible and reusable. I think the article would have been more useful if you discussed the use cases where singletons are either required or the benefit of using them outweighs the problems they cause.

Reply

Alex Ruiz March 15, 2011 at 6:32 am

Thanks Frank for the feedback.

I agree with you, I should have explained why I am using Singletons. I originally thought about it, but later on I also thought it may add noise to the post. I guess I was wrong :)

I’ll be writing a follow up shortly explaining a use case for Singletons, with pros and cons.

Cheers!

Reply

Fredrik March 21, 2012 at 2:06 am

Isn’t this really a case of using the Singleton scope rather than design pattern? You’re not after a JVM-enforced single instance, but rather to reuse the same class multiple times, right? So if you were using for example Guice, you could just write a regular class (no static field required) and annotate it with @Singleton.

It’s the design pattern people hate on, not the scope (usually). The scope alone doesn’t prevent easy testing.

Reply

codematrix August 5, 2012 at 6:57 pm

It’s not that singletons themselves are bad but the GOF design pattern is. The only really argument that is valid is that the GOF design pattern doesn’t lend itself in regards to testing, especially if tests are run in parallel.

Using a single instance of an class is a valid construct as long as you apply the following means in code:

1. Make sure the class that will be used as a singleton implements an interface. This allows stubs or mocks to be implemented using the same interface

2. Make sure that the Singleton is thread-safe. That’s a given.

3. The singleton should be simple in nature and not overly complicated.

4. During the runtime of you application, where singletons need to be passed to a given object, use a class factory that builds that object and have the class factory pass the singleton instance to the class that needs it.

5. During testing and to ensure deterministic behavior, create the singleton class as separate instance as either the actual class itself or a stub/mock that implements its behavior and pass it as is to the class that requires it. Don’t use the class factor that creates that object under test that needs the signleton during test as it will pass the single global instance of it, which defeats the purpose.

We’ve used Singletons in our solutions with a great deal of success that are testable ensuring deterministic behavior in parallel test run streams.

codematrix

Reply

Leave a Comment

Previous post:

Next post: