Singletons are the opposite of IoC.
TDD/unit testing/mock objects rock.
Singletons subvert unit testing.
[Objective No. 1] Modularity
I'd like my application components (osgi bundles, ear-s, war-s or otherwise) to be truly separate from the rest of the system.
So that a web container could provide its own implementation of file system, console, threading API to my webapp. And a different implementation to another guy's webapp.
[Objective No. 2] Unit Testability
I'd like to unit test every bit of code I write. For every unit I test I need to mock all it's external dependencies.
I would also like to unit test 3rd party modules if need be.
What Are The Evil Singletons?
These are the complex application entities that can not be mocked for testing
- constructors, static methods, static variables (Java)
- functions (C)
Singletons so trivial that dependency on them does not violate modularity and we never need to mock them for testing either
- constants (Boolean.TRUE, Enum values)
- constructors of value types (java.lang.Integer(int))
Spring, PicoContainer, Felix (OSGI), Tuscany(SCA) all give us the blessing of IoC. J2EE also does a good job of abstracting inter-module and container services dependencies via interfaces. A small fault is that J2EE components still have to depend on certain singletons.
J2SE is more troublesome. These are the prime examples of what I'd like to mock for testing but can not
- new FileOutputStream()
- new File("a").mkdir
- all of Swing
I've long dreamed of writing alternative Java libraries. I don't have any exact design. Just an intuition of strict API/Impl separation + Spring/OSGI/Pico to tie modules together.
Another dream is to have this supported at programming language level. Each application consists of module instances. Each module declares its dependencies. The module's instantiator provides them.
Top level module instantiates and connects subordinate modules.
Subordinate modules do it recursively.
Only the top level module has access to true singletons. True singletons are operating system services like IO console thread management.
Only the top level module can provide the true singletons to subordinate modules. Subordinate modules have no way to know if they have been provided with real system services or fake ones.
Perhaps some young and daring programming language has a chance to get this right?