
The Case for Singletons - krogsgard
http://eamann.com/tech/the-case-for-singletons/
======
bcoates
Necessary singletons are a sign that your language/library either embraces
"everything is a class" so you have to make vacuous singleton classes to get
full access to the language, or it is lacking a sufficiently powerful module
system so you have to implement an ad-hoc one yourself using classes.

Unnecessary singletons are usually a sign that someone, somewhere designed a
way too general system that allowed multiple instances of something, then
nobody ever used that feature, then someone else came in and made things a bit
saner by adding a singleton constraint, leaving vestigial object-ness and
meaningless pointers being passed around everywhere.

In a perfect world with perfect programmers you'd never see one so the
instinct that they smell bad is correct.

~~~
masklinn
> Unnecessary singletons are usually a sign that someone, somewhere designed a
> way too general system that allowed multiple instances of something, then
> nobody ever used that feature, then someone else came in and made things a
> bit saner by adding a singleton constraint

I fail to see how that makes anything saner.

~~~
bcoates
If your program has an unused and untested capability, killing it is a move in
the right direction even if it makes your program less elegant. Bad behavior
is worse than ugly design.

Of course the right thing to do is to simplify the rest of the program to take
advantage of the new assumption but maintenance programmers don't always have
the luxury.

------
jessedhillon
Downvote away -- I know I deserve it, but I need to say this:

Whenever I see a discussion of good software design principles given by a PHP
programmer, with PHP examples, I roll my eyes and press Back.

Rightly or wrongly, the thought that goes through my head as a former PHP
programmer (from versions 3 - 5.x, ending in ~2010) is something like, "if
this person knew anything about well-designed software, they'd know enough to
use a well-designed language."

~~~
jt2190
A statement like this doesn't help anyone.

It doesn't help the productive PHP programmer get a better understanding of
other (possibly better) tools that exist, what problems they solve, and how
they can transition to those tools.

It also doesn't help the person making the statement convey their expertise in
the subject matter. Instead it looks like an easily dismissed statement about
PHP, without any real attempt to prove it.

~~~
olleicua
The problems of PHP have been well documented here:
[http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-
de...](http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/) I
think its relevant that PHP does object and classes in terrible backwards ways
and, among other things, a singleton will necessarily be rather ugly in this
context. Learning about singletons won't help anyone get a better
understanding of other tools that exist. Learn Ruby or Python if you want to
do web programming.

~~~
jmathai
It's like people in Ferraris yelling at people in Toyotas.

~~~
1010011010
It's more like people in cars yelling at people who have attached wheels and
diesel engines to horses.

~~~
jmathai
What?

------
michaelfeathers
There is another argument against singletons. They destroy design information:

[http://michaelfeathers.typepad.com/michael_feathers_blog/201...](http://michaelfeathers.typepad.com/michael_feathers_blog/2012/12/global-
variables-destroy-design-information.html)

------
jcampbell1
I am not a big fan of "getInstance". For a session it should be named
something like "defaultSession". It is perfectly reasonable that you later
want to add a separate session that requires HTTPS only cookies, in which case
it could be called "secureSession".

------
mikevm
If we're on the subject of anti-patterns, should GOTO really never be used, in
any situation?

I remember writing some code in C a few years ago and I needed a place in a
function where cleanup is performed, and in case there were errors caught in
multiple places before you get to the cleanup area, I used a goto statement to
jump there after printing the error message and turning on a special error
flag.

How would you solve that problem without goto?

~~~
IsaacSchlueter
You would put the cleanup code in a separate function, and call it.

I don't think there's anything wrong with using goto in such a case, though,
if it makes the code more understandable.

~~~
asveikau
Having worked in a large C code base that was occasionally tainted with this
approach (rooted only because people have been told to avoid goto as dogma), I
have to say that goto is a better approach to emulate try-finally or RAII in
C. For one, the goto will read better as a single piece of prose, there will
be no need to glance over at some other function to see the free call. Second,
let's say your function has 2 allocations and a lock acquisition - that means
your cleanup function needs a pointer to each, usually done with parameters.
Add an extra allocation? New parameter to the cleanup function. This gets
messy, fast, in a way that the goto does not.

------
georgemcbay
My problem with most singletons is that they are a half-way solution for a
developer unwilling to commit and accept that sometimes a bit of global state
isn't the end of the world.

Static fields and static methods on classes should be used sparingly, but if
you're going to use them, just use them. Why half-assedly try to hide the fact
that you're using them by wrapping them into a singleton?

This is a(nother) thing I like about Go, the design of the language allows for
the fact that sometimes a function is just a function and doesn't need an
object receiver and maybe it even modifies a package level global, so what?
Just make sure you properly handle multithreading situations. In Go code you
don't find a lot of patterns where people are trying to sweep what they are
doing under a rug in order to not anger people who accept "common wisdom" code
design guidelines as absolutes.

If you need to write "dangerous" code (and sometimes it is best to write
"dangerous code"), do it in the open, out in the light of day, that way at
least it can more easily be reasoned about if someone does hit a snag in it.

~~~
mikeschinkel
"Why half-assedly try to hide the fact that you're using them by wrapping them
into a singleton?"

I may be misunderstanding your context for the above comment but when I use
singleton classes for WordPress plugins I do so to avoid potential namespace
collisions with other WordPress plugins.

------
rdwallis
Singletons are easy to implement, simple to understand and have no performance
penalties. They don't need to be defended. If they work for your project, use
them.

~~~
masklinn
> Singletons are easy to implement, simple to understand and have no
> performance penalties.

Unless there's any concurrency to the system, that is. Then they're shared
state (as fraught with peril as any shared state) except they're shared state
which can be broken/corrupted straight from the initialization.

------
KirinDave
So Eric is sort of right although he doesn't explicitly state it: Singletons
_may_ provide a decoupling point nearly identical to dependency injection when
designed with care. But that's not really the problem, and he stops with an
argument that is compelling to someone in 2002 but not so compelling for
someone from 2012.

The reason we prefer non-singletons to singletons are as follows:

• Most languages do not provide very good ways to prevent singleton collision.
As software has become more complex and open source's success increases the
size of the average dependency tree, this problem is exacerbated.

• Singletons force you to confront all the problems shared state concurrency
has to offer, with almost no support. DI objects tend to be isolated from one
another and do not run into that level of complexity so soon.

• Singletons tend to make it harder to test code unless your language has a
method for overriding or mocking singletons within a dynamic scope (or static
type checking between types with liskov-substitutable signatures). The most
classic exampe of this is one of the most prevalent singletons: your system
clock.

Knowing what we know now about how successful software projects tend to be
confronted with expectations of concurrency, parallelism, robustness in the
face of reuse, and testability; singletons offer a lot of costs for very
transient benefits.

~~~
masklinn
Singletons also make things painful if (when?) you have to go from "one
instance" to "two instances", which regularly happens.

~~~
eamann
Which is why they should be used sparingly, if at all. I'm not advocating we
go out and start making every class a singleton, just explaining how they _do_
serve a purpose in PHP/WordPress development.

~~~
mikeschinkel
I support Eric here. Singleton make sense in WordPress specifically for
encapsulating plugins. In WordPress plugins can never have more than one
instance so it's really a moot point to expect them to be anything else.

Outside of WordPress plugins, I don't currently know of cases where I'd also
advocate for singletons. Yes in most other cases singletons are bad but I'm
sure there are some other cases where they do make sense. And you can't prove
a negative.

------
pcwalton
I generally prefer Lisp-style ✲dynamic✲ variables. They basically work the
same way singletons do, but they can be set and reset at a block-scoped level
(great for test mocks and the like, and makes your control flow easier to
understand), and they play much better with threads.

Rust doesn't even have singletons or global variables, since they aren't
threadsafe. It has thread-local storage, which dynamic variables are built on
top of.

~~~
masklinn
> It has thread-local storage, which dynamic variables are built on top of.

That hack only works if execution can never be suspended though. The issue
exists in Python where it's possible to fake dynamic scope using threadlocals,
but _that_ can blow up if execution is suspended (between `yield`s in a
generator, for instance) as the stack doesn't get unwound (merely frozen) and
the threadlocal isn't reverted if it's in the frozen part of the stack. Same
deal if it's possible to unshift stack frames, the threadlocal will more than
likely end up in the wrong state.

An other thing which bothers me with threadlocals is that it's not really
possible to introspect currently-bound locals in order to "save" them
alongside lambdas (though that may be an API issue more than an issue with the
locals themselves), and in my experience async callbacks tend to need their
creation stack context more than their callstack context.

~~~
pcwalton
Both good points. Rust doesn't have the problem with execution being
suspended, since the only mechanism for suspending execution is through the
task system. Thread locals are all per-task.

The issue with introspection is fair, and it's a gotcha you have to keep in
mind whenever you use dynamic variables. They're necessary to make the task
system and condition handler system work under the hood, however, so we can't
just remove them.

~~~
masklinn
> They're necessary to make the task system and condition handler system work
> under the hood, however, so we can't just remove them.

Oh I've nothing against dynamic variables at all and wouldn't want them (or
conditions) to be removed from Rust (in fact I wish solid dynamic variables
were available in more languages), don't get me wrong.

------
1010011010
This is a good read on singletons.

[http://www.object-oriented-security.org/lets-
argue/singleton...](http://www.object-oriented-security.org/lets-
argue/singletons)

"Singletons are possibly the single greatest obstacle to good object-oriented
design today. They are often at the root of huge intractable design flaws in
large systems, and yet many programmers continue to use them and even insist
that they are a good design pattern. Many programmers point to the fact that
the singleton pattern is a prominent part of the book Design Patterns, but
don't realize that at least one of the authors of that book (Erich Gamma) is
on record saying that it shouldn't have been.

We argue that Singletons are almost always bad design and almost never needed.
In the few cases where singletons seem necessary, the "environment pattern"
offers a reasonable alternative. Therefore, we recommend that programmers
always avoid singletons and that programming languages ban them or at least
provide an option to ban them."

------
wvenable
I prefer to mix both dependency injection and singletons for the best of both
words. Classes accept dependencies in their constructors but as optional
parameters -- if the parameter isn't provided, a default reference is pulled
from a singleton.

It saves a lot of extra typing when 99% of the time your dependencies are
fixed.

------
cousin_it
Singletons, globals/statics, and dependency injection all seem to be solutions
to the problem of making objects find each other at runtime.

Maybe it's time for a dedicated language feature to solve that problem? For
example, each object could carry an implicit reference to an "object pool",
from which it can fetch other objects by their class/interface. If an object
constructs other objects, the "pool" gets passed along implicitly. Test suites
could use "pools" filled with mocks. And unless I'm missing something, the
presence of all required dependencies could be statically checked at compile
time.

Basically it would be like Lisp's dynamic variables, but based on the
construction hierarchy instead of the call hierarchy. What do you think?

------
wvs
The main issue I have with singletons is that _any_ mutable global state
prevents your application from being first-class within its own runtime
environment.

This is of course useful for unit testing, but also reduces hidden state
dependencies between submodules.

------
api
I've been of the opinion for a while that static variables of any kind should
be avoided except for const data (tables, constants, etc.). They make code
very difficult to impossible to port to multi-threaded environments, and make
it hard to cleanly instantiate and then clean up a module within a larger
program. Even things that feel like they should be global should be contained
with a global context container that can be cleaned up.

~~~
eamann
I agree. But remember, the article is specifically about singletons in
_WordPress_ , which is written in PHP, which is single-threaded.

~~~
masklinn
> the article is specifically about singletons in WordPress

Is that why you open with

> I would argue that Singletons are not just useful, but are necessary for
> robust software development.

?

No mention of wordpress there, you use it as an example but your assertion is
that singletons are downright _necessary_ to software development.

~~~
mikeschinkel
@eamann, I gotta give @masklinn credit there, you didn't explicitly make it
clear your post was focused on WordPress-related use-cases. It was obvious to
me from your references and knowing your focus but maybe not obvious to those
who don't specialize in WordPress if all they did was scan the article, as
most people do.

~~~
masklinn
No, even reading the post it's not obvious. It's obvious that he talks about
wordpress, but considering the assertion I quoted I simply read it as using a
wordpress-based example/use case to support his hypothesis.

At no point did I find or notice a modifier of the article being an argument
for the usage of singletons _in wordpress plugins_. though I may just have
missed it.

------
seanalltogether
I can't speak to server side development, but for ui applications, storing
your models in a singleton can save you a lot of time. When you're developing
apps its very easy to get stuck in a mindset that you only need certain data
for each screen, but the truth is the data for one area will inevitably bleed
over into other areas, and having a good way of updating and reflecting data
to the areas needed is the sign of good architecture.

------
eamann
I've posted a follow-up to this that broadens the ideas of Singletons for
general PHP use. Using abstract classes and inheritance, it's also possible to
unit test the code contained within a Singleton. The follow-up is here:
<http://news.ycombinator.com/item?id=5023027>

------
zaphar
Is it just me or did he never actually address the dependency injection
complaints? It read like he spoke glowingly of how dependency injection
decouples your code and makes your blissfully flexible and then nothing. Was
his counter argument just that sometimes you _need_ to be less flexible?

~~~
jasonlotito
He tried to, with the suggestion that with DI, you suddenly had the dependence
hard coded and would have to make a code change to change the dependency.
This, of course, is not accurate.

------
debacle
> Think of every time you’ve used the global keyword when working in
> WordPress.

I pretty much stopped reading there. Referencing WordPress when making a point
about software design does not strengthen your point.

Singletons are the antithesis of dependency injection.

------
1010011010
The number of replies defending PHP make me think that HN is very close to
becoming a useless place, dangerous even, for obtaining programming (and
probably other) advice.

~~~
eamann
It's not about defending PHP. PHP is an ugly, inconsistent language. It's a
matter of pointing out why certain tools are used in certain environments.

------
VMG

         $this-&gt;persist
    

That's just sad. And the author even is a wordpress _developer_

~~~
eamann
Yes, it's sad. And no, I'm not a "wordpress" developer, I'm a WordPress
developer who didn't properly proofread everything before publishing. You
should probably take a lesson from that ... :)

