Singletons: good design or a crutch? [closed]
Asked Answered
S

23

69

Singletons are a hotly debated design pattern, so I am interested in what the Stack Overflow community thought about them.

Please provide reasons for your opinions, not just "Singletons are for lazy programmers!"

Here is a fairly good article on the issue, although it is against the use of Singletons: scientificninja.com: performant-singletons.

Does anyone have any other good articles on them? Maybe in support of Singletons?

Scoles answered 15/8, 2008 at 0:39 Comment(0)
C
56

In defense of singletons:

  • They are not as bad as globals because globals have no standard-enforced initialization order, and you could easily see nondeterministic bugs due to naive or unexpected dependency orders. Singletons (assuming they're allocated on the heap) are created after all globals, and in a very predictable place in the code.
  • They're very useful for resource-lazy / -caching systems such as an interface to a slow I/O device. If you intelligently build a singleton interface to a slow device, and no one ever calls it, you won't waste any time. If another piece of code calls it from multiple places, your singleton can optimize caching for both simultaneously, and avoid any double look-ups. You can also easily avoid any deadlock condition on the singleton-controlled resource.

Against singletons:

  • In C++, there's no nice way to auto-clean-up after singletons. There are work-arounds, and slightly hacky ways to do it, but there's just no simple, universal way to make sure your singleton's destructor is always called. This isn't so terrible memory-wise -- just think of it as more global variables, for this purpose. But it can be bad if your singleton allocates other resources (e.g. locks some files) and doesn't release them.

My own opinion:

I use singletons, but avoid them if there's a reasonable alternative. This has worked well for me so far, and I have found them to be testable, although slightly more work to test.

Candlepower answered 15/9, 2008 at 17:38 Comment(5)
The assumption in the first point is quite a leap, usually heap allocation is not how singletons are created (in C++ at least).Phrygian
I'm not sure about that, MadKeithV. There's a standard pattern where a member function, say, MyClass* MyClass::get_instance(), checks a static member pointer, and if it's NULL calls new to allocate (on the heap) the shared instance. How would a singleton live elsewhere?Candlepower
About the downside in C++: take a look at the Meyers singleton.Felty
@Tyler: I just came across below code which supports @MadKeithV view of not using heap for singleton . class MySingleton { public: static MySingleton &getInstance() { static MySingleton instance; return instance; } private: MySingleton(); ~MySingleton(); }; . Ref - https://mcmap.net/q/16875/-c-singleton-classVictualage
Question tag: "language-agnostic". First point in the answer: "globals have no standard-enforced initialization order, ... singletons (assuming they're allocated on the heap) are created after all globals". These are certainly not language-agnostic comments.Extortionary
T
38

Google has a Singleton Detector for Java that I believe started out as a tool that must be run on all code produced at Google. The nutshell reason to remove Singletons:

because they can make testing difficult and hide problems with your design

For a more explicit explanation see 'Why Singletons Are Controversial' from Google.

Thaumatology answered 15/8, 2008 at 2:40 Comment(5)
I suspect it's a stretch to say this 'must be run on all code produced at Google.' (For one thing, they probably use other languages.)Candlepower
I believe Java, Python and C++ are the approved languages at google.Thaumatology
They can also use javascript: steve-yegge.blogspot.com/2007/06/rhino-on-rails.htmlIfni
Google also has an accounting department; does that mean every developer should get one? The decision to disallow certain constructs is a business decision on Google's part that speaks more to their internal environment. No doubt some hand-tuned machine code still gets twiddled with there, but for business reasons not just anybody should be doing so.Marking
Go and read some Google code, they do not live by this rule.Dulcinea
R
31

A singleton is just a bunch of global variables in a fancy dress.

Global variables have their uses, as do singletons, but if you think you're doing something cool and useful with a singleton instead of using a yucky global variable (everyone knows globals are bad mmkay), you're unfortunately misled.

Rousseau answered 15/8, 2008 at 2:12 Comment(2)
global variables...and methods. a global object even...Kor
A singleton doesn't have to be a true global object.Epistemic
G
27

The purpose of a Singleton is to ensure a class has only one instance, and provide a global point of access to it. Most of the time the focus is on the single instance point. Imagine if it were called a Globalton. It would sound less appealing as this emphasizes the (usually) negative connotations of a global variable.

Most of the good arguments against singletons have to do with the difficulty they present in testing as creating test doubles for them is not easy.

Gonadotropin answered 15/8, 2008 at 0:48 Comment(6)
So why should a class ensure itself that it only has one instance? This pretty much defeats the purposes of object-oriented programming.Engineer
Usually you'd want only one logging facility? Or you're wrapping some voodoo dll, and you don't want to make it possible to load the dll twice?Pontiac
@Pontiac but why make that as responsibility of the class it self when it is clearly as system responsibility. (any one instance of the object will work just fine but the system might fail if the only one alive at a time constraint is not met)Placentation
@RuneFS Because I just have to write code once in a class to enforce singleness. If the system was enforcing it, I'd have to write code everywhere in the system to enforce singleness. Much easier to test one class for one specific behavior than 100 different classes to ensure they all reflect that one behavior.Epistemic
@Epistemic you are missing the point. You've placed the responsibility in "a 100 classes" that's not a design that has made it a system responsibility. I'm advocating placing the responsibility in what ever part of the system that's responsible for instantiation (IoC or similar)Placentation
@RuneFS Ah - thanks. I'd been reading more about this and I think I've come to the conclusion that the singleton's only beneficial use is as a compile time assertion that I've only created one of a particular object. Sometime I may use early on in the design/implementation phase as a sanity check, but remove the "singleton" protection once things make sense. I agree with your comment now - I'd concluded that to ensure one didn't hide dependencies, you'd want to pass a reference to the singleton object to user's constructors. And if you're doing that - you don't actually need a singleton.Epistemic
H
23

There's three pretty good blog posts about Singletons by Miško Hevery in the Google Testing blog.

  1. Singletons are Pathological Liars
  2. Where Have All the Singletons Gone?
  3. Root Cause of Singletons
Homelike answered 15/9, 2008 at 17:52 Comment(3)
woow, really interesting stuff, but i want solutions! :-) txnSalgado
I think one of the "solutions" is dependency injection which actually handles the instance injection for you and it reliefs singleton from being a anti-pattern. :) Check out Guice! code.google.com/p/google-guiceHomelike
1. Problem with the first article. You could simply make the singleton a constructor argument and totally solve the problem in the article. 2. Singleton's need not be global. So replace "shared objects" in the article with Singleton and everything still works. 3. It's only when you get to the third article that he hedges all the crap claimed in the first two to say "oh, the bad thing I was referring to is the design pattern where access to the "singleton" is truly global. Well duh. So you've written 3 articles to simply say, globals are bad, especially when used in complex ways.Epistemic
G
20

Singleton is not a horrible pattern, although it is misused a lot. I think this misuse is because it is one of the easier patterns and most new to the singleton are attracted to the global side effect.

Erich Gamma had said the singleton is a pattern he wishes wasn't included in the GOF book and it's a bad design. I tend to disagree.

If the pattern is used in order to create a single instance of an object at any given time then the pattern is being used correctly. If the singleton is used in order to give a global effect, it is being used incorrectly.

Disadvantages:

  • You are coupling to one class throughout the code that calls the singleton
    • Creates a hassle with unit testing because it is difficult to replace the instance with a mock object
    • If the code needs to be refactored later on because of the need for more than one instance, it is more painful than if the singleton class were passed into the object (using an interface) that uses it

Advantages:

  • One instance of a class is represented at any given point in time.
    • By design you are enforcing this
  • Instance is created when it is needed
  • Global access is a side effect
Gittens answered 19/2, 2009 at 22:33 Comment(5)
"Global access is a side effect" I'm glad someone pointed this out. The global aspect is probably the most misused part of a singletonSpent
I bet Eric Gamma's opinion on singletons came from a lot of hard-earned experience.Tellurian
This answer deserves to be on top IMO.Korwun
@Spent I don't understand. How can you use a Singleton without accessing it's global instance and keep the advantages you have linked? Global access is not a side effect.Mensural
@Jeffrey The point might be better referred to as 'global reference'. The original answer states this clearly: "If the code needs to be refactored later on because of the need for more than one instance, it is more painful than if the singleton class were passed into the object"Spent
S
18

Chicks dig me because I rarely use singleton and when I do it's typically something unusual. No, seriously, I love the singleton pattern. You know why? Because:

  1. I'm lazy.
  2. Nothing can go wrong.

Sure, the "experts" will throw around a bunch of talk about "unit testing" and "dependency injection" but that's all a load of dingo's kidneys. You say the singleton is hard to unit test? No problem! Just declare everything public and turn your class into a fun house of global goodness. You remember the show Highlander from the 1990's? The singleton is kind of like that because: A. It can never die; and B. There can be only one. So stop listening to all those DI weenies and implement your singleton with abandon. Here are some more good reasons...

  • Everybody is doing it.
  • The singleton pattern makes you invincible.
  • Singleton rhymes with "win" (or "fun" depending on your accent).
Sum answered 9/9, 2009 at 17:14 Comment(0)
T
8

I think there is a great misunderstanding about the use of the Singleton pattern. Most of the comments here refer to it as a place to access global data. We need to be careful here - Singleton as a pattern is not for accessing globals.

Singleton should be used to have only one instance of the given class. Pattern Repository has great information on Singleton.

Treasurer answered 27/8, 2008 at 1:20 Comment(0)
B
6

One of the colleagues I have worked with was very Singleton-minded. Whenever there was something that was kind of a manager or boss like object he would make that into a singleton, because he figured that there should be only one boss. And each time the system took up some new requirements, it turned out there were perfectly valid reasons to allow multiple instances.

I would say that singleton should be used if the domain model dictates (not 'suggests') that there is one. All other cases are just accendentally single instances of a class.

Bacteriology answered 22/9, 2008 at 11:48 Comment(0)
A
5

I've been trying to think of a way to come to the poor singelton's rescue here, but I must admit it's hard. I've seen very few legitimate uses of them and with the current drive to do dependency injection andd unit testing they are just hard to use. They definetly are the "cargo cult" manifestation of programming with design patterns I have worked with many programmers that have never cracked the "GoF" book but they know 'Singelton' and thus they know 'Patterns'.

I do have to disagree with Orion though, most of the time I've seen singeltons oversused it's not global variables in a dress, but more like global services(methods) in a dress. It's interesting to note that if you try to use Singeltons in the SQL Server 2005 in safe mode through the CLR interface the system will flag the code. The problem is that you have persistent data beyond any given transaction that may run, of course if you make the instance variable read only you can get around the issue.

That issue lead to a lot of rework for me one year.

Ancelin answered 15/8, 2008 at 2:54 Comment(1)
I never understood why people 'love' this pattern so much. I guess it's because it 'allows' you to use global variables, which saves you the trouble of rethinking the design. Except, of course, it doesn't.Frumpish
F
5

Holy wars! Ok let me see.. Last time I checked the design police said..

Singletons are bad because they hinder auto testing - instances cannot be created afresh for each test case. Instead the logic should be in a class (A) that can be easily instantiated and tested. Another class (B) should be responsible for constraining creation. Single Responsibility Principle to the fore! It should be team-knowledge that you're supposed to go via B to access A - sort of a team convention.

I concur mostly..

Forestaysail answered 23/8, 2008 at 17:22 Comment(0)
G
4

Many applications require that there is only one instance of some class, so the pattern of having only one instance of a class is useful. But there are variations to how the pattern is implemented.

There is the static singleton, in which the class forces that there can only be one instance of the class per process (in Java actually one per ClassLoader). Another option is to create only one instance.

Static singletons are evil - one sort of global variables. They make testing harder, because it's not possible to execute the tests in full isolation. You need complicated setup and tear down code for cleaning the system between every test, and it's very easy to forget to clean some global state properly, which in turn may result in unspecified behaviour in tests.

Creating only one instance is good. You just create one instance when the programs starts, and then pass the pointer to that instance to all other objects which need it. Dependency injection frameworks make this easy - you just configure the scope of the object, and the DI framework will take care of creating the instance and passing it to all who need it. For example in Guice you would annotate the class with @Singleton, and the DI framework will create only one instance of the class (per application - you can have multiple applications running in the same JVM). This makes testing easy, because you can create a new instance of the class for each test, and let the garbage collector destroy the instance when it is no more used. No global state will leak from one test to another.

