• Neil (unregistered) in reply to Fakeyede Mobolaji
    Fakeyede Mobolaji:
    return instance ?? instance = new KpiService();
    I've always wondered whether there should be an ??= (or ||= in other languages) operator:
    return instance ??= new KpiService();
  • Randy Snicker (unregistered) in reply to Dave Insurgent
    Dave Insurgent:
    Programming isn't philosophy, programming is engineering.

    Well, engineering is a branch of philosophy, just like science. I'd argue the difference is that engineering has little to no tolerance for experimentation, which belongs in science and then gets merged in to engineering after sufficient testing/examination. What's the point? You still use philosophy to practice engineering. Just a refined subset of it.

    Thank you for not attributing my quotes to me so that I get to play detective to find out whether you've answered to me or not.

    Sure, if you like to mince words and act like an idiot, engineering is philosophy. Although, anyone with half a brain should have seen that I clearly contrasted philosophy with engineering, which should tell a rational person that I used the terms in a context in which I specifically redefined them to be mutually exclusive. In addition, the word philosophy is probably most often used to describe the particular branch of science that doesn't fall under the common definitions of engineering or the other branches of science.

    I'd argue the difference is that engineering is about problem solving and making things work, whereas philosophy is a bunch of hipsters drinking red wine talking about something so meta that it has effectively no relevance to anything practical whatsoever.

    There shouldn't be a class called Damaging

    Why not? You don't know my problem domain any better than I know yours. I'm postulating ways to define a robust language for expressing many different configurations that could happen within a game engine. Not a specific application (a game), but the engine - which I'd like to reuse if possible, because I don't like rewriting the same crap every day.

    I like the idea of their being a Damaging attribute (it might not be an actual class definition either: it could be a name of a composite definition of other attributes, but that's not important right now). A Weapon is Damaging. Is a Thruster? I can apply the Damaging attribute to both, so that when the Thruster engages, anybody behind them gets burnt.

    We're not arguing about class naming conventions or object hierarchy, because I get what you're trying to do and it works when it works and it doesn't when it doesn't. I'm illustating that there is a different paradigm for how you model the problem - and that, based on the experience of some professionals, solves some issues that crop up in a neat way.

    Instead, you could have a Weapon class defining an interface functions (and possibly subclasses) for different ways of using something as a weapon.

    I already addressed that point: It works for simple games, but my point was that as games increase in complexity then seem to run in to an awful mess of an inheritance tree, and sometimes end up not being able to model certain things at all.

    Well, you "addressed" that point by coming up with a strawman idea of using classes as an overly general attribute definition and then proceeding to create rules based on those overbroad categories. Unsurprisingly, that idea turned out to be rather stupid.

    If your attribute definitions fall in the category of idle philosophy rather than that of methods of use, you're going to have the problem of overly complicated rules for interactions, which is exactly the problem you seemed to be arguing against earlier. Even if your goal is to not design a game but rather model a world with fully realistic and rationally emergent behaviour, you're going to have extremely tough time doing it if you don't define the objects in terms of their use - regardless of the specificity.

    Don't believe me? Ok, you want to know what is damaging? Everything in some way or another. It's a useless property to be used as a class definition, because it doesn't restrict in any way how something is damaging. Then again, if it does, it's badly named because the name doesn't reflect those specifics. Weapon, however, defines clear use cases on which more specific logic can be built on. Even game engines should focus on some specifics and useful naming conventions so that whatever the framework they provide includes some default logic and structures for basic interaction. Otherwise it's just massive waste of everyone's time.

  • Dave Insurgent (unregistered) in reply to Randy Snicker
    Randy Snicker:
    Sure, if you like to mince words and act like an idiot, engineering is philosophy

    Here I was thinking I said:

    Dave Insurgent:
    engineering is a branch of philosophy

    Not that they were equal.

    Randy Snicker:
    I clearly contrasted philosophy with engineering ... I specifically redefined them to be mutually exclusive.

    In addition, the word philosophy is probably most often used to describe the particular branch of science that doesn't fall under the common definitions of engineering or the other branches of science.

    I'd argue the difference is that engineering is about problem solving and making things work, whereas philosophy is a bunch of hipsters drinking red wine talking about something so meta that it has effectively no relevance to anything practical whatsoever.

    Philosophy is the study of general and fundamental problems. Philosophy is distinguished from other ways of addressing such problems by its critical, generally systematic approach and its reliance on rational argument.

    So you wanted to contrast "critical", "generically systematic" and "rational" with engineering? You should play more carefully with "idiot" and "half a brain". You have your relationship between science and philosophy backwards.

    Well, you "addressed" that point by coming up with a strawman idea of using classes as an overly general attribute definition and then proceeding to create rules based on those overbroad categories. Unsurprisingly, that idea turned out to be rather stupid.

    I also provided a reference to a number of sources from people in the industry related to the problem domain in question, stating that it is, in fact, a real problem. Not a straw man. But I know it makes you feel superior (perhaps while drinking white wine since red is for those hipster philosophers) to try to bring up the term as often as you can.

    If your attribute definitions fall in the category of idle philosophy rather than that of methods of use, you're going to have the problem of overly complicated rules for interactions, which is exactly the problem you seemed to be arguing against earlier.

    It's not idle philosophy. It's still scoped to the mechanics that the game engine wishes to model. Equipment, Damage, Health, and so on. Those "overly complicated rules for interactions" are created through composition and those definitions can be tested and maintained better than an object hierarchy.

    Even if your goal is to not design a game but rather model a world with fully realistic and rationally emergent behaviour, you're going to have extremely tough time doing it if you don't define the objects in terms of their use - regardless of the specificity.

    Good point! It shows you didn't bother to read anything I linked and continue on your "object oriented is the only way to think about any given problem" way.

    Don't believe me? Ok, you want to know what is damaging? Everything in some way or another. It's a useless property to be used as a class definition, because it doesn't restrict in any way how something is damaging. Then again, if it does, it's badly named because the name doesn't reflect those specifics.

    Except that you could restrict it by virtue of the class definition of Damaging. The physics subsystem might emit collision events which have the Damaging attribute with a type - physical. It could possibly inherit the type from whatever it collided with. A Weapon could have the Damaging attribute with a type of magic. It could be fire, or poison, or whatever. That's where, you're not wrong that you have to have some definition of what problem you're trying to solve. But it's very, very difficult to model "A weapon that causes fire damage and can only be held with two hands" using inheritance.

    Weapon, however, defines clear use cases on which more specific logic can be built on.

    Yep! And that specific logic is sometimes mutually exclusive in an is-a approach, which is why inheritance becomes very messy. I'm not saying you can't make Weapon. It may make sense. But where do you stop? Is Bow a Weapon? Is Crossbow a Bow? Does Bow implement Pluckable? Does the Crossbow implement some properties of a Gun interface such as .reload()? If you do make Weapon, you can give it the Damaging attribute as an explicit definition of what is a weapon. You've still used composition and a has-a approach to giving the weapon the property of causing damage as opposed to trying to figure out how much of a weapon is a damage causing thing. Those decisions are both philosophical and engineering based.

    It's appears you don't understand some portions of software engineering / computer science that I'm talking about. That's OK, I mean, I don't think any of us understand all of it, but you're not very nice about it. You seem like a fairly intelligent person, though prone to outbursts which probably impacts your social life. It would benefit your career to take a look beyond object-oriented programming as the only way you approach problems. That doesn't mean stop using it. Just put another tool on your tool belt. And be a little nicer to people.

    The best part is that it's still actually object-oriented programming, so you should have figured it out. The "data oriented" part is a design decision.

    The first thing you can do towards bettering yourself as a professional (the being nice part is up to you) is read some good sources about what I'm advocating. I'm still well within the realm of not "composing everything" - data-oriented design specifically pushes the limit of what constitutes composing everything, but I'm not acting radically here at all, as I am supported by the link (and subsequent links it contains) I provided earlier.

    Good luck with your career!

  • Dave Insurgent (unregistered)

    I'd also like to add that a difference between you and I is that I brought up an idea - I proposed a problem, supported the existence of that problem with evidence, and showed how people who have had to deal with that problem "for real" have used that idea to solve the problem. All that does is give you another problem-solving tool to choose from. You're effectively attempting to suppress the existence and use of that tool absolutely based on rigid adherence to the use of another tool. Not supported by evidence. In fact, in direct opposition to evidence supplied, which is unreasonable.

    That's not engineering or philosophy, even with your asinine redefinition.

  • qbolec (unregistered)

    I have read all comments and found many of them interesting but I really need to add my two cents.

    1. It is easy to fix all problems submitter had with the offending code by simply adding new KpiSingleton call in the same file in which the class is defined. Depending on the language this may require special care to make sure there is only one call resultimg fromthis single line but I am pretty sure that any of you can figure out the needed combination of static, final, etc keywords.

    2. The submitter's attempt to fix a problem by calling constructor on something which has Singleton in its name is stupid.

    3. The idea of putting Singleton in the name of a class means that all pkaces where you use it is forced to know that it is a singleton. Same goes for naming the function getSingleton instead of more general getInstance.

    4. I see no difficulties in unit testing code which uses KpiSingleton. Simply inherit from it, add mocking functionality to derived class nd call its constructor, which as we can see will replace the instance with mock.

    5. I believe that if you need to resort to making something private to make sure there is only one instance of something, then you put too much trust in code and too litle in coworkers. Where I work it is common to change private to public if there is a good reason for it, and there are some things we do not do even though they are possible.

    6. Singleton is not equal to global state. You can have singletons which are not globally accessible. You can have global state comprised of multiple objects of the same class. Global state is bad for me because it makes understaning of a peace of code more difficult. Same goes for goto. Same goes for multiple assignments to same variable. But singleton does not make it harder. Virtual functions sometimes make it harder. Events often make it not only harder to comprehend but also to debug.

  • Thomas (unregistered) in reply to snoofle

    The constructor is public, and every time you create a new object via the constructor, getInstance() returns a different object. That's the problem

  • AN AMAZING CODER (unregistered)

    Though it was probably a pain in the neck to track down, that's a very simple bug to fix. Have our WTFs come down to small and obvious bugs?

    change public to private then be done with it and move on.

  • impulse (unregistered) in reply to snoofle

    I think the issue was that the static instance is never initialized.

  • Alexander Gee (unregistered)

    I don't think this was ever intended to be a singleton. I think that someone didn't want to pass a reference down a chain of objects (to lazy to write the setters) so they just chucked it statically in there statically assuming that no one else would want to instantiate it.

  • JimmyNeutron (unregistered) in reply to snoofle
    snoofle:
    What's wrong with that? It's easily discerned that the this in this singleton refers to this this from the singleton's point of view. From all other points of view, you should not be accessing that this, this this or the this, but the singleton via its getInstance, or pseudo-this.

    See? This is not so hard to understand!

    But the constructor is *public*. And the static initializer should be a pointer.
  • narrowtux (unregistered) in reply to snoofle

    the point is, that the singleton doesn't care about actually constructing the singleton if it doesn't exists.

    The author should've put something like

    if (instance == null) { new KpiService(); }

    at the top of the getInstance() method

  • justforgetme (unregistered) in reply to snoofle

    I don't get it, are you funny?

  • TheLogster (unregistered) in reply to snoofle
    snoofle:
    What's wrong with that?
    The singleton is never initialised, nothing calls new KpiService().

    If you call KpiService.getInstance(), you'll get null.

    The code should be something like :

    public class KpiService {
        private static KpiService instance = null;
    
        public static KpiService getInstance()
        {
            if (instance == null)
               new KpiSerice();
    
            return instance;
        }
    
        protected KpiService() {
            instance = this;
        }
    }
    

    The constructor should also be protected, so nothing outside the class can create a KpiService, and thus change where the instance points to.

  • StewartMoss (unregistered) in reply to snoofle

    The method which populates the static property with the current instance is not static (eg the constructor is populating the property). This is a good WTF

  • gumcio (unregistered) in reply to snoofle

    This code always throws exception.

  • Mmx (unregistered) in reply to snoofle

    I guess the complaint is because the traditional singleton pattern would have it be allocated just-in-time at the first getInstance call.

    However that is a very broken pattern which behaves badly under multithreading scenarios AND has issues if order of construction should be maintained in any minor way.

    On the other hand requiring a manual allocation requires you to slap a new KpiService(); somewhere in the code.

    At the very least I would:

    • wrap the allocation a create method
    • assert if create is called twice (ignore the request in release)

    I think the mistake is calling this a singleton.

  • sigs (unregistered)

    Sad thing is, Unity basically forces you to do that; there are lots of cases where you need a "manager class", essentially a singleton, but it still needs to inherit a framework class to integrate with the game loop.

    So yes, you basically get instance = this; a lot.

  • DFPercush (unregistered) in reply to snoofle

    The problem is that the class has never been instantiated, and you try to call a static function. Static functions don't trigger any constructor because they do not reference any particular instance. So the assignment of 'this' never happens.

  • KnobbyHills (unregistered) in reply to snoofle

    From the code snippet, i cannot see that the class is ever instantiated. That is, while the singleton accessor is legitimate, shouldnt getInstance() check for a null state and initialize the var?

  • Chris (unregistered) in reply to KnobbyHills

    Just because all of you guys expect a certain pattern for a Singleton doesn't make your opinions right. What about multi threading scenarios where two threads both try to access the Singleton for the first time simultaneously? That requires a bunch more synchronization in the getter which slows down the whole getInstance() function.

    The solution is then to ensure that only one thread can instantiate the instance on app creation, which is no different than having that one same thread just call the constructor.

    I have written code exactly like this for android for exactly this reason. If you know your Singleton is only ever constructed once, then it's better to have a null pointer exception when you violate the state design than sometimes have strange state errors caused by synchronization problems between threads. If you don't understand what I'm talking about, work 10 more years and reread this comment.

    /big fan of asserts that crash the program the second bad things happen as opposed to debugging strange behaviors.

  • Justin (unregistered) in reply to snoofle

    I think the issue here is that calling getInstance() should return you an instance even if it hasn't been initialized and also constructing the object would reset the singleton instance.

  • Mikey (unregistered) in reply to snoofle

    Sure, it compiles fine, but it's certainly not a singleton. You can create as many as you want, and instance just points at the most recently created one.

    For it to be a singleton, it should be:

    public class KpiService { private static KpiService instance = null;

    public static KpiService getInstance() {
        if (instance == null) { instance = new KpiService(); }
        return instance;
    }
    
    private KpiService() {
        // NOT NEEDED: instance = this;
    }
    /* SNIP */
    

    }

    Also, singletons are ridiculous anyway -- just use a static class and be done with the bullshit.

  • Oi (unregistered) in reply to snoofle

    The constructor should be private and the getInstance should do something like:

    public static KpiService getInstance() { if (self::instance == null) { self::instance = new self(); } return instance; }

  • Grayson C (unregistered) in reply to snoofle

    But it's never initialized, so THIS doesn't matter.

  • Powerslave (unregistered) in reply to snoofle

    I'm not sure if you're actually trolling or not?

  • TigerShark (unregistered) in reply to letatio
    letatio:
    QJo:
    For the record ...
    public class KpiService {
    
        private static KpiService instance = null;
    
        public static KpiService getInstance() {
            if (instance == null) {
                instance = new KpiService();
            }
            return instance;
        }
    
        private KpiService() {
            /* SNIP */
        }
        
        /* SNIP */
    }
    
    
    But don't you think about performance? While the program runs every single access to the singleton will execute that unnecessary "if", except the first. Do you think processor cycles grow on trees?
    Are you serious? Modern CPUs have been using branch prediction units for ages now, and that pattern will cause a pipeline flush only the first time that is executed, optimistically speaking.
  • TigerShark (unregistered) in reply to TheSHEEEP
    TheSHEEEP:
    Severity One:
    TheSHEEEP:
    What would be better? Passing an instance of the "SoundManager" to each an every class that may want to play a sound? Limiting what classes should be able to play a sound? What good would come of that?
    Well, why would you want to play a sound from your disc I/O classes?

    The question is not why I would want to allow something, the question is why would I want to limit something that does no harm?

    Remy Porter:
    Yes, you should limit what classes should be able to play a sound. I think OOP does a lot of harm in the way it forces us to live in a world of nouns, but one of the principal benefits of OOP is that it allows for clear separation of concerns. Part of that is making the interactions between modules explicit. This allows the code to be understood from a structural perspective.

    I am absolutely convinced that a simple SoundManager singleton would be far easier to understand than the complex architecture you suggest. And it would also be much faster, an event system would simply introduce clutter.

    Mind you, I'm not talking about more complex stuff like 3D sound, that would be a pretty bad idea to have as a Singleton as it depends on a whole new layer of stuff, would have to watch objects, etc. And if you already built that 3D sound class, there's no point in building an extra singleton class for 2d sounds. Even if it means you won't be able to play a sound from anywhere.

    Remy Porter:
    There are a lot of ways to provide sound functionality. One way that would be vastly superior to a Singleton is to use the Observer pattern. A single SoundManager instance registers interest in game objects. When sound-worthy events occur in those objects, the SoundManager matches them up with a sound.

    I get the idea, but that would be an overly complex solution to a very easy problem. You know, we have a nice saying in our office: "You can solve any problem by adding another layer of indirection. Except too many levels of indirection." Some people should really take that to heart. ;)

    Also, people seem to be stuck on that sound example. Let's introduce another one: Logging. In the same game (and in all other applications I wrote and most I encountered) I had a Logging singleton class. Now Logging is really something you want to do from possibly everywhere without having to rewrite your class hierarchy/structure.

    And the possibility to do so from everywhere also doesn't break or harm anything. Except threaded stuff, but you can always make that Singleton thread-safe.

    AOP is the solution for logging, as for every crosscut responsibility, not singleton.

  • TigerShark (unregistered) in reply to AGray
    AGray:
    Dave Insurgent:
    That being said, I also see YOUR way of things - what if, in a future project, I want items to be degradable? What if I want to implement the Gummi Sword? The way you defined would be better.

    Not to mention you can also write automated acceptance tests for them, so that your game, as an application of your game engine, is driven not by the "wizard specification" (nicely put), but by an actual spec - that maybe someone else a little more 'product-oriented' or 'business-oriented' (almost like an analyst... for business!) writes themselves.

    TDD in a nutshell...I've been exposed to it, and trying to integrate it into my very-indie dev ops at home.

    Well, we should thank the TDWTF staff - the WTF posted has helped one developer see another set of WTFs in his own work! Thanks Remy et al!

    nope, this is BDD. You formalise the requirements in acceptance test and then when your code is green for all of these you know that you are satisfying the requirements. TDD is at unit test level, you write a test that defines some method behaviour and then you write the simplest code that makes it pass, then you write another test and so on until the method behaviour is formalised exactly by the unit tests.

    (Why there are Latin words in the captchas? WTF???)

  • TigerShark (unregistered) in reply to Randy Snicker
    Randy Snicker:

    Thank you for not attributing my quotes to me so that I get to play detective to find out whether you've answered to me or not.

    Sure, if you like to mince words and act like an idiot, engineering is philosophy. Although, anyone with half a brain should have seen that I clearly contrasted philosophy with engineering, which should tell a rational person that I used the terms in a context in which I specifically redefined them to be mutually exclusive. In addition, the word philosophy is probably most often used to describe the particular branch of science that doesn't fall under the common definitions of engineering or the other branches of science.

    I'd argue the difference is that engineering is about problem solving and making things work, whereas philosophy is a bunch of hipsters drinking red wine talking about something so meta that it has effectively no relevance to anything practical whatsoever.

    philo and Sophia are two Greek words that mean love for the knowledge. I think that an engineer that is not in love for the knowledge is not an engineer by any means.
  • TigerShark (unregistered) in reply to Chris
    Chris:
    Just because all of you guys expect a certain pattern for a Singleton doesn't make your opinions right. What about multi threading scenarios where two threads both try to access the Singleton for the first time simultaneously? That requires a bunch more synchronization in the getter which slows down the whole getInstance() function.

    The solution is then to ensure that only one thread can instantiate the instance on app creation, which is no different than having that one same thread just call the constructor.

    I have written code exactly like this for android for exactly this reason. If you know your Singleton is only ever constructed once, then it's better to have a null pointer exception when you violate the state design than sometimes have strange state errors caused by synchronization problems between threads. If you don't understand what I'm talking about, work 10 more years and reread this comment.

    /big fan of asserts that crash the program the second bad things happen as opposed to debugging strange behaviors.

    just instantiating it in the member variable or in a static initialiser as someone already suggested fix this problem with absolutely no need for synchronisation. that code is really awful and is a TWTF.

  • cppdragon (unregistered) in reply to snoofle

    The point is if you create a singleton this way the constructor has to be private in order to not contruct the object from the outside. This thing is in fact no singleton because there is no implementation in the code to ensure it. Of course it will always return null because it is never constructed, not even by the getinstance!

Leave a comment on “The Lone Rangers”

Log In or post as a guest

Replying to comment #:

« Return to Article