Global states and evil, evil singletons


#1

Some questions about what to allow in a global state:

I’ve always liked my singletons, but suspected I was using then too liberally (especially when doing plugins - where shared memory is a definite no-no).

So … After some discussion with the sagely mattsonic (from this forum), and reading some hate mail on singletons, I was convinced to try removing all my singletons and cause my dependencies to become explicit (mostly by including them in constructors and then centralizing all the constructors in a builder class). This makes tremendous sense to me, because dependencies should be clear after all. If an objects initializes and then later conjures a singleton from midair to provide a needed link … well, that’s not exactly modular is it?

So far, so good … six sessions of heavy coding and I am nearly rid of my global objects.

However …

There are surely some things that can still be in a global state? For example, I see in the Juce docs that for the AudioDeviceManager …


“The idea is that your application will create one global instance of this object, and let it take care of creating and deleting specific types of audio devices internally. So when the device is changed, your callbacks will just keep running without having to worry about this.”

… awesome, done. I place this in a singleton state object and it can then be accessed from various places around the code. And this is safe, clearly.

some other examples are not so clear cut to me … like …

Colours … I have a long list of Colours that are referenced by various UI elements. Colours are atomic, yeah? And since their are some stored already in the LookAndFeel singleton … this must be safe.

or a Changebroadcaster? Or value object?
I have some of these to trigger things like “midi learn mode” … which many, many objects need to be able to see … so where better than on a singleton?

How about a propertiesSet? ApplicationCommandManager? knownPluginList?

I am probably missing the key guiding principle here, and certainly I am continuing to change my mind about singletons every time I read a few more articles … but any discussion here would be great. I want to make sure to strike the right balance.


#2

You’re right to avoid singletons. But don’t misunderstand my comments on the AudioDeviceManager - saying ‘global’ there is probably a bit misleading. Sure, you should probably have one instance of it, but there’s no reason why that should be a in singleton rather than just owned by your application object or some other object. In my own code I don’t think I ever use AudioDeviceManager as a singleton.

For global constants, colours, etc. you may want to just make them static, which is generally ok as long as they’re read-only.

To try to summarise the reason why singletons/statics are bad: Ideally, when you write a class, the class should only operate on its own internal state, and on any data that you explicitly give to it. That way, there’s no danger that it’ll have unexpected side-effects when you use it. By allowing singletons, ANY part of your code, and ANY class may actually be messing with global state behind the scenes, so could have unexpected interactions with other, completely unrelated bits of the code. That’s bad design.

So wherever possible, if a class needs to access some kind of shared object, you should explicitly give it a pointer/reference to that object, so that at least it’s obvious by looking at the class which other objects it uses.