For more information: The Clean Code Talks - "Global State and Singletons"

Graaf answered 18/2, 2009 at 19:52 Comment(2)
With regard to the cleaning of such objects between tests, why need it be complicated? Why can't the object be destroyed, and a new one spun up in it's place? Having no facility for this is an implementation issue, not a problem with the Pattern itself.Marking
The problem is remembering to always clean the objects after a test. Also since the code may get access to a static singleton from anywhere, it's not possible to see just by looking at the test code, whether some class uses a static singleton, so it's very easy to forget some dependencies. Compare this to dependency injection, where all dependencies must be declared explicitly in the constructor - the code will not even compile if some dependency is forgotten.Graaf
C
3

Singleton as an implementation detail is fine. Singleton as an interface or as an access mechanism is a giant PITA.

A static method that takes no parameters returning an instance of an object is only slightly different from just using a global variable. If instead an object has a reference to the singleton object passed in, either via constructor or other method, then it doesn't matter how the singleton is actually created and the whole pattern turns out not to matter.

Chavers answered 18/2, 2009 at 19:49 Comment(0)
A
2

It was not just a bunch of variables in a fancy dress because this was had dozens of responsibilities, like communicating with persistence layer to save/retrieve data about the company, deal with employees and prices collections, etc.

I must say you're not really describing somthing that should be a single object and it's debatable that any of them, other than Data Serialization should have been a singelton.

I can see at least 3 sets of classes that I would normally design in, but I tend to favor smaller simpler objects that do a narrow set of tasks very well. I know that this is not the nature of most programmers. (Yes I work on 5000 line class monstrosities every day, and I have a special love for the 1200 line methods some people write.)

I think the point is that in most cases you don't need a singelton and often your just making your life harder.

Ancelin answered 15/8, 2008 at 5:22 Comment(0)
A
2

The biggest problem with singletons is that they make unit testing hard, particularly when you want to run your tests in parallel but independently.

The second is that people often believe that lazy initialisation with double-checked locking is a good way to implement them.

Finally, unless your singletons are immutable, then they can easily become a performance problem when you try and scale your application up to run in multiple threads on multiple processors. Contended synchronization is expensive in most environments.

Allograph answered 16/9, 2008 at 10:55 Comment(4)
Anyone care to share the reason for the down-votes?Allograph
Bill, I have to say I wonder too? I don't have much experience, but your point about concurrency issues sounds logical to me?Bailey
What is wrong with using singletons in lazy initialization, where the singleton is a helper for example? I'm not saying you're wrong, I'm just asking.Shovelnose
The problem is in using double-checked locking to initialise them. See en.wikipedia.org/wiki/Double-checked_locking - in Java, for example, the simple double-checked implementation is not thread safe and so may cause difficult-to-diagnose failures.Allograph
U
1

Singletons have their uses, but one must be careful in using and exposing them, because they are way too easy to abuse, difficult to truly unit test, and it is easy to create circular dependencies based on two singletons that accesses each other.

It is helpful however, for when you want to be sure that all your data is synchronized across multiple instances, e.g., configurations for a distributed application, for instance, may rely on singletons to make sure that all connections use the same up-to-date set of data.

Undercut answered 15/8, 2008 at 1:48 Comment(1)
Singletons are mixing responsibilities. To ensure there's ever only X instances of something is a system responsibility to do what ever the functionality of an object is, is an object responsibility.Placentation
M
1

I find you have to be very careful about why you're deciding to use a singleton. As others have mentioned, it's essentially the same issue as using global variables. You must be very cautious and consider what you could be doing by using one.

It's very rare to use them and usually there is a better way to do things. I've run into situations where I've done something with a singleton and then had to sift through my code to take it out after I discovered how much worse it made things (or after I came up with a much better, more sane solution)

Morry answered 15/8, 2008 at 2:50 Comment(0)
L
1

I've used singletons a bunch of times in conjunction with Spring and didn't consider it a crutch or lazy.

What this pattern allowed me to do was create a single class for a bunch of configuration-type values and then share the single (non-mutable) instance of that specific configuration instance between several users of my web application.

In my case, the singleton contained client configuration criteria - css file location, db connection criteria, feature sets, etc. - specific for that client. These classes were instantiated and accessed through Spring and shared by users with the same configuration (i.e. 2 users from the same company). * **I know there's a name for this type of application but it's escaping me*

I feel it would've been wasteful to create (then garbage collect) new instances of these "constant" objects for each user of the app.

Luralurch answered 27/8, 2008 at 18:14 Comment(1)
that's an ok way to do it. The problems come with static accessors for singletons.Tellurian
E
1

I'm reading a lot about "Singleton", its problems, when to use it, etc., and these are my conclusions until now:

  • Confusion between the classic implementation of Singleton and the real requirement: TO HAVE JUST ONE INSTANCE OF a CLASS!

  • It's generally bad implemented. If you want a unique instance, don't use the (anti)pattern of using a static GetInstance() method returning a static object. This makes a class to be responsible for instantiating a single instance of itself and also perform logic. This breaks the Single Responsibility Principle. Instead, this should be implemented by a factory class with the responsibility of ensuring that only one instance exists.

  • It's used in constructors, because it's easy to use and must not be passed as a parameter. This should be resolved using dependency injection, that is a great pattern to achieve a good and testable object model.

  • Not TDD. If you do TDD, dependencies are extracted from the implementation because you want your tests to be easy to write. This makes your object model to be better. If you use TDD, you won't write a static GetInstance =). BTW, if you think in objects with clear responsibilities instead classes, you'll get the same effect =).

Europeanize answered 22/10, 2009 at 5:18 Comment(0)
A
0

I really disagree on the bunch of global variables in a fancy dress idea. Singletons are really useful when used to solve the right problem. Let me give you a real example.

I once developed a small piece of software to a place I worked, and some forms had to use some info about the company, its employees, services and prices. At its first version, the system kept loading that data from the database every time a form was opened. Of course, I soon realized this approach was not the best one.

Then I created a singleton class, named company, which encapsulated everything about the place, and it was completely filled with data by the time the system was opened.

It was not just a bunch of variables in a fancy dress because this was had dozens of responsibilities, like communicating with persistence layer to save/retrieve data about the company, deal with employees and prices collections, etc.

Plus, it was a fixed, system-wide, easily accessible point to have the company data.

Ambrotype answered 15/8, 2008 at 3:40 Comment(2)
I didn't down-vote this, but I would like to explain why someone might have down-voted. Singlton is not the best/only way to cache data. A class with dozens of responsibilities is not "properly" designed.Herd
It sounds like your singleton should have been a separate program entirely. The interface is its service layer.Tellurian
D
0

Singletons are very useful, and using them is not in and of itself an anti-pattern. However, they've gotten a bad reputation largely because they force any consuming code to acknowledge that they are a singleton in order to interact with them. That means if you ever need to "un-Singletonize" them, the impact on your codebase can be very significant.

Instead, I'd suggest either hiding the Singleton behind a factory. That way, if you need to alter the service's instantiation behavior in the future, you can just change the factory rather than all types that consume the Singleton.

Even better, use an inversion of control container! Most of them allow you to separate instantiation behavior from the implementation of your classes.

Donetsk answered 15/9, 2008 at 17:24 Comment(0)
P
0

One scary thing on singletons in for instance Java is that you can end up with multiple instances of the same singleton in some cases. The JVM uniquely identifies based on two elements: A class' fully qualified name, and the classloader responsible for loading it.

That means the same class can be loaded by two classloaders unaware of each other, and different parts of your application would have different instances of this singleton that they interact with.

Pahari answered 17/9, 2008 at 20:4 Comment(2)
If the same class is loaded by two class loaders it's not the same class.Wersh
If the class is loaded by classloaders A and B, but they both implement the same interface loaded by classloader C, then you can pass instances of the class from classloaders A and B to users of C. So the program can use two instances of a singleton at the same time.Graaf
P
0

Write normal, testable, injectable objects and let Guice/Spring/whatever handle the instantiation. Seriously.

This applies even in the case of caches or whatever the natural use cases for singletons are. There's no need to repeat the horror of writing code to try to enforce one instance. Let your dependency injection framework handle it. (I recommend Guice for a lightweight DI container if you're not already using one).

Paramilitary answered 18/2, 2009 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.