Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I refactor my code to remove unnecessary singletons?

Tags:

I was confused when I first started to see anti-singleton commentary. I have used the singleton pattern in some recent projects, and it was working out beautifully. So much so, in fact, that I have used it many, many times.

Now, after running into some problems, reading this SO question, and especially this blog post, I understand the evil that I have brought into the world.

So: How do I go about removing singletons from existing code?

For example:
In a retail store management program, I used the MVC pattern. My Model objects describe the store, the user interface is the View, and I have a set of Controllers that act as liason between the two. Great. Except that I made the Store into a singleton (since the application only ever manages one store at a time), and I also made most of my Controller classes into singletons (one mainWindow, one menuBar, one productEditor...). Now, most of my Controller classes get access the other singletons like this:

Store managedStore = Store::getInstance();
managedStore.doSomething();
managedStore.doSomethingElse();
//etc.

Should I instead:

  1. Create one instance of each object and pass references to every object that needs access to them?
  2. Use globals?
  3. Something else?

Globals would still be bad, but at least they wouldn't be pretending.

I see #1 quickly leading to horribly inflated constructor calls:

someVar = SomeControllerClass(managedStore, menuBar, editor, sasquatch, ...)

Has anyone else been through this yet? What is the OO way to give many individual classes acces to a common variable without it being a global or a singleton?

like image 691
e.James Avatar asked Jan 23 '09 21:01

e.James


2 Answers

Dependency Injection is your friend.

Take a look at these posts on the excellent Google Testing Blog:

  • Singletons are pathologic liars (but you probably already understand this if you are asking this question)
  • A talk on Dependency Injection
  • Guide to Writing Testable Code

Hopefully someone has made a DI framework/container for the C++ world? Looks like Google has released a C++ Testing Framework and a C++ Mocking Framework, which might help you out.

like image 172
matt b Avatar answered Sep 29 '22 12:09

matt b


It's not the Singleton-ness that is the problem. It's fine to have an object that there will only ever be one instance of. The problem is the global access. Your classes that use Store should receive a Store instance in the constructor (or have a Store property / data member that can be set) and they can all receive the same instance. Store can even keep logic within it to ensure that only one instance is ever created.

like image 32
Eddie Deyo Avatar answered Sep 29 '22 11:09

Eddie Deyo