riedquat - valueable resource for those who seek.
Home Blog Technical Reports Art Articles RapiDocs Coding Bugs Links Reviews Projects: CherBot Daimonin Gridarta

Singletons are Evil

The Singleton design pattern is nowadays seen as an anti pattern. While in the past it has served the nice purpose of making sure that something exists only once, the sole purpose of a singleton has become a show stopper for proper (unit) testing and thus is being declared evil by many architects these days.

Introduction

To understand why the Singleton design pattern is evil, we first need to understand the purpose of design patterns in common and that of the Singleton design pattern in particular plus what fundamental architectural design requirements these days need to be fulfilled when designing software.

Design Patterns

Design patterns are used to model solutions for reoccuring problems in software design. These solutions are then named because names are much shorter than descriptions. The names of design patterns allow easy communication about design patterns as well as creating catalogues with indices about design patterns.

There are many well known design patterns, like Factory Method, Factory Class, Abstract Factory, Visitor, Mirror, Facade and many many more.

The Singleton Design Pattern

In a model, a Singleton is something which is class and instance at the same time. The requirement that is set for a Singleton thus is that there shall be only one instance of the Singleton's class. Therefore instantiation of the Singleton must be prevented.

A typical Singleton source code might look like this:

/** The Singleton class. */
public class MySingleton {
    /** The instance. */
    private static MySingleton instance = new MySingleton();

    /** Private constructor, prevents any further instantiation. */
    private MySingleton() {
    }

    /** Returns the instance of this Singleton.
     * @return The instance of this Singleton.
     */
    public static MySingleton getInstance() {
        return instance;
    }
}

Please note that lazy initialization, multi-threading and other issues are beyond the scope of this discussion.

Todays Architectural Requirements

Unit testing, sometimes also referred to as component testing, is a fundamental part of modern software engineering. Unit testing helps increasing the software quality by finding bugs in an early development stage. When unit tests are maintained in a good manner, they can be easily executed over and over again, helping to prevent regression. Regression means that something that was already working fine broke, usually due to changes.

Changes lead to regression. But not applying changes to circumvent the risk of regression is the wrong approach. Software needs to be changed regularly, to increase its maintainability and to make the integration of new features for new requirements easier. That means we must find a different way to regression, and that is unit testing. The other approach would be to not change the software, but we want to change the software to integrate new features to compete on the market, don't we?

Unit Testing

Unit testing is a well established process for increasing software quality. Unit tests are applied on a relatively low level. A single unit test uses a very small part of the software and verifies that it behaves as expected, i.e. as the requirements, the design, the architecture, the documentation or the contract suggest.

There are some requirements on unit testing which lead to some requirements in software design and software architecture.

Collection
Unit tests should be collected. Whenever a unit test was written, it should be added to a unit repository and be kept in there as long as it is applicable. We don't want a regression to come from "well, we once had a test but we deleted it.".
Automation
Unit tests must be executed and evaluated in a highly automated manner. Over the time we might get something like several thousands, in larger projects even some millions of unit tests. Executing them manually would be a highly laboruous, error-prone and cost-intense way. Thus, the whole unit test suite must be runnable with the click of a button, typing a single command or just waiting until a build or test robot executes them automatically.
Reproducability
A unit test must, as long as the test target remains unchanged, always yield the same result when executed over and over again. There should not be any non-deterministic dependencies. It is important for a software developer to be able to reproduce an error found in a unit test on his own machine to be able to debug and fix it.
Test Independence
Because the whole test suite can grow quite large (see Collection), the execution of the whole test suite can take quite long. A test suite of 150,000 test cases is not rare, and its execution might take hours. Therefore it should be possible to execute only a subset of the whole test suite, a smaller test suite, or even just a single test case. The result of a single test must be independent of all other tests, otherwise a test might yield different results depending on which other tests have or have not run before.

What makes Singeltons evil

Violation of Test Independence

A Singleton exists only once, by definition. This violates the test independence, which as we've seen is a fundamental requirement of unit testing.

Why make Singletons anyway?

Quite often, the assumption that it usually doesn't make sense to create further instances from a class apart from the first one is wrongly turned into a requirement that such further instances must be prevented. Why? Let's take a closer look.

Do you really know whether absolutely no user does not have a good reason to instantiate the class a second or third time? Apart from unit tests, there might be other occasions where a second instance might make sense which we just can't think of right now. Why place such restrictions on your class when you could live without? Let's see what we could do instead:

/** Class with default instance. */
public class ClassWithDefaultInstance {

    /** The default instance. */
    private static ClassWithDefaultInstance instance = new ClassWithDefaultInstance();

    /** Create an instance of ClassWithDefaultInstance.
     * Usually you will want to use the default instance,
     * which can be retrieved with {@link #getInstance()}.
     */
    public ClassWithDefaultInstance() {
    }

    /** Returns the default instance.
     * @return The default instance.
     */
    public static ClassWithDefaultInstance getInstance() {
        return instance;
    }
}

Please note again that lazy initialization and threading issues are beyond the scope of this discussion.

Special Singleton issue in Java

In Java there is another issue with Singletons. In fact, Singletons are impossible in Java. If you create a Singleton and rely on the Singleton really being a Singleton, you fool yourself. It will always be possible to create more than one instance of the class. The trick is using the ClassLoader to load the class more than once. There will still be only one instance per class, but the class will be loaded more than once, and thus indirectly there will be more than one instance.

Conclusion

An OO model thus looks better without Singletons.

 . 
..: