Sunday, November 14, 2010

Do I really need a Singleton?

Recently I have published a post on "Static Vs Singleton". While working on the topic, I slipped into another: “Are Singletons really that bad?”. I started reading further. Trust me, it’s a holy war! And here is the result of my investigation.

To start with let’s take a look of the definition of the pattern. Singleton as a pattern provides two functionality:
1. Global access to an object
2. Only one unique instance of the object across the system (in some cases, limited number of instances)

So, what is bad about Singleton? Why Singletons are so bad?

1.  In a Singleton, we have a private static final instance of that class and we provide a public static getInstance() method to access that instance. This means that the instance can be accessed/used from any where under the Sun. A developer can use the instance within a method form any other class just by invoking the getInstance(). He is not bound to declare the dependency in the method signature as he is not explicitly passing that instance through the arguments. Does not this create unwanted dependency and close coupling? Yes, it does. The worst thing is ONLY the programmer who has created the dependency knows about it, but the user of the method who came later never notices it as the dependency is not explicitly mentioned. So, it is very easy to get a Singleton, use it and then forget it for the time being. Most of the programmers (including me :-)) goes on using it almost every where creating a hidden chain and finally cycle of dependencies. When the bubble bursts, its too late. Only option left is to refactor the code heavily. So, the first point - Singletons expose a global variables and global variables creates unwanted dependencies.

2. By this time it is clear that use of Singleton creates a very tight coupling between it (the Singleton) and user who uses it. This tight coupling makes it difficult to test the user alone. If I want to test the user, the Singleton has to be tested also (I have to first create the Singleton and then test the user - maintain a particular order). But, that ‘s not what I am supposed to do! Ideally the singleton should be passed in the user classes’ constructor as a parameter (or in the method as an argument in case a method is being tested). This way, the tester can easily make a mock of the Singleton and pass it as a parameter or argument.

3. Another accusation against the Singleton is that it violates the Single Responsibility Principle. A Singleton class holds the business logic as well as it’s own creation logic. But the SPR principle states that a class should have one and only one responsibility. To be strict enough, one of the responsibilities should be moved out of the Singleton class.  

Point number two of Singleton definition doesn't  have a problem. There may be a number of real use cases where only one instance (or limited number of instances) across the system is required. But, the big question is can I have a single instance without exposing it globally? Dependency Injection is the answer. Let the Singleton be created during the initialization of the application and then pass that unique instance downwards (from the top layers to the bottom) as parameter/argument to all the objects those need it. The getInstance() method should be used ONLY when it is necessary. This is a much cleaner approach.

As per my understanding, the primary purpose of this pattern is to provide a system wide single instance. Global access is secondary. Otherwise, the name of this pattern might have been Globalton! Use it properly and ONLY when it is really needed. But finally, I believe avoiding it would be better than abusing it.  Don’t you think so?

The last WARNING is applicable also for me  :-)

Further Reading:
1. StackOverflow.com
2. Why Singletons Are Controversial
3. Root Cause of Singletons
4. Singletons are Pathological Liars
5. Inversion of Control Containers and the Dependency Injection pattern

