Wednesday 20 August 2008

Singletons are misunderstood

This post seems to echo a meme thats been floating around the developer communit for the last year : Singletons are bad. ( If you don't know what a single is, check the wikipedia definition ) .

Now I disagree with this sentiment - singletons are not pathalogical liars, they're just misunderstood. Or, more accurately, they're frequently misused or misapplied. Often you see singletons used when a developer just wants to be lazy and do something in one line. Take the example from Mr Hevery's blog :

testCreditCardCharge() {
  Database.init();
  OfflineQueue.init();
  CreditCardProcessor.init();
  CreditCard c = new CreditCard(
    "1234 5678 9012 3456", 5, 2008);
  c.charge(100);
}


Database, OfflineQueue and CreditCardProcessor are both singletons that shouldn't be . In the example of Database you'll run into trouble with that mechanism extremely quickly if you ever need more than one database connection at a time.

However take this piece of code.

testScreenCapture() throws InterruptedException {
  ScreenCaptureRobot.setInterval(1000);
  ScreenCaptureRobot.start();
  Thread.sleep(1500);
  assertTrue( ScreenCaptureRobot.isRunning() );
  BufferedImage image = ScreenCaptureRobot.getLastScreen();
  assertNotNull( image );
  ScreenCaptureRobot.stop();
}


ScreenCaptureRobot is a utility class for taking screenshots at timed intervals. It should be a singleton - you wouldn't want multiple instances of this running (it would rapidly hog resources, on windows at least). It should also be coded with the following guidelines :


  1. You must comment and do so correctly.
  2. If you must call an init() method before calling a method then say so in that methods documentation.
  3. If a method is called when it's inappropriate to do so then it should return informative errors, not ambiguous general java exceptions.


In conclusion I don't think Singletons are pathological liars, they're just misunderstood. It's true they are too easy to misuse, and extremely easy to shoot yourself in the foot with, or at least other members of your team.

No comments: