As an Agile Coach, Miško is responsible for teaching his co-workers to maintain the highest level of automated testing culture, allowing frequent releases of applications with high quality. He is very involved in Open Source community and an author of several open source projects. Recently his interest in Test Driven Developement turned into http://TestabilityExplorer.org with which he hopes will change the testing culture of the open source community. Misko is a DZone MVB and is not an employee of DZone and has posted 38 posts at DZone. You can read more from them at their website. View Full User Profile

Where Have All the Singletons Gone?

08.27.2008
| 6256 views |
  • submit to reddit

In Singletons are Pathological Liars we discussed the problems of having singletons in your code. Let’s build on that and answer the question “If I don’t have singletons how do I ensure there is only one instance of X and how do I get X to all of the places it is needed?”

An OO application is a graph of objects. There are three different kinds of graphs I think of when I design an application

  1. Collaborator Graph: This is the graph of objects that would be emitted if you serialized your application. This shows which objects are aware of which others. (through object’s fields)
  2. Construction Graph: This graph shows which object created which other ones.
  3. Call Graph: This graph shows which other methods each method calls. A stack-trace would be a single slice through this graph.

If the new operators are mixed with application logic (see: How to Think About the new Operator) then the Constructor Graph and the Collaborator Graph tend to be one and the same. However, in an application which uses Dependency Injection the two graphs are completely independent. Lets have a closer look at our CreditCardProcessor example. Suppose this is our collaborator graph which we need to execute a request.


The above shows the application collaborator graph. The letter (S/R) in the corner designates object lifetime; either Singleton or Request scope. Now, just to be clear, there is nothing wrong with having a single instance of a class. The problem arises only when the singleton is available through a global “instance” variable as in Singleton.getInstance().

The HTTP request would come to AuthenticatorPage which would collaborate with Authenticator to make sure the user is valid and forward a valid request onto ChargePage which would then try to load the user from UserRepository and create the credit card transaction which would be processed by CrediCardProcessor. This in turn would collaborate with OfflineQueue to get the work done.

Now, in order to have a testable codebase we have to make sure that we don’t mix the object construction with application logic. So all of the above objects should rarely call the new operator (value objects are OK). Instead each of the objects above would declare its collaborators in the constructor. AuthenticatorPage would ask for ChargePage and Authenticator. ChargePage would ask for CreditCardProcessor and UserRepository. And so on. We have moved the problem of construction elsewhere.

In our tests it is now easy to instantiate the graph of objects and substitute test-doubles for our collaborators. For example if we would like to test the AuthenticatorPage, we would instantiate a real AuthenticatorPage with mock ChargePage and mock Authenticator. We would than assert that a request which comes in causes appropriate calls on Authenticator and ChargePage only if authentication is successful. If the AuthenticatorPage were to get a reference to Authenticator from global state or by constructing it, we would not be able to replace the Authenticator with a test-double. (This is why it is so important not to mix object construction with application logic. In the unit-test what you instantiate is a sub-set of the whole application. Hence the instantiation logic has to be separate from application logic! Otherwise, it’s a non-starter.)

So now the problem is, how do we construct the graph of objects?

In short we move all of the new operators to a factory. We group all of the objects of similar lifetime into a single factory. In our case all of the singletons end up in ApplicationFactory and all of the Pages end up in RequestFactory. The main method of our application instantiates an ApplicationFactory. When we call build() the ApplicationFactory in turn instantiates its list of objects (Database, OfflineQueue, Authenticator, UserRepository, CreditCardProcessor and RequestFactory). Because each of the objects declares its dependency, the ApplicationFactory is forced to instantiate the objects in the right order. In our case it must instantiate the Database first and than pass the reference to UserRepository and OfflineQueue. (The code will simply not compile any other way.)

Notice that when we create a RequestFactory we must pass in references to the Authenticator, UserRepository and CreditCardProcessor. This is because when we call build() on RequestFactory it will try to instantiate AuthenticatorPage which needs the Authenticator. So we need to pass the Authenticator into the constructor of RequestFactory and so on.