18 comments:

  1. I too agree with your point of view but in some cases they are inevitable..plus cloning is other problem and when threads come into picture...boom!!! disaster.... if not taken care properly....

    Reflection seems to be other thing...

    ReplyDelete
  2. Good Article Arnab. I could relate to the issues you mentioned while refactoring the code, where Singleton is heavily used. Testablity of code is very important for sustainence of business applications where changes are always made. If singleton creates problems with testablity, then one should use it carefully.
    keep posting.
    Sandeep

    ReplyDelete
  3. The anti pattern is implementing a singleton with static. The concept of singletons itself is sound and useful, and the best way to implement is to use a dependency injection framework such as Guice.

    ReplyDelete
  4. @Cedric, yes you are right. The problem with Singleton lies in the way it is being used (abused) in most of the cases.

    ReplyDelete
  5. I'm a novice developer that came across your post that wants a better understanding of singletons..but after reading your post I have the following question.

    So by using a Singleton in a method, it makes the method tightly coupled to the Singleton. You also create a tightly coupled relationship when you create new instances of a class inside a method too correct?

    So if creating tightly relationships are bad for testing..when should you create instances of an object inside a method vs passing it into the method or the constructor?

    ReplyDelete
  6. @ Glide
    Yes, you are right. Both of them create Tight Coupling. But, IMHO, passing the parameter is always better than instantiating an object directly within the method. Let's try to find out the disadvantages of "direct instantiation inside the method code" approach.

    class Test {

    public void m(A a, B b) {

    //Do A specific thing
    //Do B specific thing
    C c = new CImpl();
    c.doSomething();
    }

    //setter methods for A, B
    }

    1. Tomorrow, if m() needs a different version of C (say CImpl2), the code has to changed completely. But, the same is not true for A/B (Here A, B are interfaces). Any concrete implementation of A/B can be passed as a parameter and depending on that the behavior of m() would change. As far as C is concerned, here we are programing to implementation and not to interface - which should be strictly avoided. It is very easy to create dependency, but reverse is always difficult.

    2. I want to write test code for m(). First, if C belongs to a Project other than A/B, the test code will not compile. Tester will not know about dependency on C, unless he goes through the implementation of m() [Hidden dependency]. Next, For A/B, light weight mock objects can easily be created only for test. But, that is not possible for C. To test m(), now CImpl has to be tested first, which may not be acceptable always.

    ReplyDelete
  7. @Arnab Biswas

    I agree with everything you said and it makes sense, but I do have a question though. Object A and B have to be instantiated SOMEWHERE, so how do the two points that you mentioned apply for whichever method ends up creating A and B.

    So is the only way we can achieve total decoupled relationships to use an IoC/Dependency Injection framework? Or, are there other solutions?

    ReplyDelete
  8. @ Glide

    Thanks for coming back with your doubts. :-)
    First let me answer your questions:
    a. Yes, somewhere A,B,C has to be constructed (new() operator has to be called)

    b. Again, Yes, Dependency Injection is the best way to do so.
    The “concept” DI is all about two things:
    1. Providing an object it’s dependencies without violating point 2.
    2. Application logic should be separated from object creation.
    Let me expand my previous example code to explain it in a better way.

    class Test {
    Test(A a, B b, C c) {
    this.a = a;
    this.b = b;
    this.c = c;
    }

    //app logic
    public void m() {
    //Do A specific thing
    //Do B specific thing
    //Do C specific thing
    }
    }

    class TestCreator {
    public Test createTest() {
    return new Test(new AImpl3(),
    new BImpl2(), new CImpl3());
    }
    }

    class Main {
    public static void main(String args[]) {
    Test test = new TestCreator().createTest();
    test.m();
    }
    }

    I have separated out the application logic(Test.java) from the object creation (Factory - TestCreator.java). Tomorrow if I need different implementations of A,B,C I have to only change the factory, not the application logic OR if I m() start depending on a new object D, then I have to have a new constructor for Test taking D in addition to A,B,C.
    Finally, If dependency injection framework (e.g Spring, Google Guice etc) is required or not depends entirely on the size/requirement of the application.

    ReplyDelete
  9. hi , great post . i linked your blog also i love "Globalton" word :).

    ReplyDelete
  10. Indeed a good article. I agree, avoid if possible, but like all patterns, used in the right context it can be powerful and helpful.

    ReplyDelete
  11. It's a problem that comes with the pattern, but the pattern itself is pretty solid, proven useful and IMO needed..

    I also think it's mainly used as utility for stateless helper classes, instead of insuring that only one instance can exist of a resource. Which I think is bad coding in alot of cases.

    ReplyDelete
  12. Agree with point one.

    For Point 2, just use introspection. Make an helper that just set proper instance of the singleton at the beginning of the test and you are done. So when you made your helper method you end up with a code like :

    UnitHelper.set(MyStaticClass.class, new MyMockInstance(...));

    Of course you can be pedentic and say that instrospection is evil. Anyway you'll have to deal with legacy code and it's better to know how single it is to solve you testing problem with singletons.

    Point 3 is not a point. It is simply being fondamentalist. Anyway your singleton instance can reside in another static class if needed. You can even use a factory to create your singleton instance.

    Dependency Injection is the same thing as a singleton. Just by declaring a field an put in an annotation I have access to everything.

    For separate modules code, i like to explicitely declare with some initialize method with the dependencies I need use the module explicitely. I would still use singleton for access to loging for exemple.

    When I am on the UI/client part, I like to have some sort of context object. The context object has a serie of getters of facade interface you can use to access all the services. There is also the UI context (like list of windows/differents UI parts, access to I18N service or anything you think is revelant and make use of nearly everywhere).

    Why do I use a context object as it break the encapsulation mechanism ? Because in a UI, you end up using everything all the time. All part of the UI will use some service or the other even when you didn't thinked about it. And because it is so conveniant.

    You know OOP principles can't all be satisfied at the same time. It is not a religion. It the designer of the architecture, the developers that have to choose the correct compromise. Don't be too pedentic about some aspect of OOP paradigm.

    OOP say that everything that is related to this object should occurs in this object. But typicaly persistence is done in a DAO or a Data Access Layer. Typicaly, OOP principe say that an object should initialize itself, but it is very common to use dependency injection, singleton or factories to provide some part of the object.

    OOP say that every object should manage everything related to what the object is, but on the oposite say that each object shall deal with only one purpose.

    Reusing code is good and a best pratice, and specialization/generalization is a good way to do that. But then when you have huge class hierachy,changing the code of a base class nearly break half of the tree. And all classes of the hierarchy have to take care of the internal of all the others to work properly.

    ReplyDelete
  13. Good article and detailed explanation about things which really happens in real.
    Although,i have noticed in huge frameworks where it rule that not to use singleton as long as they are not really required as they can be expensive business.Well,these problem can also be addressed by having multithreading programming patterns and considering concurrency utils.Thats the place where frameworks like Spring has the edge and the way they have handled this is awesome and therefore makes developers life easier.

    ReplyDelete
  14. hello nice post on singleton,
    but always remember we should use enum to make sure not more than 1 instance is created. please visit the post

    http://hellotojavaworld.blogspot.com/2010/11/singleton-pattern-am-i-implementing-it.html

    ReplyDelete
  15. Comments received at DZone.com can be found at

    http://www.dzone.com/links/do_i_really_need_a_singleton.html

    ReplyDelete
  16. Singleton is useful pattern you just got to implement it correctly to address issues like thread safety, cloning, serialization, early loading and lazy loading etc.

    Javin
    Why String is immutable in Java

    ReplyDelete
  17. Singleton remains a powerful core java pattern and has its place in between Static utility class and Many framework like Spring now days provide an outofbox implementation of Singleton via singleton scope. Though Singleton seems easy many programmer mess it up when asked write code for Singleton. I have shared view as 10 questions on Singleton pattern in java you may find interesting.

    ReplyDelete