10 ms·
So Singletons are bad, then what?
- herge 13y agoThe big issue with singleton is that every time you have one db connection, one cache store, one file store, one of anything, you wind up needing a second one. Make it easy to use the default one, but also make it easy to swap it out and use a different one.
- pmelendez 13y ago>" you wind up needing a second one" And by that moment it is not a singleton any more. The other way around is also true, you design your system to be scalable in db, cache store, etc. and you end using only one.
- masklinn 13y ago> And by that moment it is not a singleton any more. That's the point. If it's originally a singleton and you need a second instance, you're going to have a hard time. If it's a regular factory/object and you only ever use a single instance, chances are nothing will care (much, it may let some concurrency bugs or global state creep in)
- pmelendez 13y ago>". If it's a regular factory/object and you only ever use a single instance, chances are nothing will care" That's true, although if it is a single instance but not global then you are not enjoying the benefits of the guaranteed of an unique instance. A well used singleton is a great tool that simplify things a lot.
- masklinn 13y ago> A well used singleton Something which I've come to believe does not exist, the pattern itself is broken. Thus, > singleton is a great tool no. > that simplify things a lot. Paraphrasing Mencken, for every complex problem there is an answer that is clear, simple, and wrong. Singleton is ever that answer.
- pmelendez 13y ago>Something which I've come to believe does not exist, the pattern itself is broken. >Paraphrasing Mencken, for every complex problem there is an answer that is clear, simple, and wrong. Singleton is ever that answer. Just because you haven't found a good use it doesn't mean it doesn't exist. And about Mencken... All he said is that you can't have Singletons without having a Global State (obvious) and apparently he has an strong allergy to global states. Global states are fine. Sure, they will make your tests harder but there are a lot of software that don't use unit test for legitimate reasons and hence don't have that problem.
- Nursie 13y agoOne of these things is a problem you need to fix the other is a solution to a problem you don't have. It's not usually good to over-engineer or over-spec, but I'd rather have a little bit of that than a whole lot of software that can never scale.
- pmelendez 13y ago>"One of these things is a problem you need to fix the other is a solution to a problem you don't have." That's true, but there are so many cases were a singleton is way more convenient than the alternatives, and not using it because it might "potentially" need to scale but never does sounds a bit silly to me. I am agreed though that you must be clear on the specifications, if a shadow of doubt appears is very to play it safe.
- eludwig 13y agoReligious wars against particular design patterns just seem so, well, religious! To me, a singleton is a particular implementation of a global variable. Nothing more. You use it one when you need one. It isn't magic or evil. It's a global variable. The problem comes in when you are using one but don't know it. It's the beginner Spring problem. Developers don't realize that some libraries use them by default and start storing state there. Needless to say, not good.
- fhd2 13y ago> To me, a singleton is a particular implementation of a global variable. Except that it's not. Global variables aren't initialised lazily, and their type can be an interface just fine. I can think of a few valid use cases for singletons, but it's not a great replacement for global variables IMO. Service locators are closer, and I think they have far more valid use cases than singletons.
- dllthomas 13y agoIsn't that basically "A singleton is a particular, better implementation of a global variable"? Does "global variable" imply a primitive type?
- eludwig 13y agoA getInstance() call can return a pre(statically)-initialized instance if it wants to. Laziness is optional. The pattern gives you the freedom to do it either way. Maybe not so in all languages?
- masklinn 13y ago> Except that it's not. Global variables aren't initialised lazily Depends on the language, and the global. In java, a static attribute is initialised when the class is first used. Until the class itself is accessed and used, the attribute remains uninitialized. In clojure, delay[0] will invoke (and cache) its body the first time it's deref'd. [0] http://clojuredocs.org/clojure_core/clojure.core/delay http://clojuredocs.org/clojure_core/clojure.core/delay
- 13y ago
- lazydon 13y agoSingletons are always a lazy solution to the problem. For me the rule of thumb is if there's some class requiring lots of work to test, I've been lazy. So, go back and review my sloppiness. The questioner was in a way implementing a poor man's cache using Singletons (I wonder how was he planning to test it); some use it for connection pooling instead of a specific library. I've heard even GoF regretted including Singletons in the s/w patterns club. I'm a big fan of Misko Hevery's (now working on Angular) work on this. http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/ http://misko.hevery.com/2008/08/17/singletons-are-pathologic... http://misko.hevery.com/2008/08/25/root-cause-of-singletons/ http://misko.hevery.com/2008/08/25/root-cause-of-singletons/ http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/ http://misko.hevery.com/2008/08/21/where-have-all-the-single... I miss this guy in Java world.
- brown9-2 13y agoI really loved Misko's blog back in the day, and these are the exact articles I always quote to people when they ask "why is the singleton pattern a bad thing?".
- ehutch79 13y agowait. isn't angular full of singletons? I mean that's what a service is in angular. I just wrote like three of them.
- supermatt 13y agoAs the author would say: singletons (single instances), yes. Singletons (as in the pattern), no. In his articles, it appears that he uses the word 'singleton' to mean 'Singleton' though, which is mildly annoying.
- seanalltogether 13y agoSomething is bugging me about the examples he's using there, I've never seen singletons used that way. these are just static initializers. testCreditCardCharge() { CreditCardProcessor.init(); CreditCard c = new CreditCard( "1234 5678 9012 3456", 5, 2008); c.charge(100); } Instead I would expect a singleton to be used this way. Which takes care of initialization where its needed. class CreditCard { private number; function charge(amount){ processor = CreditCardProcessor.getInstance(); processor.go(number, amount); } } I'm not saying this is better way to process this datamodel, but it is the correct way to use a singleton.
- csmithuk 13y agoSingletons are fine. It's just some idiots plug everything into them then realise they've blow their toes off with a monolithic ball of mud architecture. I use a singleton on every project which is OO based but it only ever holds the service locator/container. Asp.net MVC is a fine real world example of how to fuck up Singletons (routing dictionary, global action filters etc). Totally stinks and is coupled like glue.
- mattgreenrocks 13y ago> I use a singleton on every project which is OO based but it only ever holds the service locator/container. iOS devs love singletons; it seems like almost everything is a sharedSomething. Definitely a design smell. Infrastructure can sometimes call for a singleton. It's very convenient to have something that is only created when it is needed. That way, users only pay for what they use, and they don't have to bear the conceptual burden of toting an extra context object around. But it is a sledgehammer, and the people most inclined to abuse it lack the ability to tell the damage it is doing to the design.
- frou_dh 13y agoIt's mildly interesting to note that in practice essentially every GUI application on OS X is a singleton because the OS makes a strong distinction between application instances and windows (compared to e.g. MS Windows where the distinction is muddy). Launch TextEdit.app twice and there is still only one running instance of the application. If you want a second window, you open a second window. # instance trivia: $ open -n /path/to.app
- fhd2 13y agoI've been using manual DI a lot (there aren't many reasonable alternatives in C++), and occasionally ran into situations where doing that was insanely cumbersome. Like passing a resource managers down a widget hierarchy. Service locators implemented as singletons have served me well in those cases. They're fairly simple, and share almost all the benefits of DI (as opposed to singletons). Some people have been calling service locators an "anti-pattern" as well, but I'm not buying it. Singletons have very obvious drawbacks and have been incredibly overused, so they sort of deserve that term - even if they have a few valid uses. Service locators on the other hand have very few drawbacks, the only real one I can think of is that dependencies are no longer obvious. Is that really that much worse than throwing complex IoC containers into the mix? (Note that I just recommend service locators as a fallback when manual DI doesn't make sense. I much prefer manual DI generally.)
- humanrebar 13y agoSo what if I need several ServiceLocators: various unit test versions, production, development, etc?
- mikegioia 13y agoI've spent the last few months (casually) testing the differences between the service container and DI container and I've come to the conclusion that it's a stylistic decision. I found that using a DIC and passing references to services to the constructor of every class was just far too cumbersome. Is it clear which services the class uses? Absolutely. But it's also clear if you document the services used before the class declaration. The cited advantage of DI is that it's easier to pass service mocks during testing. This isn't difficult to do with a service locator; as long as you instantiate your services at the beginning of the test you can have full control over mocking certain services on a test-by-test, or group-by-group level. Personally, the added cruft of passing services to every constructor made me want to rip my eyes out.
- Glide 13y agoI am of the school of thought that making relationships explicit leads to better coding practices and use DI via constructor to do so. I think the really important factor though is how mature the ecosystem is in supporting DI. The richness of C# and Java DI container implementations make using service locator patterns dubious. Well and how many ice cold stares you would get by using service locators. I'm trying my hand at iOS development after years of C# and the ecosystem is radically different. On the other hand mocking libraries are a dream in a message passing runtime like Objective-C.
- Pxtl 13y agoI always get cranky about people fixating on the difference between a static class and a singleton. A static class is just your language's default implementation of the singleton pattern, it just fails at providing any polymorphism to swap out the object for a new one. Mechanically, they do the same thing. Single global point of access to some effectively-global-state. Also, the singleton thing (and interfaces everywhere) stinks of YAGNI. Your toolkit can find all references to X.Y, which means you can replace all references to X with a reference to X.Instance.Y. when you need to change a static class to a singleton, do so. Or just use a dynamic language where there isn't any difference. Seriously, I wish C# offered a "root" static class or global variables or something equivalent so that the singleton pattern was less verbose to implement, because you will need them.
- arethuza 13y agoWhat other languages than C# have the concept of a static class?
- jimmaswell 13y agoVB.NET for one. It calls them Modules.
- Pxtl 13y agoOther languages can sport a class full of static methods and a private stub constructor, all C# offers is the means to force a class to only contain static methods and block the constructor. You can make an all-static class in any OOP language that supports class-level methods and members. That's my point. This argument is all semantics. There's a million little ways to create something with the functional utility of a Singleton, and there's no sense in pretending that they're vastly different.
- arethuza 13y agoIt was just idle curiosity - I wasn't familiar with the term "static class", looked it up and wondered if that particular set of features (and the term) were used in any other languages.
- JulianMorrison 13y agoStatic classes and singletons just tell you that the people who shoehorned everything into an OOP paradigm in your language of choice were mistaken, because there are plenty of things that are simpler and clearer as top level functions and data.
- mikegioia 13y agoI think you're right, but wouldn't the alternative then just be namespacing all of your top level functions into separate files? It seems that a static class of related functions is just another way to organize top level functions.
- pmelendez 13y agoIt really depends. I had used singletons when wanted to manage a resource using RAII and have to be easily available across all the applications. My canonical example would be writing on a log but YMMV.
- jimmaswell 13y agoThere's nothing wrong with singletons when they're used when needed. They've been particularly useful in the Unity/C# development I've done on an MMO, both on the client and server. The problems someone listed in an answer haven't really occurred in our use as far as I know.
- mnw21cam 13y agoNot all singletons are "global state". Yes, I agree that using singletons to store global state is a bit dumb. You may as well use static methods and variables. Where a singleton does become useful is as an immutable carrier of methods. No state. It means that an object somewhere can have a reference to a WeirdOperator object, which contains a method called doWeirdOperation(inputs). WeirdOperator would then be an interface or abstract class, and various different operators are implementations, thus effectively allowing methods to be passed around. Consider Comparator (in Java). The alternative is to access methods by introspection, but doing Method.invoke(parameters) is nasty and evil and slightly slower than doing it properly.
- peeters 13y agoWhen classes have no state, there's also really no need to have a singleton instance. If someone wants to instantiate a new object, who cares? It's a few extra cycles and a few more bytes in memory. Sure, you can have an easily accessible instance for convenience and performance, but nothing's going to hurt if somebody uses a different instance. Your program isn't compromised. Singleton exists as a pattern to enforce a single instance because of state and side effects. What you're talking about is just a cached instance.
- masklinn 13y ago> Not all singletons are "global state". Then why have a singleton? > Where a singleton does become useful is as an immutable carrier of methods. No state. Why have a singleton? Just use functions, or static/class methods in KON languages.
- mnw21cam 13y agoCertain languages don't have methods as first class objects which can be passed around. In Java, you can pass around a Method object, but it isn't really the full thing, as calling it is not type safe, and is slower than a real method call. Likewise, passing around a Class object in order to identify a static method to use is equally unwieldy. Therefore, a singleton object can be passed around, and it carries with it the implementation of the method. That allows you to have a variable that effectively references a type-safe fast method, allowing the nearest thing to having methods as first class objects.
- jimmaswell 13y agoHere's a good use of something close to a singleton. Different things will initialize the class, and you want to keep track of the last one initialized, so that's what you assign to the static T Instance. I used this for a component that could be added to something, but the Update function of which should only run for the latest initialization.
- gohrt 13y ago> Different things will initialize the class, and you want to keep track of the last one initialized, In that sentence, only the class is being initialized, so there's nothing to track. What did you mean? "Instantiate", not "initialize" ?
- jimmaswell 13y agoyes, Instantiate. the class's Update had if (Instance != this) return;
- yawz 13y agoSome of the singleton addiction comes from premature optimization.
- camus2 13y agoor the lack of IoC containers.
- mercurial 13y agoThen what? Then you use dependency injection if you think you need a singleton, and inject a single instance of a cache object. Which means you can mock it when unit testing, or make different instances of it if needed, or have different implementations of it.
- jason_slack 13y agoWithout starting a flame war, I use a few singletons in my game and I dont understand why it is a problem. The instantiation of the game, an object that manages layers, HUDS, Preferences and saving game data (it is done in a separate thread). I have also worked places where literally every class is a singleton (practically, not really all) and to avoid the xxx->getInstance()->yyy->getInstance()...... They would use some Defines to shorten typing it all.
- pmelendez 13y ago> xxx->getInstance()->yyy->getInstance() That is weird... wouldn't you just do yyy::getInstance() directly? The whole point of singletons is being global right?
- jason_slack 13y agoWell I think that yyy is a private member variable inside of xxx so maybe that is why the did that? Like: #define GAMELAYERINSTANCE _dir->Instance()->getGameScene()->Instance()->getGameLayerObject()->Instance()
- gohrt 13y agoYou mean getGameSceneClass() and getGameLayerClass(), yes? As in Dependency Injection? object->getInstance() makes no sense, you already have the object!
- jason_slack 13y agoI may be reading this weird. object->getInstance makes no sense? You mean if object is a private member variable? So class _dir contains object as a member variable. _dir->Instance(), already has access to object without doing _dir_Instance()->object->Instance() as an example...?
- pmelendez 13y ago> object->getInstance makes no sense? If getInstance returns an instance of object class, and object is an instance itself, then it doesn't make sense or it is not a singleton. You can think it like this: if object class has one unique instance, then object == object->getInstance(), so in your case either object != object->getInstance and they are from the same class (hence it is not a singleton) or they are from different classes (once again then, it is not a singleton).
- martian 13y agoA great talk on the topic is this one. The basic argument is that global singletons (and global state generally) is detrimental to maintainability, flexibility, and testability. The talk discusses several strategies for moving away from global-state to a dependency-injected and testable codebase. Video: http://www.youtube.com/watch?v=qKXt9fBDVoY http://www.youtube.com/watch?v=qKXt9fBDVoY Slides: http://www.gostevehoward.com/presentations/20131212-moving-to-wyoming/ http://www.gostevehoward.com/presentations/20131212-moving-t...
- goostavos 13y agoAh, I really enjoyed that talk. Thanks for the link! I've been trying to move into more of a DI style with my code so that it's easier to test. One thing that I'm fuzzy on is where you instantiate everything. In the past, if I have something like a UserSettings kind of structure, I would usually turn it into a singleton. It made it conceptually simply to instantiate it at the start of the program, and then have any other class that needed it to simply do a `user_settings.get_instance()` type of call. If going a DI route, would the UserSettings object be instantied in the program's start, and then simply passed as a parameter to every object that needs it? I tried it out, but it felt a little "off" passing this one object to almost every class that had anything to do with user settings. Is that just what you do when your doing DI?
- sdegutis 13y agoSingletons aren't always bad. I use a few in my Objective-C Cocoa apps to share common behavior. For example in my music player Bahamut[1], I have a singleton for actually playing music. This way, you can have several Bahamut windows open at a time which all control the same music player. Sure, you could store this variable as a property on AppDelegate or some other parent in the object graph, and then either pass it down to each window controller which needs it, or give them access to it, either directly or via delegates or something. But these are all very convoluted compared to having a single class-method in the class itself which returns a shared (static) object. The only caveat is to make sure that you don't introduce race conditions by poor design. For example, don't do stuff in -init on your singleton, and especially don't do stuff that might call other stuff that might access the singleton via the public accessor. Doing so could turn into an infinite loop if -init is called when creating the singleton. (I've done this before.) Instead, just add a new -setup method and call that somewhere in -applicationDidFinishLaunching: or whatever. It's also a good idea to use dispatch_once to create the singleton[2]. EDIT: Of course, these suggestions don't only apply to Objective-C apps, although your entry points and race-condition-avoiding functions will certainly be different in other environments. [1]: https://github.com/sdegutis/bahamut https://github.com/sdegutis/bahamut [2]: https://github.com/sdegutis/bahamut/blob/master/Bahamut/SDMusicPlayer.m#L44-L51 https://github.com/sdegutis/bahamut/blob/master/Bahamut/SDMu...
- sdegutis 13y agoI'm aware that the example provided makes it slightly harder to test, since it's more tightly coupled than other options. It's a trade-off, simplicity over testability. In this case, I manually test my music player object when I make changes to it. So using a simple singleton here makes sense. I find the same true for most GUI controllers. But I'm not willing to get into a debate about whether or how you should test your GUI. I'm just stating how I do things, and it's worked well for me.
- deleted 13y ago[deleted]
- kenrikm 13y agoObjective C land there a specific API interfaces that really should be wrapped in a single instance if you're going to be accessing them a lot because they are costly to make I.E EventKit.
- msluyter 13y agoHaving used Spring for a year or so now, I'm curious what people think of singletons in Spring? Most of the problems noted in the OP (inability to use interfaces, unable to mock, tight coupling, etc...) aren't really problems that I've noticed. For example, if you're autowiring a typical spring bean, as in: @Autowired private Blah blah; You can actually autowire an interface here. Similarly, it's pretty easy to mock these or swap them out in tests. Parallelization is usually handled by not storing private state in a singleton bean. I'm no Spring expert, so I'm not sure what I may be missing, but most of these concerns appear to be less problematic than many suggest.[1] [1] Nothing is perfect, of course. I have noticed problems with spring singletons where a test would basically screw up the application context, causing subsequent tests to fail. This caused some hair pulling until I learned about @DirtiesContext.
- UK-AL 13y agoSpring does it right. This is a IoC container btw, and not unique to spring. This isn't a singleton, but a single instance of a object. You can change the lifetime of an object, by changing a setting in the IoC container. From ApplicationLifetime To SessionLifetime quite easily. That solves the biggest problem of the singleton, which if you ever DO need more than one, it requires a refactoring. I hate singletons, and I'm a iOS developer. So i'm continually mad about misuse of singletons(Working on legacy code).
- masklinn 13y agoThat's not a singleton, that's just injecting the same instance everywhere.
- taeric 13y agoHow is that not a singleton? I can see the argument that dependency injection is better than a factory method. Especially considering the memory model, but I thought this was still a singleton.
- masklinn 13y ago> How is that not a singleton? The way it is normally used, a singleton is a self-managing, globally accessible, single-instanced object (lazy or not). Just having a single instance does not a singleton make.
- jokoon 13y agoI've got to understand how a singleton is better than a global variable
- StevePerkins 13y agoReading and re-reading the StackExchange answer with the most votes, I'm still not sure I get it. It SEEMS like he's saying: [1] Hand-rolling a class around the "Gang of Four" singleton pattern is bad (i.e. tightly coupled, etc). [2] Grabbing a singleton reference from Spring, CDI, Guice, or some other dependency injection framework is awesome (i.e. easier to use inheritance, abstract out some interfaces, inject mock objects into your unit tests, etc). Am I missing something here, or is this entire discussion really no more complex than that (once you scrape away the enterprise-babble)? It's been almost a decade since I last worked on a non-trivial project that wasn't using a dependency-injection framework anyway, so some of this may just be so obvious I haven't thought about it in awhile.
- jdmichal 13y agoThe top answer is basically saying: 1. The "Gang of Four" "Singleton" pattern, meaning stateful functionality that is statically available from anywhere, is broken. It hides dependencies and makes it impossible to uncouple the items for testing. 2. However, the idea of an application needing a single instance of an object, whether it be a configuration or renderer or what-have-you, is quite common. 3. Using "dependency injection" allows use of single instances, without the "Singleton" pattern. Which, to clarify, does not necessarily mean the more magical forms of dependency injection found in systems such as Spring, where you simply declare a variable and it is magically fulfilled later. It can also just be a parameter in the constructor of the dependent object.
- shitgoose 13y agoHilarious! Doing x=C.getX() is bad, but if it is hidden by numerous layers of libraries and monstrous config files, somehow it becomes acceptable. Out of site, out of mind. The fact that global scope bean is essentially a singleton, doesn't seem to bother architecturally inclined crowd - they are too busy admiring sound of their own voice pronouncing words "dependency injection", "mutability" and "coupling". The top answer is a perfect example of what is wrong with IT today. It takes a working solution, declares it wrong and starts piling up classes and interfaces to solve a problem, that was never a problem in first place (OP never said that their singleton-based cache didn't work, he merely asked if there are "better" ways of doing it). So in the end we have the same singleton cache, but hidden behind interfaces ("It makes the code easier to read" - yea, right, easier, my ass! Ctrl+click on interface method and try to read the code), thousand lines xml Spring configs, and other crap that is completely irrelevant, hard to follow and debug, but glamorous enough for SOA boys to spend endless hours talking about it.
- Sandman 13y agoDoing x=C.get(x) is bad because there's no way of mocking C, thereby making unit testing a component that uses C impossible (the unit test will need to use the concrete implementation of C). Using dependency injection as described in the accepted answer, and particularly separating the concerns of C by using several different interfaces allows you to not only mock C, but actually create mock classes each of which is mocking one particular logical subset of C's functionalities. It's easy to dismiss all this as "bloated" and "enterprisey" and people that use this as "architecture astronauts" but in reality, this pattern really does help. Well, at least if you want to be able to unit test your code properly. Otherwise, you might as well just use a singleton object.
- rdw 13y agoI realized recently that the reason that there is no way of mocking C is because of a weakness in the language implementation/design. In Python, it's easy to mock and unit test globals, because in the test you can just overwrite them in the test's setup, and restore them in the test's teardown. You could argue that it's a static vs dynamic typing thing, and I don't know enough to really dispute that, but it seems to me that there's no inherent reason that a static type system can't handle using a different concrete implementation. I think you can do this with Java/C# by doing some library loading trickery, but it'd be inconvenient. And that's the whole point of all this, isn't it? Automated testing is a convenience that saves you from doing manual testing. Unit testing is a convenience that catches test failures before commit rather than during the automated testing phase. Creating the unit test, well, is it more convenient to create 8 interfaces and completely change the way the code is structured, or is it more convenient to mock out the singleton? It depends on the circumstance, I've done both in various languages. It's good to have the option.
- fleitz 13y agoIn theory there is absolutely nothing wrong with singletons. In practice singletons become God objects where hack upon hack upon hack is placed. Eventually to modify a program in a safe way you end up needing to understand the entire program because everything depends on the singleton and the singleton depends on everything else. Singletons like writing an entire program using only global vars are a tradeoff, you tradeoff maintainability and design for performance and ease of (initial) implementation. In the long term maintainability is usually more important than performance and ease of initial implementation.