SitePoint Sponsor

User Tag List

Page 1 of 4 1234 LastLast
Results 1 to 25 of 79
  1. #1
    Non-Member melancholic's Avatar
    Join Date
    Nov 2004
    Location
    Australia
    Posts
    447
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Why is the singleton pattern bad?

    Hey guys,

    Been reading through a few posts and got the consensus that singletons are bad/evil/shouldn't be used.

    As I saw it, the singleton pattern was the workaround for objects that required global access such as the registry, service locator, abstraction layers and other objects of the like.

    To my understanding, it stopped being evil because you had control of what goes in it. On the flip side of the coin I can understand why it could be evil. Worst case scenario, you could end up with a singleton riddled application, well that and kyberfabriken's OO purist point of view (it's a process call) .

    Other than reasons listed above, are there any other reasons why the singleton is bad and should be "avoided like the plague"?

    Thanks in advance,

  2. #2
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    http://c2.com/cgi/wiki?SingletonsAreEvil is a good starting place to look.

    The main problem I have with them is like any other global variable, they make testing much harder. The problem is that of Dependency Injection. If the code creates the object you are using by using the hard coded singleton factory, then how to you get a mock object in place of the singleton resource?
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  3. #3
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's hard coupling.

    Singletons are essentially static functions - the difference is syntactical sugar. Whenever you reference a static symbol in your code, you make it more dependent on the context. It's really the same as with a global variable - A global variable is bad because it has a global scope. A static function is also global in scope, so it has the same problems associated. The difference between the two, which accounts for the assumption that singletons are slightly better than global variables, is that functions are more abstract than variables, and this gives you some flexibility. This flexibility can then be used to excersise some damage control. Still it can't beat narrowing the scope, which is what objects provides. (Among other things)

  4. #4
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Surely it depends entirely upon the context it's used in right? I've heard a lot of this singletons are evil lark but I'm still to be convinced. It's easy to go nuts with 'em when you first see the few advantages if you're using the same object all over the place (database?) but used correctly they are useful right?

    I'm not sure how bad this is (no doubt stupid) but I have a habit of placing configuration data in a singleton and using that throughout my application as a config object... I've done this with an inherited registry before too.

    EDIT | To expand on the config object in a singleton thing: I consider configuration directives as a set of defaults, not necessarily entities that cannot be modified at run time. If something config-wise change I want the rest of my application to pick up these changes quickly... a singleton gives me that option... what should I be using?

  5. #5
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Whilst I prefer not to use singletons, not sure its that hard coupling in a scripting context. As ultimately a singleton is included/required in, so can various implementations can be swapped in and out.

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    Whilst I prefer not to use singletons, not sure its that hard coupling in a scripting context. As ultimately a singleton is included/required in, so can various implementations can be swapped in and out.
    Not out - you can't redefine a static function.

  7. #7
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's my understanding from what I've read that Singletons are not necessarily bad, but too many is a bad sign. There certainly are objects that all or most of the application wants to have. What is better, passing it around for the sake of passing it around or having it available through a universal lookup? I don't know but in such cases I use the universal lookup (Object Registry).

    Here's an example that may not be unrealistic. A programmer has been trained to such an extend that global objects are bad, and he is programming a database heavy application. So rather than having just one global object, or placing it in a registry (which then becomes your one global object), every time he needs to use the database, he re-establishes a connection. I don't know about you, but I'd fear having such a person program for me. Any resistance one may have associated with the implications of having that object be global are blown clear off the planet by the very real and dramatic performance hit the application will take from re-connecting to the database several times during each request.

    I guess I'm just rambling, but you know never say never.

    I'm not sure about saying that patterns are bad because they are harder to test either. I agree that Singletons are generally bad, but not on that basis. I don't really think that is much of a basis, no offense. As technology improves, inevitably testing will become harder as programming languages become more complex and "intelligent" than ever before. Does that mean that new programming techniques that will inevitably be developed be bad? Perhaps, but only if you believe that something like the Matrix will come out of it.

  8. #8
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Not out - you can't redefine a static function.
    You can't have two class names the same either, so you can only have one "included" at any one request/run. But still allows replacing a singleton with a mock implementation for instance.

  9. #9
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    You can't have two class names the same either, so you can only have one "included" at any one request/run.
    Instantiation is also hard coupling for that exact reason. You can replace it with a factory or use dependency injection.

  10. #10
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Instantiation is also hard coupling for that exact reason. You can replace it with a factory or use dependency injection.
    Or a simple service locator.

  11. #11
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    It's my understanding from what I've read that Singletons are not necessarily bad, but too many is a bad sign.
    Well - the more the merrier. One global variable isn't going to crash your application, but they add up.

    Quote Originally Posted by dreamscape
    A programmer has been trained to such an extend that global objects are bad, and he is programming a database heavy application. So rather than having just one global object, or placing it in a registry (which then becomes your one global object), every time he needs to use the database, he re-establishes a connection.
    Clearly that's a mistake. Replacing one global with a multitude of instances isn't comparable.

    I do think I get your point though - Decoupling is good for some things (it makes your application more flexible), but it comes at a certain cost - As the code becomes more abstract, it demands more interpretation by the programmer. I'd claim that it's kind of the same way that objects are harder to understand than functions, and functions are harder to understand than scripts.

    Quote Originally Posted by Ren
    Or a simple service locator.
    Yes, certainly. I kind of think of that as a form of factory, but it could also be a registry, so I guess it's a distinguished type. The point though, is that it decouples the dependency on the static constructor.

  12. #12
    SitePoint Member
    Join Date
    Jan 2006
    Location
    Norway
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I do not believe, or fall for the: Singletons are always evil mantra.
    The Singleton pattern has its usage, however as pointed out in this topic it clearly has its drawbacks.

    One situation I use a singleton is when I implement an application flow tracker. A simple class which just set that a object was initialised or similar.

    So instead of writing:
    PHP Code:
    $tracker Registry::retrieve('tracker');
    if (
    tracker->isEnabled) {
        
    $tracker->setStatus('Exception_Handler','initialising');

    in every class and method where you want to track a behaviour, I write:
    PHP Code:
    if (Tracker::isEnabled) {
        
    Tracker::setStatus('Exception_Handler','initialising');

    Although using a singleton will only remove one line. One line less to write 100 or 1000 times do make a difference.

    Also such a simple singleton class as my Tracker class:
    PHP Code:
    <?php
    class Tracker {
        private 
    $enabled true;
        private static 
    $instance null;
        
        private function 
    __construct() { }
        
        private static function 
    getInstance() {
            if(!
    self::$instance instanceof self) {
                return new 
    self();
            }
            return 
    self::$instance;
        }

        public static function 
    isEnabled() {
            
    $instance self::getInstance();
            return 
    $instance->enabled;
        }
        public static function 
    setStatus($id,$msg) {
            
    $instance self::getInstance();
        .........
       }
    .....
    does not have any effect on my unit tests in the classes where it is used, since it does not alter the behavoir of the class.

    Disclaimer.......
    This was the best example I could come up with 03:40 in the morning

  13. #13
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  14. #14
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by Fjoggen
    One situation I use a singleton is when I implement an application flow tracker.
    What is this? Are you just writing a debugger into your application? I'm genuinely curious.

    Quote Originally Posted by Fjoggen
    This was the best example I could come up with 03:40 in the morning
    I think it is very hard to come up with a situation where global data is good. For Singletons I think it is impossible.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  15. #15
    SitePoint Member
    Join Date
    Jan 2006
    Location
    Norway
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    ......
    I think it is very hard to come up with a situation where global data is good. For Singletons I think it is impossible.
    ....
    Well I believe there are situations where one should use a Singleton. I think it is worse to decide on before hand: I will never use a Singleton! than to look at what does the job best in this situation. As was the case with my Tracker class. However I agree that usually a Singleton isn't the right choice.





    Danger Off Topic
    Quote Originally Posted by lastcraft
    What is this? Are you just writing a debugger into your application? I'm genuinely curious.
    ......
    It's purpose is to help a user optimise the application, so basically it is a debugger.

    I and a couple of others are designing a mulitplayer logfile parser/ statistics generator, where the log files in question can be from 3KB to 1GB and bigger. That in it self is quite easy. However the statical analysis of all the data is sometimes to much of a burden for a shared host or a old server. Especially when you realise that the script isn't finish after 0.001 second as a normal php script. So the purpose of the application flow tracker (in lack of a better description) is to give users a overview of the performance of each process.Which then can help them change configuration options, such as:
    • How many players should be updated before the application frees all memory and starts over.
    • Is the server fit enough to analyse everything at once.
    • etc.

    Also when running the parser in debug mode the application will terminate when a set criteria is hit and present performance info,

    Additional it is used in the process of tuning the statistical algorithm as a supplement to other debugging tools (dbg, etc).

    We are using some mathematical expression which the founders of php probably didn't have in mind when they created php. Fortran isn't my favourite language, but with heavy mathematical calculations it is a quite better tool than php.

    Not exactly something I need in my everyday php application. To be honest I am not convinced php is the right tool for the job.

    Edit
    It is not designed to replace DBG or even be used actively in the production of the application, but a tool for users to tune the application configuration.
    Last edited by Fjoggen; May 29, 2006 at 22:30.

  16. #16
    SitePoint Addict
    Join Date
    Apr 2002
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I just love to make my sql connection object singleton in PHP so I can connect once then use the reference in functions without passing an object in the parameter as a reference. It's less clutter. I had no problems with this. Of course I wouldn't just make all my classes like this unless they only need to be instantiated once.

  17. #17
    SitePoint Member
    Join Date
    May 2006
    Location
    Saratov, Russia
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What if later you decide to reuse a class in another application? If the class accesses the database through Singleton's instance operation, it's hard to reuse it in an application that passes the database connection around.

  18. #18
    SitePoint Member
    Join Date
    May 2006
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey Dude !!!!

    Singleton is evil ?? hey common buddy !!! its essential.. go back and brush up the basics of design pattern :-).. What is Most widely used Design Pattern of all ??

  19. #19
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think people will always at some point down the line find a way to make something "evil". Use it correctly and it's fine.

    ~ArtGor - come on it's hardly rocket science to take out the static stuff and make the constructor public so you can use multiple instances

  20. #20
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    It's hard coupling.

    Singletons are essentially static functions - the difference is syntactical sugar. Whenever you reference a static symbol in your code, you make it more dependent on the context. It's really the same as with a global variable - A global variable is bad because it has a global scope. A static function is also global in scope, so it has the same problems associated. The difference between the two, which accounts for the assumption that singletons are slightly better than global variables, is that functions are more abstract than variables, and this gives you some flexibility. This flexibility can then be used to excersise some damage control. Still it can't beat narrowing the scope, which is what objects provides. (Among other things)
    It's not the "same" as a global variable, singletons do have their advantages in certain systems and any software should be "context dependant" imho.

    So if 50% here tells you they are indeed bad, and you are reading that page your not gonna use it ?

    Why bother about it in the first place, i have several sources here which cover more then 20 pages about the singleton pattern so there must be a need for them, i use them in .net through a message object (soap) cause you should only have on request to the message object.

    andaahh, .... iSingleton rings a bell.... just to save you from your "oh no dont go global" issues...
    Business as usual is off the menu folks, ...

  21. #21
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ArtGor
    What if later you decide to reuse a class in another application? If the class accesses the database through Singleton's instance operation, it's hard to reuse it in an application that passes the database connection around.
    Erm,..... right, but then again this is not the intention of this (or any other) pattern, to support you with a database connection (or any other implementation details), it's a "pattern"... so dont see it as a piece of your software but more as a solution to a common problem within your software.
    Business as usual is off the menu folks, ...

  22. #22
    SitePoint Zealot
    Join Date
    Jan 2005
    Location
    Romania, Iasi
    Posts
    119
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One can make a class that can behave as a singleton or as a 'normal' class, like
    PHP Code:
    $a something::instance();
    $b something::instance(); 
    will give two different objects and
    PHP Code:
    $c someting::instance('etc');
    $d someting::instance('etc'); 
    will give the same objects...

    I'm using something like this to create database connections. In this way i can use one or mutiple connections without recreating the connection each time. I have best of both worlds with some minor incoveniences.

  23. #23
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What is the problem in using the Registry pattern? This way there is a singleton (the registry), but every specific item is an instance. Unless, of course, you want to go the full dependency injection way, which is often an overkill in PHP, IMO.

  24. #24
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Galo
    It's not the "same" as a global variable
    I don't think I said that. I said that it's a static function.

    Quote Originally Posted by Galo
    So if 50% here tells you they are indeed bad, and you are reading that page your not gonna use it ?
    I'm not following you ? I don't believe that the number of people who say something have much value over people using rational arguments.

    Quote Originally Posted by Galo
    Why bother about it in the first place, i have several sources here which cover more then 20 pages about the singleton pattern so there must be a need for them
    What kind of argument is that ?

    Quote Originally Posted by Fjoggen
    Well I believe there are situations where one should use a Singleton
    If the choice is between a global variable and a singleton, I would choose the singleton. In a perfect world I wouldn't use any of them. However, I realize that there is a chasm between theory and practice.

  25. #25
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Fjoggen
    So instead of writing:
    PHP Code:
    $tracker Registry::retrieve('tracker');
    if (
    tracker->isEnabled) {
        
    $tracker->setStatus('Exception_Handler','initialising');

    in every class and method where you want to track a behaviour, I write:
    PHP Code:
    if (Tracker::isEnabled) {
        
    Tracker::setStatus('Exception_Handler','initialising');

    Actually I would claim that neither of thoose two represent a singleton. The first is a registry and the second is a static function.

    To complete the picture, this is a singleton :
    PHP Code:
    $tracker Tracker::getInstance();
    if (
    tracker->isEnabled) {
        
    $tracker->setStatus('Exception_Handler','initialising');



Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •