Home > Design > Singleton Considerations

Singleton Considerations

I started out writing this post as a series of comments on StackOverflow but I decided there just wasn’t enough room to discuss this.

The original question is titled “What is so bad about Singletons?” and can be found at StackOverflow here. The answer receiving the most upvotes was:

Paraphrased from Brian Button:

  1. They are generally used as a global instance, why is that so bad? Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a code smell.
  2. They violate the Single Responsibility Principle: by virtue of the fact that they control their own creation and life-cycle.
  3. They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases.
  4. They carry state around for the lifetime of the app. Another hit to testing since you can end up with a situation where tests need to be ordered which is a big no no for unit tests. Why? Because each unit test should be independent from the other.

1:

I agree with him on that. In cases, where such a dependency is not obvious by the classes name, the dependency should be injected. Injecting Singleton Instances into classes proves a wrong usage of the pattern.

2:

All Objects need to control their life-cycle in a way. All objects need to have a constructor/destructor. This is even more true in non-managed languages such as C++/Objective-C where you are responsible of releasing your collaborators (Java and .NET programmers tend to forget that).  A Singleton’s life-cycle is assumed to be the same as the application’s, so I don’t see the need to “control” that here. Most Singleton implementations are using a lazy-load mechanism to instantiate themselves. This is trivial and their life-cycle is unlikely to change, or else you shouldn’t use Singleton.

3:

The GoF Singleton Pattern description includes the following: (p.128, Consequences 3.)

Permits refinement of operations and representation. The Singleton class may be subclassed, and it’s easy to configure an application with an instance of this extended class. You can configure the application with an instance of the class you need at run-time“.

Contrary to static classes, Singleton Instances are normal classes and can therefore inherit from base classes and/or implement interfaces. In order to make a Singleton Instance swappable, you can either choose to inject (“initialize”) a “to-be-Singleton Instance” into the Singleton or lazy-load it based on some configuration info. Throwing exceptions on requests made before the Singleton Instance was initialized (and optionally, when an attempt is made to reinitialize it) ensures the same semantic behaviour as that of a simple Singleton Class. Eventually, this is no different from how an IoC Container would deal with Objects whose lifetime shall be that of a Singleton.

4:

If your Singleton carries a significant global state, don’t use Singleton. This includes persistent storage such as Databases, Files etc. Note that log files are an exception to that. In most cases their state isn’t significant for the behaviour of the Application. Good examples for the usage of Singletons are PrintSpoolers (fire and forget).

Advertisement
Categories: Design
  1. runefs
    August 25, 2010 at 14:42

    Your point 1 and 3 contradicts each other. In 1 you say there’ no life time management or trivial management because it’s the application life time but in 3 you introduce exceptions to be thrown when the Singleton is expected to exist but doesn’t aka when there’s a life cycle management error.

    AD 1 & 4) How would you name a singleton for a PrinterSpool so that it’s obvious that the class called “BusinessReports” depends on it? (BusinessReports depends on PDFViewer that in turn depends on Printer for printing purposes and Printer depends on PrintSpool)

    How would you inject a singleton? Remember no one but the singleton can create it. If some one else can create it it’s no longer a Singleton (some other instance is controlling the number of created instances)

    Deriving from Singleton breaks the Singleton-ness (implementing an interface in a singleton class does not)
    “and optionally, when an attempt is made to reinitialize it” is no option since not throwing would result in at least two “singletons”

  2. sleeplessnerd
    September 5, 2011 at 02:44

    Passing stuff in isn’t really that hard. I dont see the benefits other than not having to explicitly declare the dependency and therefore being able to change stuff after designing the api.

  3. June 28, 2012 at 01:08

    Interesting discussion, just stopped by from SO thread to say thanks for sharing your thoughts on this topic.

  4. funatlearn
    January 15, 2013 at 18:08

    To the point no. 3, How would you inject singleton instance from DI/IoC? A standard singleton implementation does not allow public constructors (which are needed for majority of Di/Ioc)

    • Vaeth
      January 24, 2018 at 05:00

      There are a number of frameworks that do just this. Spring Beans for example are singleton by default but they’re still registered for autowiring

    • Vaeth
      January 24, 2018 at 05:02

      In addition to, the “new” singleton uses enumeration to enforce single instance, not private constructors

  5. November 10, 2013 at 13:05

    >> How would you inject singleton instance from DI/IoC?
    Having single instance globally is called Singleton.
    Having a private constructor enforces this above rule. It doesn’t need to be enforced, if you use dependency injection (DI) properly.

  6. SapoChule
    September 29, 2014 at 16:27

    You really shot off target on 2:[ All Objects need to control their life-cycle in a way. All objects need to have a constructor/destructor. ] – A constructor and destructor defines HOW the object is constructed/destructed. Object life-cycle is WHEN the object is constructed and destructed. No, objects shouldn’t control their life-cycle, no no no no, stop advocating the use of the Singleton, it makes writing unit tests as painful as birth

  7. xrutv
    October 24, 2014 at 16:25

    @SapoChule, no need to get so melodramatic in a discussion about coding practice. Just because you have had a negative experience with singletons doesn’t mean that there’s no valid use case for them.

  8. August 9, 2016 at 07:57

    Singleton is a baggage. Experienced programmers know intuitively know when it’s OK to use a singleton. In Ruby, Configuration class is very often a singleton. Yes you need to know about `Configuration.config` in order to access it, but you can also hide this implementation behind a simple helper that returns Singleton. This way you can easiliy mock the helper in tests, and not suffer any of the negatives. So I would say that generally I do not see any issues with testing singletons, or classes that depend on them, and faking or mocking any part of that dynamic.

    Having said that, I also naturally don’t add singletons all over the place. It would be unusual for a project of mine to have 2+ classes implement singleton pattern. Mostly it’s for configuration related stuff.

    PrinterPool in the example below would NOT be a good example for singleton, because who says that there can only be one and only one at any point in time, including future? Nobody. You might use multiple PrinterPool configurations per printer, and have many printers configured. This is a great example where an inexperienced programmer who implements PrinterPool as singleton, will likely end up rewriting it very soon into a non-singleton class, that can be instantiated and passed around as a dependency.

  9. slyy2048
    September 7, 2016 at 11:54

    3 & 4. points against Singleton seem like wrong test-design pattern.
    If they don’t like singletons, they should stop making the app instance as singleton.
    Some kind of class MyApp : TestAPI would make testing still possible.
    With kind of paging – turn another page if need another set of global state.
    Globals* g_pGlobals; // including also “single-instance”s of singletons (non-static)
    main() {
    g_pGlobals = Globals::I(); // get current instance for “global” variables
    testOldVersion();
    Globals::next();
    testOptimized();
    pGlobals->compare2prev(); // compare global states of 0 and 1 after testing
    }
    Tests should not affect application. Choosing a design-pattern for testability would cause impact on performance even after testing is finished. If performance is priority, having to write more complex tests is part of performance tuning.

  10. Vaeth
    January 24, 2018 at 04:59

    The issue is how readily used Singletons are because they seem like a quick answer to a short term issue. However, they are difficult to mock for testing when necessary and not scaleable, leading to larger issues if not used properly.

    Nowadays the use case of a singleton often involves injecting it or chaining its dependencies. DI makes singletons more testable, and that should be a point of agreement for why to use DI over just singleton.

  11. October 28, 2018 at 17:30

    1. Agreed.
    2. This is a grey area where people will swing one way to another in the same day, some are more religious about it. What really matters is simply the expectation of the calling code, do I expect a singleton, or not, or doesn’t it matter? Define that by considering calling code.
    3. Yeah there’s a mix up between Singleton and Static there. A miscommunication.
    4. That shows a misunderstanding of Static and Singleton again, you can inject and mock a singleton, not a static. Technically if you provide a Setter for the singleton, you can even use a static one in your unit tests! But wait, he’s saying “state between tests”. Why are you not mocking out the inputs for every single dependency call in your “unit test”? Each test should be a test for each thing the method does, including checking for correct parameters being passed, correct dependency method calls correct number of times, and and then you start the next test where you mock the result of the previous dependency call. Rinse and repeat.

    Rant rant rant. Singletons are GOOD, if you use them PROPERLY.

  12. Alexander Sitnikov
    June 15, 2022 at 20:29

    Thanks for your thoughts! I use singletons from time to time and see no issue with that. Also, an interesting observation is that you can create a sole instance through the DI and inject everywhere, but that might just be confusing….

  1. August 8, 2013 at 13:01
  2. November 5, 2016 at 20:41
  3. May 2, 2017 at 23:56

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 )

Connecting to %s

%d bloggers like this: