22

Not sure of downfalls using strict global state implementation. When is singleton not ideal for an application?

1
  • Here is a good read on singleton being an anti-pattern. Commented Oct 25, 2016 at 6:31

4 Answers 4

38

Singleton is generally a bad idea if you are doing unit testing, and its generally a bad idea not to do unit testing (or BDD or Acceptance Testing).

Making objects have global state means that the unit tests you write involving these objects will be isolated and disjoint from one another. Instead, you will have to worry about resetting the state for each test and believe me ... that is never done 100% of the time. If you don't reset the global state then you start to get very weird and hard to debug errors in your tests that waste time.

Global state also increases coupling in your code and makes it very hard to refactor.

The ideal method would be to use an IoC/DI container (Spring, Guice, etc.) to request objects. These containers often have ways of making objects appear as 'Singletons' but they also have ways of modifying that behavior depending on the situation (i.e. unit testing vs. your domain code).

This all depends on the size of your problem of course. If you're hacking together a 4-class test rig to try something out then go ahead and use a Singleton. However, as soon as that project takes on life and grows bigger and more complex then refactor the Singleton out.

Sign up to request clarification or add additional context in comments.

3 Comments

So do you mean that singletons are never eligible for use in real projects (and spotting a singleton in a real project automatically equates to code smell regardless of the use case)?
Do refrain from smelling thyself then. Your answer suggests that singletons are only used for "initial phase" code and should be factored out in all mature projects that grows bigger. So do you mean that singletons are never eligible for use in these projects, or are there valid use cases?
Very well. Singletons in real projects are a code smell, regardless of the use case and the size of the project. Using the DI pattern (with a specific container if you choose) completely negate the need for them and Singletons result in solutions that are more tightly coupled and harder to maintain in the long term.
19

Google Tech Talks had some time ago a good presentation about Global State and Singletons. The static singleton pattern is evil, because is causes unwanted side-effects and makes the code untestable. Static singleton is the OO version of global variables.

The solution is to just create one instance of the object and pass it to its users through dependency injection. DI frameworks, such as Guice, make defining the good kind of singletons easy (in Guice just annotate a class with @Singleton). There was a similar Tech Talk called Don't Look For Things! which discussed DI more.

Comments

7

In addition to the testing and design issues mentioned in other posts, there are issues with Singletons and classloaders. Singletons aren't really "single" per JVM or application - they accomplish this through the static property, which really means there is one per class. If there are multiple classloaders - like in most app servers - each separate application gets a new classloader, even multiple levels of classloaders are used in EJB. A singleton instance gets loaded per classloader - which depending on what you're doing with the singleton, may not produce the results you expect.

3 Comments

@Nate, this sounds interesting, Could you give me an concrete example?
Are there authoritative sources for your claim? Why wouldn't separate instances of JRE use separate instances of singletons?
@Pacerier oracle.com/technetwork/articles/java/singleton-1577166.html Separate JREs using separate singleton instances is the expected case - the problem is a single JRE can have multiple classloaders and thus multiple singleton instances.
3

I would use a Singleton very rarely. Due to their nature (static, global objects) they are difficult use in unit testing your code. You end up needing to do some synchronization or building in some re-initialization mechanisms so that you can get a fresh version for each unit test. There are cases that make sense -- say, for instance, a global configuration class -- but they are much fewer than people new to singleton seem to believe. I know I went through a phase where I saw applications of the singleton pattern everywhere. Now I avoid it wherever I can and undo it via refactoring in my code as I come across an unnecessary implementation.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.