10 ms·
Singleton Is a Bad Idea
- 32gbsd 5y agoAn exe is a singleton, a file is a singleton. Most things in a computer are singletons. We have been battling this OOP problem for decades. Memory mapped structure is volitile busy work. There is no perfect design pattern
- nedbat 5y agoI don't know what you mean by "a file is a singleton": I have many files on my computer, and I can open any of them multiple times.
- postalrat 5y agoAnd what happens when all those places you have the file opened want to write or read the file?
- gpderetta 5y agoThey need to use some form if mutual exclusion? Same as for non-singleton objects in a process.
- bdcravens 5y agoIn most cases nothing, the OS or applications will naively read it or write what they believe the current state to be.
- philihp 5y agoYou fclose the handle when you're done, or you create some kind of synchronized semaphore, if you wanna be extra. The issue is really around having multiple handles for writing (not just reading or appending), and the number of times you actually have this problem here is vanishingly rare.
- nedbat 5y agoI'm not saying it's a good idea to open it more than once at the same time, but nothing is preventing me from doing it, so I'm not sure what is meant by, "a file is a singleton"?
- Matthias247 5y agoWhen you start executing a binary, it becomes a procoess. As long as the code in the binary allows for it, there can be multiple instances of it. So a exe/binary is more along of a regular class than a singleton.
- ardit33 5y agoIf two process are modifying the same file.... that file is a 'single object'. So, the Parent's point stays. A process can create its own copy, and do things with it, but eventually it has to load and save it at one single place.
- gpderetta 5y agoThat's exactly the same as a specific non-singleton object instance. Processes have handles that represent open files. The filesystem tree on an unix OS is a better example but that was also been identified as a mistake and there have been attempts to rectify it (namespaces)
- yokaze 5y ago> There is no perfect design pattern There I can certainly agree, but ... > An exe is a singleton, a file is a singleton. Most things in a computer are singletons. I would say you are mistaking the instance for the class. An individual exe/file/... are instances of the abstract concept file or executable. What you are interacting with is usually an instance, not a class.
- 32gbsd 5y agoAnd a singleton is not an instance? Its all the same thing; 1 file, 1 instance. A file has properties, size, data memory, you can copy, paste it, delete it. A file has a type though generic.
- yokaze 5y ago> And a singleton is not an instance? No, a singleton is a pattern that ensures that there is at most a single instance of a class.
- mikece 5y ago> These ways are simpler than the usual gymnastics to implement singletons. Is this a python-centric complaint? I usually write C# and Singletons are just one of a few different scope types for defining objects in the IoC container, no easier, harder, rarer or more common than any other class type.
- emodendroket 5y agoI would consider creating a dependency as a singleton in your composition root different from a "true" singleton, because the latter involves baking the assumption that it will be a singleton into all callers rather than injecting it.
- Matthias247 5y agoI guess so. My favorite problem with singletons is testability. How can you properly mock/observe/etc it inside a test case, if lots of test-cases are executed in parallel. With a real global object it can be tricky. But if the object is not global because an IOC container might still create a fresh one per test, it wouldn't be an issue.
- brtkdotse 5y agoCame here to write this. In .NET it’s easier to just follow the normal DI pattern and inject your desired singleton with AddSingleton<>
- moron4hire 5y agoThe Singleton of .NET IoC containers is not the same thing as the Singleton pattern. It's called a Singleton because the DI controller will make sure only one instance is available. But the Singleton pattern has the class itself making sure it can have only one instance. The mixing of concerns is the problem with the Singleton pattern. With a DI controller, you can change the lifetime of the instance without having to change the class definition itself. With the Singleton pattern, changing the instance lifetime requires changing every utilization site.
- emodendroket 5y agoI prefer the Yegge classic, "Singleton Considered Stupid." https://sites.google.com/site/steveyegge2/singleton-considered-stupid https://sites.google.com/site/steveyegge2/singleton-consider... Though I do admit to occasionally violating my own precepts and using them.
- petilon 5y agoJust wasted 5 minutes reading that page. I didn't see a single worthwhile argument.
- emodendroket 5y agoSorry it didn't meet your standards.
- da25 5y agoI like the way you replied. Cheers
- jw_mc 5y agoI'm interested in this critique. Could be beneficial to others here on HN. Care to elaborate or were you just venting?
- kstenerud 5y agoSingleton is a trick to get around problems in "everything is an object" languages. It's a hack to store global data, just like the alternatives shown in this article. If you need globals and your language supports global data or functions, use that. If not, Singleton is a viable alternative.
- Traubenfuchs 5y ago> It's a hack to store global data * It's a solution to store, encapsulate and abstract global data
- humanrebar 5y agoEh. Global data doesn't really get abstracted. Abstractions over global data generally leak like a sieve.
- TheOtherHobbes 5y agoAlthough it can be hacky to implement in Python, a singleton object can enforce locking and privilege-based access control. It can also group globals into sub-objects, which can make some naming systems easier to enforce/remember. Open globals are unstructured, and more likely to turn into a messy free for all.
- nedbat 5y agoYou make it sound like "everything is an object" also means "there are no globals". What language is like that?
- javajosh 5y agoHard disagree. Singleton is a tool, and like any tool it has trade-offs. Singletons help you target a very specific, useful time in your application: after it's compiled, but before it's serving requests. You can call this the "initialization time". Within this time, singletons help you organize the one-off components of your application - canonincally, things like connection/thread pools. But hey, thanks for the hot take.
- cr__ 5y agoWhy not explicitly initialize the one-off components and pass them to the other parts of the system that need them as arguments so the system is testable and dependencies are clear? (I know why, generally—low-expressivity languages make it nightmarish to actually do this.)
- nedbat 5y agoIf you need just one, make just one. Why should the class enforce it?
- jackblemming 5y agoDomains often organically have an entity that is well mapped to a singleton. Don't fight the domain if this is the case, you're fighting against reality. But don't reach for a singleton if this isn't the case. Especially bad are singletons that are mutable, for these are just thinly masked globals.
- petilon 5y agoA singleton restriction is a guide to other programmers in the team as to how to use your class. i.e., "don't create multiple instances of my Cache class, use this one instance, otherwise you defeat its purpose". It is a good idea.
- moron4hire 5y agoYou might think today, "I only need one cache", but that assumption might not hold in the future. The problem with Singletons is that you are deciding for everyone who is ever using your code that there will be only one instance of that class. The original article is right. That's not the concern of the class you're writing. That's a concern of the context that is using the class. Dependency injection is better for this sort of issue.
- jackblemming 5y agoThen they can refactor it to not be a singleton in the future. It definitely could be a concern of the class. What if having multiple copies caused catastrophic consequences?
- petilon 5y agoConstraints such as singleton give guidance on how to use your code. If you remove constraints then it is harder to figure out intended usage. Sure constraints may need to be modified in the future, but that doesn't make constraints useless. A simple example of a constraint is 'private' modifier on a method. You could make your arguments against 'private' constraint and say "that's an assumption that might not hold in the future", so we shouldn't have private methods.
- moron4hire 5y agoExcept these two things--single instance-ness of classes and private-ness of class fields--are not comparable things. There's no way to easily change a field from public to private without breaking an unbounded set of code. The Singleton pattern is similarly difficult to change the lifetime of an object without breaking code. But we can achieve the same, desired results of Singleton with Dependency Injection, which can change the lifetime of an object without breaking dependent code. We have no such alternative for field access modifiers. Yes, these things are tools, and in some cases, better tools have been invented.
- david2ndaccount 5y agoSince this post seems to actually be about python, the actual way to implement a singleton is to just use a module. Modules are naturally singletons in python and are objects like everything else.
- addsubtract 5y agoI’ve seen singleton mis-implemented as well. For example, multithreaded implementations that can actually can make multiple instances depending on timing due to the constructor/initialization not being thread-safe.
- emodendroket 5y agoThat's a problem but more languages are introducing features to their STL that make it pretty much idiot-proof.
- ardit33 5y agoSingleton became the 'enemy' during the 'Dependency Injection' craze, spawned in the Java enterprise environment. Singletons are a tool, that at some point you just can't avoid. We can discuss the way to create or access them, but saying they are just all bad is a diservice to younger engineers that are learning proper paterns.
- emodendroket 5y agoIt's like when you teach students not to begin sentences with "and." Sure, in practice, very sparingly, that can make sense. But the problem is that beginners think that almost everything is a case for them.
- nedbat 5y agoIt's fine to have an object that is only instantiated once. But there's no reason to enforce that in the class.
- Etherlord87 5y agoSo, as per the argument in the submission, you should create a function that manages that. And then you want to make sure the class is not instantiated other than with that function. So you recreate a singleton, but one of the methods is outside the class, is harder to find, easier to forget about when moving code around etc. Yes, making sure no one makes more than one instance of the class is defensive programming and you could consider it bad, but a lot of techniques in programming are defensive like that, especially in OOP.
- andrewallbright 5y agoSingletons make it hard to write tests for my programs so I try to avoid them. Being able to run tests simultaneously without them interfering with each other is important to me.
- mdb31 5y agoAs a simple C# (and previously VB.NET, sorry not sorry) wageslave, I've never understood the disdain towards singletons. A single static class that is referenced all over the place (or, alternatively, some huge state object): sure, don't do that. But given a semi-decent dependency injection framework, and a choice of lifetimes like 'singleton' (only one per container), 'transient' (as many per container as required per type) and 'scoped' (as many per container as required for transactions), do I really need to feel bad about the first choice? My app only has a single task scheduler: that's sort-of important, as otherwise there is just chaos. So that's a singleton. Maybe not the same singleton depending on whether I'm running a test or the actual production app, but a singleton nonetheless. So what, exactly, is the big issue with that?
- strictfp 5y agoHaving one instance of a class that's being passed around isn't bad. The singleton pattern with what's effectively a global variable , accessible from anywhere, is bad though.
- mdb31 5y agoSure, as I said "a single static class: don't do that" -- however, the definition of a singleton, as per the GoF, is just "something that restricts the instantiation of a class to one instance". Nothing about global visibility, and again, any decent dependency-injection framework should manage that well enough. So, still mystified about all the singleton-hate here!
- kjeetgill 5y agoI mean, you're right. I came to much the same pattern myself. Much of the singleton hate is from everyone who hasn't figured out, seen, or works with a language that doesn't support "the good way" to do singletons. Alternatively, you could say this _similar, but different_ approach correctly acknowledges and similarly avoids _actual_ problematic singletons. We can all be friends here :D.
- amp108 5y ago> Your ChessBoard class should only be concerned with chess-board-ness. A separate second idea is that your program only needs one board. That’s not a fact intrinsic to chess boards, so it shouldn’t be coded into your ChessBoard class. This is a remarkably bad example, because either (a) a program might need more than one board (e.g., a server for multiple games), in which case the example is irrelevant, or (b) singularity really is a fact intrinsic to chess boards, and is therefore a perfect example of a Singleton.
- bluesign 5y agoI read that more like: your program needs only one board is not enough reason to make ChessBoard singleton.
- nedbat 5y agoThe point is to separate what is true about an object by its nature (what do we know about chess boards), from what is true about how we intend to use the object (we need only one of them). There's no reason to bundle those two concepts together.
- strictfp 5y agoSingleton pattern == global variable
- Fire-Dragon-DoL 5y agoSingleton is not a bad idea, it's just misused. As many pointed out, singleton = global variable. That is the wrong approach. Treating the singleton like a normal object that must be injected makes the pattern way more useful and safe