Thursday, February 14, 2008

Singletons Make Me Crazy

I think there are two types of Java Programmers, those that use 'singletons' and those that don't.

I put singletons in quotes, because 99% of singletons implemented follow the singleton implementation pattern without the singleton goal as the objective.

From wikipedia (http://en.wikipedia.org/wiki/Singleton_pattern)

"In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object."

Instead of having the goal of restricting instantiation, the vast majority of singletons are implemented to access part of the system that is non local. You see, a mere side affect of having only a single instance of an object in a system is that they are usually accessible globally throughout the system, and singleton misusing programmers use this otherwise legitimate attribute of singletons to justify letting any part of there programs talk to any other part of there programs in a tightly coupled way.

If this conjures images of a plate of spaghetti with strands weaving every which way, then we are on the same page.

Good Object Oriented Design


Object Oriented Programs have been around for a while now, and while we are seeing significant changes with things like dynamic languages, the basis of good Object Oriented design holds true and constant.

Relationships between objects should minimize coupling and maximize cohesion.

For example, my TV has high cohesion with my DVR and with that comes a certain level of coupling. To upgrade to HD, I had to replace both. There is some coupling, but the designers of the TV and the DVR work hard to minimize it so that internal changes to one doesn't result in breaking the other. This means that the two components can change independently, but it also means the TV can work with DVRs from different manufacturers and vice versa. They achieve minimal coupling by communicating through a well defined protocol that doesn't expose the internals.

Working with the TV/DVR metaphor, consider the singleton again. Lets say for example that the DVR programmers decide that they need a singleton inside there system. Because it is globally accessible, nothing stops the TV programmers from accessing it, and if they do, the high cohesion, low coupling design collapses.

Yes, it is more important to minimize coupling across external components, but the same principle applies to components within the system. It applies for the same reason... with minimal coupling you can change or replace subsystems without affecting other subsystems.

Good Singleton Design


Here are my good singleton design guidelines.

  1. Singletons should be implemented only to achieve the goal of a single instance. Some single state or thing should be the basis for this objective. An example might be a Registry, Message Bus or Data Cache.

  2. Singletons should only expose high level concepts and information, or should only be used within the scope of the subsystem.

  3. Direct Access to singletons should be minimized and replaced with dynamic alternatives when appropriate. For example, instead of having 10 classes in a subsystem access a singleton directly, have the root, or the entry point access the singleton directly and then pass between classes or assign it somewhere locally accessible within the subcomponent.



Conclusion


So why do programmers abuse singletons? Many of them don't understand coupling and dependencies or just don't feel about it the way that I do. Even for the ones that do, as systems evolve, its very difficult to keep everything organized so subsystems communicate with other subsystems in low coupling/high cohesion kind of way. You have to continuously evolve and adapt the structure of the system and that takes lots of time and energy. When your customer just wants to get X feature out the door, the singleton shortcut becomes very tempting.