Singletons are bad umm ok!

Posted: 2009-08-17 in Code and Computers
Tags:

Really I think the title says it all but let’s turn this from a statement to a theory.

Ok so why are singletons bad?

Global variables are bad right? Variables that inadvertently allow any code with access the ability to indirectly changing other code relying on the same variable. Problems that are also amplified with multi threaded applications (Google C# keyword volatile for more information).

So if everyone blindly takes global variables as being bad then why can’t people see that singletons are bad (umm ok).

For nearly all general purposes global variables and singletons are the same thing… well almost one has a bit more syntactical sugar coating around it and is hidden by a functional global variable instead of direct access to the variable itself.

Function variables are a bit like putting a wolf in sheep’s clothing, from a distance the syntax is different and they are a tiny bit safer looking due to their abstraction but once in use they both equate to their original format.

No matter how you look, at what angle, or what yeah but you wrap around it, it still code smells, just slight hampered by the pine scented air fresher sitting in the corner.

So without repeating too much about why global variables are bad singletons are bad, umm ok.

Ok so they are like global variable, that can’t be the only reason right?

No your right, there are some other reasons. One being that Unit testing becomes a night mare, singleton objects could be changed depending on previous unit test runs.

For example: Singleton object which contains database connection information (quiet a common scenario for singletons)

Unit test 1 – set singleton to null and check that the app check for null values (argument null exception)
Unit test 2 – set singleton to a local test database that is invalid
Unit test 3 – set singleton to a local test database that is valid
Unit test 4 – test bulk load of test objects

In this scenario unit test 4 will succeed, but if unit test 3 was exchanged with unit test 1 then unit test 4 would fail. Add several hundred unit test and expand your singleton class and it become impossible to keep track of the value the singleton should have.

Ok with unit test you should set the default set for before each run [Test Setup]. While for this example it is easy to do, it does become a bit of a nightmare if you should reset the entire singleton each time you need to run it. This kind of defeats some of the ideas behind black box unit testing (why should you set values that may or may not have anything to do with your test).

You can work around this using dependency injection, this does entail that you should expose methods simply for testing reasons.

This also highlights a program that evolves multiple programmers, for one programmer it is usually easier to obey your singleton rules and ideologies, but when multiple programmers get involved you need either an FxCop to help or you need to turn into a coding Nazi and constantly keep a check on what others are doing with your singleton class.

A wiser solution for the above might be to pass an IDatabaseSettings into the constructor, an initialize function, or a property. It may not seem as nice but the decoupling is worth its weight in maintenance/upgrading gold.

Singleton helps code clarity, doesn’t it?

Yes but only through coupling, so while method signatures look cleaner, the programming knowledge on how to use them is much greater. This problem is amplified if programmer’s take a black box usage approach (the your code works I just need to call it not understand how it works method).

Coupling through singletons/global variables usually just denotes that someone is hiding a design issue rather than dealing with it.

Decoupling does creates greater abstraction which creates more interpretation by the programmer, but it makes your program much, much, much more flexible.

How not to serialize a singleton

The Microsoft MSDN website (http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx) has a great non working example on their website. it works perfectly if you run the code without stopping the program, but if you run this in two parts, save then restart and load then your saved values never serialize back.

If you scroll to the comments down the bottom you will see an explanation in the comments on why this example doesn’t work (submitted by me), it may or may not still be there.
You can get around the serializing issue by using a custom deserializer but this quickly becomes a point of failure also. It’s also a very messy solution.

UPDATE: 2013-01-08 My comments are still there but only when you select version 3.0, the nicest part is someone called Thomas Lee seems to have stolen err reposted my comments under his name but nicely forgot to take out my signature (cheers choco part 🙂 )

Still not convinced.

Well i tried. If: hard to unit test; global variable or global state; dependacy injections; code smell; and difficulties in serializing don’t cut it then best of the luck to you.

All I can say is “Singletons are bad, umm ok”.

My personal experience is that every time I put one in I painfully take it out several months later.

3 months after first post: The Factory Pattern
It’s a pattern I love to hate, I hate setting it up, I love its abstraction. If you must use a singleton then try a half and half “The Factory Pattern”.

There is lots of reading about the factory pattern so to keep it short. Using this pattern you get a singleton like (but not exactly alike) pattern in which a single instance is returned BUT it is not enforced… something that should be done by the users, use and discard sort of thing.

I use the Factory pattern mostly to separate storage logic (DataAccess) from the rest of the business logic.
By running the business through the factory model a working protocol can be setup as default and the storage model can come last. I usually prefer this way of work due to the cascading affect that changing something in business can have on the data storage model. E.G a new field 5 seconds in common layer about 50 minutes from data facade to data access layer.

Cheers

Choco

More reading

http://www.codingwithoutcomments.com/2008/10/08/singleton-i-love-you-but-youre-bringing-me-down/

http://steve.yegge.googlepages.com/singleton-considered-stupid

Advertisements
Comments
  1. Martin says:

    Hey here,

    Going at it at singletons. Some good point. Read this one? “Singletons are pathological liars”: http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/

    But as for static classes and factory classes, singletons have it’s usage and one should always have good init/teardown in test case to properly leave these type in a “normal” state. Can’t avoid a pattern if it is what you need because it needs a few extra lines of code in the test classes, right?

    /Martin The Wise 🙂

    • choco says:

      Hi mtw,

      I am a bit jubious about having a teardown method for 2 main reasons:

      1. If i put the tear down in the unit test, then it means that I need to really understand the code behind. This is made worse if multiple classes use the singleton class.

      2. If you move this “master reset” to the main code then anyone using the singleton has to remember to add reset behavior…. A lot like IClonable issues.

      Otherwise the Factory pattern is good point (I updated the main article to include it). Its a pattern I love when working and hate implementing 😛

      Cheers
      Choco

  2. Martin says:

    Forgot this… a few tips for the one who struggles with testing of singletons:

    – Add a setter to the singleton instance, or make the factory that creates it configurable to create your own instance.
    – Make sure a singleton always return an interface rather than a concrete class. It’s easier to stub or mock an interface than to do the same with a class you’ll need to inherit from. It also creates less complications down the road.

    /MTW

  3. Choco Smith says:

    Reblogged this on life in lower case and commented:

    this used to be one of my most popular post until I moved my blog website

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s