At run-time an HTTP request comes in. The servlet has a reference to RequestFactory and calls build(). The servlet now has a reference to the AuthenticatorPage and it can dispatch the request for processing.

Important things to notice:

  • Every object only has references to what it needs directly! No passing around of objects which are not directly needed by the code. There is no global state at all. Dependencies are obvious since each object only asks for what it needs.
  • If an object needs a reference to a new dependency it simply declares it. This change only affects the corresponding factory, and as a result, it is very isolated.
  • All of the new operators end up in the factories; application logic is devoid of new operators.
  • You group all of the objects with the same lifetime into a single factory (If the factory gets too big you can break it up into more classes, but you can still think of it as a single factory)
  • The problem of “how do I ensure that I only have one of something” is nicely sidestepped. You instantiate only a single ApplicationFactory in your main, and as a result, you only instantiate a single instance of all of your singletons.

Now the factories become largely a series of object creations. Totally boring stuff, so boring a computer could generate the code. Simply look at the constructor and recursively instantiate whatever the constructor wants. Wait, a computer can generate it! Its called PicoContainer or GUICE! So you don’t actually have to write the factories.

From http://misko.hevery.com/

Published at DZone with permission of Misko Hevery, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Silvio Bierman replied on Wed, 2008/08/27 - 12:50pm

The main reason why singletons are not a usable concept is that they trie to address a problem with a scope that transcends the programming language level. What does it mean that you want "only one instance" of a certain class? One instance in the whole universe, one per server, one per application process or thread or perhaps one per class loader instance (when using Java)? These all require different implementations, also depending on language semantics.

Second, there are few concepts that are natural and suitable candidates for being turned into a singleton. There is only one sun, for example. Many uses of singletons reflect an application limitation design choice like designing an application in such a way that it can only work with a single database instance at a time (whatever that means). The "database object" is then turned into a singleton thus casting in stone a design decision that might very well be regretted once the application needs to be run in a different environment (turning a desktop aplication into a multi-organization web-application, anyone?).

I have come across many situations where singletons in any form had to be factored out of legacy code to allow for newly required flexibility. This was always a tedious process. In my opinion singletons are an evil concept.

 

 

Silvio Bierman replied on Wed, 2008/08/27 - 12:51pm in response to: Silvio Bierman

Of course I meant to write "try" instead of "trie".

Porter Woodward replied on Wed, 2008/08/27 - 12:52pm

Suggest using an Enum to provide Singleton behavior.

Enum's are classes... And even better than the approaches using private constructors with a public field: they provide an ironclad guarantee against multiple instantiation, even when dealing with serialization and/or reflection. (See Effective Java 2nd Ed. - Joshua Bloch)

Granted this approach requires the use of 1.5 - but honestly it's long past time to move on to 1.5.

Porter Woodward replied on Wed, 2008/08/27 - 12:58pm in response to: Silvio Bierman

Singletons may be evil - they may not be.

A singleton can be useful when representing something that there really is only one of.  Usually some sort of system resource.  Maybe you want to make sure you _only_ have _one_ clock, or perhaps a file system or some other unique system resource.

Overuse of singletons is evil.  Judicious, considered use of singletons serves a purpose. 

Silvio Bierman replied on Wed, 2008/08/27 - 1:45pm in response to: Porter Woodward

A programs surroundings provides abstractions for stuff like a system clock or a file system. It is very conceivable that an application that uses "the filesystem" or "the clock" might be extended in the future to use multiple (abstractions of) filesystems or system clocks.

Representing such concepts as singletons offers no structural advantage whatsoever. The only superficial advantage is that it saves the programmer the hassle of dragging around references to "a filesystem" and "a system clock" in method parameters and class fields.

As such a singleton is no more than a repackaged global variable.

 

replied on Thu, 2008/08/28 - 1:34am in response to: Silvio Bierman

