An 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
You 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.
I'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"?
When 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.
If 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.
That'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)
And 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.
> 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.
I 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.
I 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.
The 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.
Singleton 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.
Although 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.
Hard 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.
Why 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.)
Domains 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.
A 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.
You 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.
Then 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?
Constraints 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.
Except 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.
Since 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.
I’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.
Singleton 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.
It'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.
So, 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.
Singletons 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.
As 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?
Having 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.
Sure, 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!
I 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.
> 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.
The 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.
56 comments
[ 3.5 ms ] story [ 113 ms ] threadThe 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.
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)
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.
No, a singleton is a pattern that ensures that there is at most a single instance of a class.
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.
Though I do admit to occasionally violating my own precepts and using them.
If you need globals and your language supports global data or functions, use that. If not, Singleton is a viable alternative.
* It's a solution to store, encapsulate and abstract global data
Open globals are unstructured, and more likely to turn into a messy free for all.
But hey, thanks for the hot take.
(I know why, generally—low-expressivity languages make it nightmarish to actually do this.)
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.
Yes, these things are tools, and in some cases, better tools have been invented.
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.
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.
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?
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!
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.
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