• JBert (disco)

    I heard the illustrious Gang of Four wanted to include this as the Simpleton pattern, though in the end they just thought it would set a bad precedent.

  • PJH (disco)

    Is Tinder like Grindr, only with the requisite number of vowels?

  • JBert (disco) in reply to PJH

    What's with the hate agaist disenvoweled brand names? Don't you know you can never be successful if your brand has more than 6 characters‽

  • PJH (disco) in reply to JBert
    JBert:
    What's with the hate **agaist** disenvoweled brand names?

    I'm more interested in the recent popularity with misspelt words in general. Especially on here...

  • TheCPUWizard (disco)
    1. Of course that is not a Singleton class...

    2. Did you know that the Singleton Class (as opposed to other patterns which manage instancing) is now considered an anti-pattern??? This is especially true of the Meyers Singleton implementation (which this post shows a broken implementation)

  • Michael_Mahn (disco) in reply to TheCPUWizard
    TheCPUWizard:
    2) Did you know that the Singleton Class (as opposed to other patterns which manage instancing) is now considered an anti-pattern??? This is especially true of the Meyers Singleton implementation (which this post shows a broken implementation)

    Everything has its people who "consider it harmful" or an anti-pattern. But I would would not say that it's common sense under software developpers that singleton is an anti-pattern. It's overuse maybe.

  • gleemonk (disco)

    Using this abortion of an implementation would mean you first have to call the constructor, then getInstance()?

    new SingletonSmtpClient('home', 'rose', 'hunter2', False);
    SingletonSmtpClient smtpClient = SingletonSmtpClient.getInstance();
    

    And you would have to do this everytime you wanted the instance? The first line was likely done when loading, then just calling getInstance() whenever. Or, anything else would be an even bigger WTF.

  • TheCPUWizard (disco) in reply to Michael_Mahn
    Michael_Mahn:
    Everything has its people who "consider it harmful" or an anti-pattern. But I would would not say that it's common sense under software developpers that singleton is an anti-pattern

    Most developers who actively study, publish and utilize Design Pattern based development strongly consider it an anti-pattern. Of course when you add in all the cargo-cult followers their numbers are dwarfed. Here are just a few of the many reasons:

    1. It is very rare that at the conceptual level only one instance of a type of thing can ever exist across the universe.

    2. Most implementations are NOT thread-safe, and the vast majority of "locking" implementations introduce significant overhead, which leads to caching, which leads to GC impact.

    3. A Singleton Class is very hard to test properly at all levels (ranging from unit tests on the class itself to integration classes and DI issues)

    4. In a FullTrust environment the implementations to not actually "Ensure" anything. It is just syntactic aspartame (tastes, like sugar, but can actually have negative health effects)

    There are so many alternatives that have been created in the 20 years since the book was published (which was just supposed to be a representative sample of patterns that worked well in the environments that the authors work in at the time - not a global "holy book").

  • Maciejasjmj (disco) in reply to TheCPUWizard
    TheCPUWizard:
    Design Pattern based development

    Which is, ironically, an antipattern in itself.

    TheCPUWizard:
    alternatives

    Mostly revolve arount bloated, parasitic and spooky action at a distance-fueled DI frameworks, from what I've seen.

  • martijntje (disco) in reply to TheCPUWizard

    You're just listing reasons not to use Java. In a properly designed language none of this applies. Take C++ for example. Initializing a static variable is - by definition - thread safe. The standard gives you this for free. Trying to access a static variable from multiple threads will just make them wait.

    I don't see it as syntactic sugar only. It is a convenient way to make sure a certain initialization happens only once, where the code might be included - or even linked to - multiple times.

  • boomzilla (disco) in reply to gleemonk
    gleemonk:
    Using this abortion of an implementation would mean you first have to call the constructor, then getInstance()?

    The scariest thing to me is that they might be calling the constructor in different places with different parameters.

  • gleemonk (disco) in reply to boomzilla
    Comment held for moderation.
  • Severity_One (disco)

    The Java developers (both local and off-shore) that I have to work with really, really, really love a so-called Resources class. It contains static references to about anything you might be needing. I wish I had the authority to mete out corporal punishment for bad coding practices.

  • CoyneTheDup (disco)

    How art thou broken, let me count the ways.

    1. Thou art a singleton where a singleton be-ist not needed.
    2. Thou must be instantiated as an object to create they singleton.
    3. Thou getInstance() method dost not get an instance in every case.
    4. Thought art be-ist a tenant in common SMPT client, which icht beink insanity mus. . . . . . [author disconnected]
  • Martin_Tilsted1 (disco) in reply to TheCPUWizard

    1: True, but that does not make it an anti pattern. That makes it a pattern which should only be used in cases where you need to ensure that there is only one instance. This is sometimes exactly what you need.

    2: You can't blame the pattern for the fact that someone implemented it badly. And the locking issue is not larger then for other objects you want to access in multiple threads. Besides synchronized in Java is really really cheep, as long as nobody holds the lock, so just making the method get() synchronized is not a problem. Remember we are talking about a language, where most methods in StringBuffer and Vector are synchronized*

    But I don't see how caching causes problems for the gc. The singleton should not really be garbage collected in most cases because its lifetime will be the same as the program itself. But even if our singleton has a clear() method, why do you care exactly when it will be garbage collected. The exact time the object will be garbage collected, should not affect the program at all. Unless you have a finalize in the Singleton but in that case: Please submit to the daily wft, because that would be insane.

    3: There is nothing difficult about testing the Singleton class itself. You just call get(), and test it as any other object you want to test.

    Where you can get problems is that, if you are running multiple tests, they may change the singletons state, so in worst case a test might fail if and only if, an other test have been running before which changed the state of the singleton.

    *Which as Sun realized was a major wft, so they created new classes with mostly the same methods, but no synchronization.

    TheCPUWizard:
    Most developers who actively study, publish and utilize Design Pattern based development strongly consider it an anti-pattern. Of course when you add in all the cargo-cult followers their numbers are dwarfed. Here are just a few of the many reasons:
    1. It is very rare that at the conceptual level only one instance of a type of thing can ever exist across the universe.

    2. Most implementations are NOT thread-safe, and the vast majority of "locking" implementations introduce significant overhead, which leads to caching, which leads to GC impact.

    3. A Singleton Class is very hard to test properly at all levels (ranging from unit tests on the class itself to integration classes and DI issues)

    4. In a FullTrust environment the implementations to not actually "Ensure" anything. It is just syntactic aspartame (tastes, like sugar, but can actually have negative health effects)

    There are so many alternatives that have been created in the 20 years since the book was published (which was just supposed to be a representative sample of patterns that worked well in the environments that the authors work in at the time - not a global "holy book").

  • Bulb (disco) in reply to PJH
    PJH:
    I'm more interested in the recent popularity with misspelt words in general. Especially on here...

    Misspelt words make good brand names, because they are Googleable. When you search such brand, it won't return zillions of completely unrelated results even if you don't further specify what about it you want. Given how many people don't remember domain names and rely on search it is an important advantage.

  • Magus (disco) in reply to Bulb

    Which is why Microsoft really should have called it the Srfc.

  • Bulb (disco) in reply to Magus

    Microsoft is large enough that they can afford not to follow this, because when they publish something, it will quickly gather enough links to make it to the first page of the generic search. Smaller companies don't.

  • PJH (disco) in reply to Bulb
    Bulb:
    Misspelt words make good brand names, because they are Googleable.
    [image]
  • tarunik (disco) in reply to Martin_Tilsted1

    The problem with singletons and testing is that the singleton winds up coupled to its clients, making it very hard to replace it with a mock, test implementation, or anything of the sort.

  • Jaime (disco) in reply to tarunik

    True, but many singletons don't need to be mocked. There's not much point in creating a mock for a method like HashSHA512(string s).

  • Bulb (disco) in reply to PJH

    Google is shooting themselves in the foot, because googleable is a perfectly cromulent word:

    [image]
    as is, of course, cromulent [image]
  • TheCPUWizard (disco) in reply to Martin_Tilsted1
    Martin_Tilsted1:
    1: True, but that does not make it an anti pattern. That makes it a pattern which should only be used in cases where you need to ensure that there is only one instance. This is sometimes exactly what you need.
    Something is an anti-pattern when it is demonstrated to cause more problems than it solves (compared to alternatives).

    Show concrete examples of where there is a real world "type" that there should only ever be one instance in the universe. IT is a fallacy. There may be cases where you want to ensure things within a given environment/scope use the same instance - but this is not "the universe".

    2: You can't blame the pattern for the fact that someone implemented it badly. And the locking issue is not larger then for other objects you want to access in multiple threads. Besides synchronized in Java is really really cheep, as long as nobody holds the lock, so just making the method get() synchronized is not a problem. Remember we are talking about a language, where most methods in StringBuffer and Vector are synchronized*
    I agree about the implementation not being the issue. I was actually thinking .NET (where I have extensive experience) rather than Java (where I have moderate experience), so I will concede the point for Java

    But I don't see how caching causes problems for the gc. The singleton should not really be garbage collected in most cases because its lifetime will be the same as the program itself. But even if our singleton has a clear() method, why do you care exactly when it will be garbage collected. The exact time the object will be garbage collected, should not affect the program at all. Unless you have a finalize in the Singleton but in that case: Please submit to the daily wft, because that would be insane.

    Every variable that can hold a reference type must be examined during a Gen2 GC. Declare a variable, or field within an instance and even when it is set to null there is a (very tiny) impact on GC. It has nothing to do with the collection of the object itself, and (almost) everything to do with the work required to scan for what objects are reachable. [there is also the cost of an item being copied internally as it progresses through the generations]

    3: There is nothing difficult about testing the Singleton class itself. You just call get(), and test it as any other object you want to test.

    Where you can get problems is that, if you are running multiple tests, they may change the singletons state, so in worst case a test might fail if and only if, an other test have been running before which changed the state of the singleton.

    Try writing robust concurrent tests (many tests running at the same time) against a single instance. It is virtually impossible (if the object maintains any state - and if it is stateless, why is it an instance?). Speed of execution is critical for things such as gated check-in testing.

  • FullPointerException (disco) in reply to tarunik

    Just make it a doubleton then. Have 1 real implementation, and 1 test double. Problem solved. /s

  • tarunik (disco) in reply to Jaime
    Jaime:
    True, but many singletons don't need to be mocked. There's not much point in creating a mock for a method like HashSHA512(string s).

    But that doesn't need to be a singleton, either -- it's perfectly fine living on its own as a free function. ;)

    FullPointerException:
    Just make it a doubleton then. Have 1 real implementation, and 1 test double. Problem solved. /s
    :trolleybus: ?
  • Bulb (disco) in reply to martijntje
    martijntje:
    You're just listing reasons not to use Java. In a properly designed language none of this applies.

    QFT. Half of the Holy Design Patterns™ exist to work around lack of more straightforward tools in Java. Conceptually they are used in other languages as well, but they are so trivial and obvious there that nobody bothers mentioning them.

    martijntje:
    Take C++ for example. Initializing a static variable is - by definition - thread safe.

    Non-acknowledge. File-scoped and class-static variables are initialized during global startup and by then there usually are not other threads, so it is thread safe just because of that. But function-static variables are initialized on first invocation of the containing block and that is not thread-safe.

    martijntje:
    Trying to access a static variable from multiple threads will just make them wait.

    No, it will not. C++ does not synchronize anything on its own.

    boomzilla:
    The scariest thing to me is that they might be calling the constructor in different places with different parameters.

    … and the first set of parameters will be used. Where which will be used first may not be well defined…

    Jaime:
    True, but many singletons don't need to be mocked. There's not much point in creating a mock for a method like HashSHA512(string s).

    There is not much point in making a hashing function a singleton either. A static method is just fine for that.

  • boomzilla (disco) in reply to Bulb
    Bulb:
    Non-acknowledge. File-scoped and class-static variables are initialized during global startup and by then there usually are not other threads, so it is thread safe just because of that. But function-static variables are initialized on first invocation of the containing block and that is not thread-safe.

    And that assumes that you aren't trying to do some sort of lazy initialization.

  • CHUDbert (disco)

    Obviously, they're missing the SingletonSmtpClientFactoryFactory class... :trolleybus:

  • Jaime (disco) in reply to Bulb
    Bulb:
    There is not much point in making a hashing function a singleton either. A static method is just fine for that.

    Static methods/fields are the sane implementation of the singleton concept. In any language that has static (including static initializers), I see no point in a traditional singleton.

    My point was that if you did, for some reason, implement a hash function as a method of a singleton - it wouldn't make it hard to test.

  • martijntje (disco) in reply to Bulb
    Bulb:
    But function-static variables are initialized on first invocation of the containing block and that is not thread-safe.

    From the C++11 spec, section 6.7:

    Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the object is being initialized, the concurrent execution waits for completion of the initialization.

    When talking about function-scoped static variables, the memory for them is initialized on startup, however the constructor is only executed the first time the function gets called.

  • Magus (disco) in reply to Jaime

    Many would argue that that is also wrong. Static has it's problems too. Ideally, if you need things to share a thing, you give them both the same thing. And you can give them a different thing when testing, if you do it right.

  • Eldelshell (disco)

    In this case (an SMTP client) it does makes sense to use a singleton... not this way of course.

  • Dragnslcr (disco) in reply to boomzilla
    boomzilla:
    The scariest thing to me is that they might be calling the constructor in different places with different parameters.

    Getting null if you call getInstance before calling the constructor is the obvious WTF. Personally, my favorite WTF in this was that if you call the constructor a second time, it silently does nothing. Null pointer exceptions are easy to see and fix, but silent no-ops cause all kinds of bugs that are hard to track down.

  • boomzilla (disco) in reply to Dragnslcr
    Dragnslcr:
    Null pointer exceptions are easy to see and fix, but silent no-ops cause all kinds of bugs that are hard to track down.

    Exactly.

  • Jaime (disco) in reply to Magus
    Magus:
    Many would argue that that is also wrong. Static has it's problems too. Ideally, if you need things to share a thing, you give them both the same thing. And you can give them a different thing when testing, if you do it right.

    Hey, I'm on board with the whole "singleton pattern is stupid" idea. I was just saying that a common use of the bad pattern doesn't cause testing problems.

  • bryan986 (disco)

    TRWTF is starting a variable name with an underscore. Ugh!

  • FrostCat (disco) in reply to Dragnslcr
    Dragnslcr:
    it silently does nothing

    It's easy enough to fix that. Just put in a MessageBox call.

  • Yazeran (disco) in reply to FrostCat

    Aaauuugggghhhhhh!!!!

    Please inquisitor, no more!

    :-)

  • Magus (disco) in reply to bryan986

    I agree, but it's a common practice. It's the default in Resharper for private fields, so it's caught on. Despite Resharper having a feature to make them a different color.

  • Tsaukpaetra (disco) in reply to Severity_One

    I wondered at that, when I found a "Constants.cs" file at the root of a project I inherited. 700 lines of const string declarations, for things that are just as easy (if not more so) to get "dynamically". In fact, very often these constants were used in flat script files to point to themselves, and typically consisted of things like:

    public const string UPDATELOOKUP = "Lookup/Update";
    public const string DAILYSTATUSREPORT = "Reports/GetDailyStatusReport";
    public const string SUBREPRESENTATIVELOOKUPURL = "Lookup?LOOKUP_SECTION=SUB&LOOKUP_TYPE=Representative";
    public const string SUBFEELOOKUPURL = "Lookup?LOOKUP_SECTION=SUB&LOOKUP_TYPE=Fee";
    public const string SUBSTATUSLOOKUPURL = "Lookup?LOOKUP_SECTION=SUB&LOOKUP_TYPE=Status";
    
  • riking (disco) in reply to Bulb
    Comment held for moderation.
  • boomzilla (disco) in reply to Tsaukpaetra
    Tsaukpaetra:
    `SUBFEELOOKUPURL`

    That looked like SUBFEELUPURL at first, and I wondered what sort of thing you were developing.

    :giggity:

  • FrostCat (disco) in reply to Tsaukpaetra
    Tsaukpaetra:
    `public const string UPDATELOOKUP = "Lookup/Update";`

    tr :wtf: is that that's not LOOKUPUPDATE.

  • ExceptionHandler (disco)
    Comment held for moderation.
  • Tsaukpaetra (disco) in reply to FrostCat

    It's OK, there are also ADDLOOKUP and CREATELOOKUP consts in the same pattern. Apparently they wanted to program within the guise of verb-object-ID, but MVC made them actually use object-ID-verb.

    I don't know, personally I don't understand "do $this with $object whose ID is $this" as readily as "Using $object of ID $id, do $this"

  • Tsaukpaetra (disco) in reply to ExceptionHandler

    Interesting point the first article said about where it might be necessary for singletons: A Window Manager should be more than a singleton, especially if you're running more than one desktop session under the same window manager, right? I would imagine things like Window's Fast User Switching (and whatever the equivalent for other OS's, sorry skips the mind) would be horribly difficult to implement if you couldn't separate sessions in the window/desktop manager because they're all in the same collection...

    Or maybe I'm incorrect in how I think a Window Manager even works...

  • Spectre (disco)

    When I think about singletons, I'm always reminded of this chapter from Test-Driven Development By Example:

    Singleton

    How do you provide global variables in languages without global variables? Don't. Your programs will thank you for taking the time to think about design instead.

    Yes, that's the entire chapter.

  • Magus (disco) in reply to ExceptionHandler
    Comment held for moderation.
  • Masaaki_Hosoi (disco) in reply to Spectre

    I actually use singletons a lot for game dev in Unity. I frequently have a GameManager or something like that as a singleton class which generally keeps track of overall game state.

    The reason it's a singleton is:

    1.) Because there is never a situation where I need more than one game manager. Just one will do fine. 2.) Because that's honestly the most performant way to get a reference to the game manager. The only other options are to stick my game manager in the scene and have my scripts find it with GameObject.Find by name (ew) or stick it in a static dictionary or something (which is obviously overkill if there's only ever one that exists)

    Maybe they're an antipattern, but it's the cleanest way I can think of to express the idea of a singular overall game manager concept.

  • Magus (disco) in reply to Masaaki_Hosoi
    Masaaki_Hosoi:
    Maybe they're an antipattern, but it's the cleanest way I can think of to express the idea of a singular overall game manager concept.

    Give. Things. It.

    Things locating their dependencies from elsewhere in the system, in no way observable when looking at the class definition displayed when you F12 to a DLL, is bad. Always. Having a static variable somewhere without the singleton enforcement would be better than what you have, but it's still bad.

Leave a comment on “Patterned After Success”

Log In or post as a guest

Replying to comment #:

« Return to Article