views:

266

answers:

4

After careful reading the facts about singletons (the code smell, not the pattern) I wonder:

How can I refactor my code to get rid of them?

Despite almost everyone agreeing that bad singletons are, well, bad, I could not found any practical advice on how to replace them. Either it's very trivial or very hard.

There are some ways I can think of but all of it seem to bloat my code tremendously.

For example let's say I have a "global" AppConfig class which holds license information about the product and describing the features available to the user.

What I can think of:

  • Create a common base class for each and every class of my projects which holds an AppConfig instance. (BAD: Impossible for cases where you already have a base class, e.g. forms)
  • Create a common interface with a setAppConfig method.
  • Create a global AppConfigFactory which can create AppConfig instances (BAD: Only shifts the problem to another class)
  • Pass the instance as parameter to every method which needs it. (BAD: Code bloat)
  • ...

What can I do?

EDIT: Clarification: I have identified a bad singleton in my code. Now I want to refactor my code to remove it. I'm asking for tips and general ideas on how to achive this.

A: 

How about making the class have only static members? Like, instead of this (C# code):

class AppConfig
{
    public static readonly AppConfig Instance;

    private AppConfig() { }
    static AppConfig()
    {
        Instance = new AppConfig();
    }

    public string SomeConfigParam { get; set; }
}

Do this:

static class AppConfig
{
    public static string SomeConfigParam { get; set; }
}

Singletons only make sense if you need to pass the instance around - like parameters to functions or values in a collection. System.DBNull in .NET is a good example of a singleton. If it's simply a global store of data that everyone should be able to access, static classes make your code shorter and simpler.

Vilx-
be aware though that static classes can make your code harder to test. Though if it is a simple data store that's not the case here.
Rich Seller
Wouldn't that still be a singleton?
DR
No, it's more like global variables, except with a nice namespace prefix. Face it - in every program there will be some global variables. Settings and data that need to be accessed program-wide. Static classes/class members are the best way to encapsulate those in an OOP way.
Vilx-
Global variables also aren't bad. They're only bad if you abuse them for things that do not need to be available program-wide.
Vilx-
Making the whole class static doesn't improve the situation at all. It's still global data with all the same design problems.
Nathan Monteleone
But this \* **IS** \* global data. Don't try to pretend that there is no global data. That's another code smell/bad practice/etc. Sure, you can make your code in such a way that there will be no `static` keyword used anywhere. But this will only complicate it and make it **less** maintainable. As with everything in life - avoid the extremes. Don't overuse global data, and don't underuse it. Use it where it truly makes sense, where there is not a snowballs chance in hell that it will ever need to be duplicated (like the example with application configuration).
Vilx-
+6  A: 

Use Dependency Injection and Inversion Of Control framework - this may require significant refactoring. Then, using constructor or property dependency, ask for the "singleton" - ideally, you don't ask for the whole thing, as by the principle of Demeter, it should only ask for the thing it really needs (in your case the license information).

I try to distinguish between Singleton (the antipattern disguising global variables) and singleton (meaning something you only need one of). A true singleton is created once at the start of the program (or in your factory) and passed to the objects that need it.

1800 INFORMATION
you just dont understand singleton design pattern, you should always use design patterns!!
01
I can't really tell. Are you being sarcastic?
1800 INFORMATION
Can you give some examples for these frameworks? Some keywords I can google for?
DR
It depends on your language. For Java there is Spring and GUICE. For .Net there is Spring.Net. There may be others as well.
1800 INFORMATION
+2  A: 

You say

Create a global AppConfigFactory which can create AppConfig instances (BAD: Only shifts the problem to another class)

In my view this is actually not bad at all. The client's view is that he asks a factory object for the config he should use. He does not know it is a singleton! At a stroke the singleton-ness is encapsulted in the Factory. [Pragmatically the Factory may well end up as a Singleton itself, but everything has to bootstrap, right?]

Now whether you wrap up the Factory access using Dependency Injection techniques is a refinement, the fundamental is that only one object is looking after the creation of these AppConfig objects, only the factory knows if there are one or many.

And that leads me to another pet theory ... there is no such number as 1, when you start out it looks like a Singleton, then conmplexity grows, and you find a scenario where some part of your app (for example) uses one Config and another part uses a different one (Eg. in dynamic transition between versions). The factory can hide that complexity.

djna
A: 

Either pass the AppConfig via a setAppConfig() method or the constructor, if the object needs the app-config throughout its lifetime. If the association between the global AppConfig and the object is conditional (that is, it is required only in certain methods), then pass it as an extra argument.

jeyoung