Hmmm, I don't think Singletons are evil. They serve a purpose: to guarantee that there is only one instance of a class exists. At least in the sense that you have to make extra steps to instantiate another instance of it. This largely eliminates those bugs when someone forgets about the importance of having only one instance of a given class, instantiates another one causing endless debugging sessions. The reasoning that the concept may be "extended" in the future is broken in my view. Whatever application you are developing you have to make decisions about the scope of it, otherwise you'll never have a "ready" application. This reasoning can be used for normal (I mean non-singleton) classes, too. One can reason that you have to design you class structure to be as generic as possible to enable any kind of foreseeable or not foreseeable "extension" of it, but you'll soon realize that in many cases that kind of generic design is simply not needed (the application will never be extended that much) or that making everything generic just takes too much time and effort and your deadline is quickly getting closer. So I think Singletons serve a purpose, you'd better know the limitations, and sharp statements (evil, useless, etc.) are rarely true. At least this is my view :-)

Alexander Shirkov replied on Thu, 2008/08/28 - 3:42am

Singletons have many faces. As for me, I don't like "classic" singleton - with private constructor, static instance field on getInstance() method. The main reason why - it's difficult to test them. I prefer to have Spring-managed "singletons" - when classes by semantics is simple JavaBean, but in usage acts as singleton.

Silvio Bierman replied on Thu, 2008/08/28 - 8:51am in response to:

Your remark about "only one instance" was covered by my first remark about the lack of proper definition of "only one". Preventing instantiation can easily be done by only exposing an interface paired with a reference to an implementing instance to the general application code. The number of implementing instances can then be controlled at a central point.

It is obvious applications have to be definied with certain fundamental limitations in mind. But implementing a database backend, application configuration property set or internationalized text pool as a singleton is a pointless limitation of the applicability of the resulting application code. Running the same code inside a Web application container where each session (determined by session login parameters) uses a different database, configuration proerties and end user language would become impossible. This would simple have been prevented by not representing these as a singleton.

There is no additional cost or complexity involved in not using singletons. As soon as you start writing server based applications for multiple users across muiltiple organizations you experience that very few good singleton candidates exist. Once you have ported a single user desktop application using singletons in mentioned areas to a multi user server level you will probably think twice before introducing a new singleton.

 

replied on Thu, 2008/08/28 - 9:38am in response to: Silvio Bierman

Well, I think it depends on what you are trying to achieve. I'm only working on server side development projects (although trying to avoid web development as much as possible, I concentrate on backend development) and usually am using singletons for utility classes, helpers, etc. where there is really no point having more than one instance of a class, but if there are more than one is usually not a problem either (it is just unnecessary and uses more resources).

It is always a decision whether you use singletons or not and I don't think they should be avoided in general. You might be right about database, etc. cases, but again, it is not uncommon to use only one database for an extended period of time. We have applications at a large mobile operator in use for more than 10 years, still using the same and only database.

My experience is that it is really difficult to advise that some programming concept is evil. Such a statement can be true for the majority of the cases but there are always circumstances where the best way is to use an otherwise "evil" solution (e.g. the often mentioned "goto" is a very useful construct for complex calculations where you need a way to jump from deeply stacked for cycles to an outer cycle - surely it can be done without using goto, but the code is more complex and just a lot less maintenable).

Anyway, as usual, only my view :-)

Silvio Bierman replied on Thu, 2008/08/28 - 10:11am in response to:

I think a singleton will cost you more than creating separate instances of helper classes. In case these even need intermediate state the singleton will immediately introduce a thread safety issue.

I totally agree on being pragmatic. Even more so, I do not like the rigid and dogmatic application of so called best practices like those from the infamous Design Patterns book, especially when (the application of) the basic concept of the pattern introduces more problems than it was meant to solve. If you look at http://en.wikipedia.org/wiki/Singleton_pattern you will find some resources created by people who share my view on singletons.

 

replied on Thu, 2008/08/28 - 11:16am in response to: Silvio Bierman

Actually no. Most of the time I use singletons for stateless stuff, so there is no need for synchronization. The other use is a kind of a pool or store (e.g for statistics, etc.), but in those cases it is usually difficult, if possible at all, to avoid synchronization anyway, so there is no extra penalty with using singletons :-)

I checked some of the blogs referred by wikipedia, but I have to tell you that they only focus on a very narrow way of using singletons (mainly to prove their own points) and dismiss other uses.

Anyway, I find singletons useful, you just have to know the limitations :-)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.