2

I used to use singleton get a single instance, but it was disclaimed by others because of some disadvantage in testing. What's the disadvantage? Is there any alternative good way for getting a global instance?


So is it OK for me to create only one singleton class Global in application as global hub? so that I can put any other class's single instances in Global.Instance.

demaxSH
  • 1,743
  • 2
  • 20
  • 27
  • 1
    Possible duplicate of http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – ChrisWue Apr 25 '11 at 07:36
  • @ChrisWue: +1 for perfect find! – Numan Apr 25 '11 at 07:39
  • @Chris: That's a related discussion, but it's not a duplicate. Your link is about "why singletons are bad", while this question asks what to use instead. – Gabe Apr 25 '11 at 07:47

4 Answers4

4

Ok, why singletons are bad you can read here: What is so bad about singletons?

Specifically for testing: A typical singleton pattern looks like this

class MyClass
{
    private static MyClass m_Instance = new MyClass();
    public static MyClass Instance
    {
        get { return m_Instance; }
    }
}

Now imagine you have to run a whole bunch of tests all involving the MyClass.Instance. This class carries around a state and you usually need to have to have a way to reset it between tests so that each test can start with a clean initial state. Now you can add a Reset() method but that means you add code to your class just for the purpose of being able to test it which is not desirable.

What to use instead: Well, the singleton in itself is not really the bad thing. The problem it leads to is that it makes it easy to write code like this:

class SomeClass
{
    public void SomeMethod()
    {
        ...
        MyClass.Instance.DoSomething();
    }
}

Now you have created an implicit dependency on the singleton instance you cannot easily break. One approach which solves this problem is via dependency injection (which was already mentioned):

class SomeClass
{
    public SomeClass(MyClass myClass)
    {
        m_MyClass = myClass;
    }

    public void SomeMethod()
    {
        ...
        m_MyClass.DoSomething();
    }
}

and you can do:

var someClass = new SomeClass(MyClass.Instance);

in your program and

var someClass = new SomeClass(new MyClass());

for testing.

So singletons are not that bad and sometimes the right tool for the right job, however you need to be careful of how you use them.

Community
  • 1
  • 1
ChrisWue
  • 18,612
  • 4
  • 58
  • 83
  • i dont see that singletons and DI contradict. i think they can be easily combined. singletons should be in my opion created at program startup and if you use interface i dont see any issues with testability. – NickD Apr 25 '11 at 08:12
  • I never said they contradict. I specifically stated that using DI in combination with singletons is what you actually want to do (well most of the time). – ChrisWue Apr 25 '11 at 08:58
  • i agree 90% with your answer except this sentence: The better approach is via dependency injection (which was already mentioned): – NickD Apr 25 '11 at 09:12
  • Ok, keeping "there is always more than one solution" in mind I rephrased it a bit ;) – ChrisWue Apr 25 '11 at 09:20
1

Testability is the main difficulty as I can see, to address that to some extent, we have unity containers.
Check Unity container http://unity.codeplex.com/

Numan
  • 3,918
  • 4
  • 27
  • 44
0

i dont see any issues with testability and singletons. also i dont see how DI can replace them.

NickD
  • 2,672
  • 7
  • 37
  • 58
  • Please check #3 item in first answer! http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – Numan Apr 25 '11 at 07:45
  • @System.Exception: "They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases." – NickD Apr 25 '11 at 07:48
  • Updated my answer! ;-) It is "difficult" to test as you have posted in your comment! – Numan Apr 25 '11 at 07:50
  • as the singleton is in my case always used together with a factory pattern, i dont share this point. – NickD Apr 25 '11 at 07:50
0

Consider using the what is called "ambient context" pattern instead. This example is taken from Mark Seeman's excellent Dependency Injection in .NET book. This pattern gives you the ease of use of a singleton, and also testability. The important point here is the existence of what is called a good "default" (i.e. DefaultTimeProvider shown in the example). Another thing to consider is not to abuse this pattern, in most cases you can inject the different dependencies into the constructor of the class. This pattern should only be used for concerns that cross cut throughout the whole application.

public abstract class TimeProvider
{
    private static TimeProvider current;
    static TimeProvider()
    {
        TimeProvider.current = new DefaultTimeProvider();
    }
    public static TimeProvider Current
    {
        get { return TimeProvider.current; }

        set
        {
            if (value == null)      
            {         
                throw new ArgumentNullException("value");    
            }              
            TimeProvider.current = value; 
        }
    }
    public abstract DateTime UtcNow { get; }
    public static void ResetToDefault()
    {
        TimeProvider.current = new DefaultTimeProvider();
    }
}
Can Gencer
  • 8,822
  • 5
  • 33
  • 52
  • How does this differ (apart form the nicer name) from a Singleton with a reset method, as mentioned in the accepted answer above? – MartinP Jan 19 '12 at 13:24
  • The reset mentioned there is just to reset the "state" of the singleton. This pattern is more pluggable, i.e. you can replace it with another implementation. So even though it has the ease of access of a singleton it's possible to have multiple different implementations for testing and so forth. – Can Gencer Jan 19 '12 at 15:03