Search Unity

To Singleton or Not to Singleton

Discussion in 'Scripting' started by Saxi, Aug 27, 2014.

?

Do you use Singletons or Avoid them?

  1. Use Singleton

    73.8%
  2. Avoid Singleton

    26.2%
  1. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    I am curious how many people are using Singletons and specifically avoiding them.

    If you don't understand singleton or don't have a need, please do not vote. I specifically am curious about how many use Singletons and how many are aware of their Pro/Cons and make an active choice to avoid them.
     
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I use them for all my manager classes... theyre definitely convenient when used correctly.
     
    Polymorphik likes this.
  3. Graph

    Graph

    Joined:
    Jun 8, 2014
    Posts:
    154
    Why don't you inform us about these apparent cons of using singletons since for me none come to mind.. As JL said they are quite useful when you use em for managers, factories, and the like.

    Any pattern has pros and cons relative to the environment and situation.
    Would you cross a big/deep river in a car? No; that'd be a terrible idea, I'll look for a bridge or rent a boat or something.
    Would you, if there was a ferry? Oh.. suddenly I can cross the river with the car right here and keep driving on the other side.
    Please enlighten me about these implicitly absolute Pros and Cons you refer to.

    Btw I'm not trying to be an asshole here but something about the way you wrote that post rubbed me wrong.
     
    Shir10c likes this.
  4. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    Singletons are widely considered very bad practice, even the Unity Community code site mentions it when describing the Singleton pattern.

    There are lots of reasons, but in practice they are very convenient but are considered by many to be bad programming.

    1) cause code to be tightly coupled
    2) can't be sub-classed
    3) avoid Single Responsibility Principle
    4) hide dependencies
    5) difficult to change later, for example starting with singleton for database connection, but then needing multiple causes a lot of gutting of code and logic.
    6) difficult to test

    These are common reasons, there are more but there are very strong reasons why using Singletons are a bad idea, there are equally good reasons why they are useful.

    I honestly have no idea about the nonsense about a car and a river. Sorry but you do come off as an asshole with how you worded your post. Perhaps talk less listen more?
     
    Jilbarkus, DownstairsB, Yedya and 2 others like this.
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Their point by that post was that there wasn't a lot to listen to in the first place. Your OP was rather terse and lacked any information about pros and cons. They were asking for you to say more so that they could listen.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Also, yes, I use Singletons. To various degrees.

    1) that's a problem, but if designed properly, you can avoid tightly coupling code. Because a singleton has an actual instance, you can still treat it as an instance, and pass it around by reference. Unlike static classes.

    2) yes it can be sub-classed, that's its benefit over a static class.

    3) this argument is based on a singleton having to create an instance of itself... which is sort of a stretch IMO. And also can be mitigated by having a factory. Which leads back to 1, and 2. If the singleton exists only to enforce a single instance, yet you pass by reference, you can then use a factory to create the instance for passing around, and the factory also can be how which sub class is selected.

    4) This really is just repeating number 1.

    5) very true, remedied partially again by my answer to 1

    6) ... huh?
     
    Polymorphik likes this.
  7. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    I want to make sure only to get responses from people who use Singletons despite knowing the downsides. I wanted to get a sample set of people who know the pros and cons so I can tell how many use them even though they know the downsides, many people use them but don't understand the downsides because honestly they aren't really a concern to them.

    His analogy about the car and a river is just ridiculous, who would ever use a car to cross a river? It's just a stab at someone, not anything constructive. The comment about "implicitly absolute Pros and Cons" is another comment just digging the knife in.

    There are much less aggressive and rude ways to say "Hey, I didn't know there were cons to use singletons, mind sharing them?" rather than being so damn confrontational. If you have to end your post "not trying to be an asshole.." you probably know you are being one.
     
    CheekySparrow78 likes this.
  8. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    I wasn't trying to start an argument for or against singletons, there are tons of articles and forum posts about it. I was just curious how many people use them after knowing the issues surrounding them.

    1) Yes, there are "hacks" you can do and there is the Toolbox pattern that tries to remedy some of the issues.

    2) You cannot ensure sub classes only create a single instance of themselves without a bunch of kludgy code.

    3) Semantics yes, but that's what a lot of programming patterns are all about. So it is a real issue, you can assign whatever weight to it you like, as many view it differently.

    4) Sure, 4 is part of one, but it is spelling out part of the issue even though it is mostly issue 1.

    5) Yes, there are ways, but most implementations of Singletons changing from a single to many causes a lot of problems.

    6) Hard to test mostly revolves around the issue of it being tightly coupled and the fact they hide things that may or may not be related. It's hard to test objects without depending on the singleton (which means you are testing two things not one). To really test a singleton (which may have a state) you have to create a lot of overhead code to allow it to be destroyed/rolled back after the test.

    I am not trying to make a case for or against them, I use Singletons myself, I just wanted to know what others were doing. Others who know about these issues, and still use them.

    Again, this isn't an exhaustive list and there are a zillion posts on the subject. I didn't want to get into a debate about it, or promote either side. Just curious what people are doing, and if I didn't clarify (If you don't understand singleton or don't have a need, please do not vote.) the vote would be hugely skewed and thus not very accurate and useful.
     
  9. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I find it ironic youre offended by this, when your own request for information was somewhat confrontational.

    "If you don't understand singleton or don't have a need, please do not vote."

    Id suggest staying focused on the point at hand... are singletons good/bad, do you use them... why/why not...

    Personally, I've not bothered reading into the pros/cons of using them, as game development is not typical business app development, which is where I suspect a lot of the negative connotation comes from. I use never use singletons in biz apps.

    However, singletons provide an excellent facility for manager classes that suit Unity's component based model. You obviously don't want to go overboard with them, but they replace the need for using Find functions, which are slow and best avoided, especially if you plan on accessing the manager a lot.
     
    LGW_DesertEagle_PWN likes this.
  10. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    Maybe I could have written it differently, but I was just trying to be clear so the votes are meaningful. I didn't mean anything other than that.
     
  11. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    It depends on your implementation. For Managers, or things you know for a fact should only be instantiated once, should use a Singleton Paradigm. The debate about Singletons among programmers, is that those that do not know how or when to use them tend to abuse them and break software design structures. Use them, but know how and when to use them. The best way, is to ask yourself, "Should this script have multiple instances, or should there just be one?".
     
  12. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    And when that constraint changes, and you now need more than one?
     
  13. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    Then you need to go back and reread Software Designs. I have never had this issue because I use UML to organize and construct my code before I even start to program. Again, sometimes there is the need but this in of itself is rare. If so, create a method that can control and pool outside instances. I call these "Head Connectors", as they will connect to the parent instance as a derived child. If the head loses connection, a child will become the head etc. You might see this design pattern in servers, when a 'Host' drops out, a client will get drawn from the pool to get connect as the new 'Head'.
     
  14. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    Read this.
     
  15. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    The common example is using a single database connection, so using a singleton to enforce that, then later they decide they want to use parallel connections. There are lots of other situations, but that's just one example.

    In a perfect world, nothing ever changes, but we all know programming is never done in a perfect world and you do not always have control of the constraints and when they change.
     
  16. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    When I tutor Computer Science, I tell my tutees expect the unexpected. The purpose of being a software engineer is to understand, and solve problems. If you find yourself with issues with a database, your software designs are poor. If the project is too deep, that you cannot change it for whatever reason, then your project is tightly coded and is not abstract enough to sustain later modifications and maintenance.
     
  17. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    Again, plan out what you are about to do. Don't just dive in without proper knowledge of what you are going to program or else, you will dig yourself a hole. I have seen this many many times, nobody seems to put thought into algorithms or design patterns. I rarely see anyone use OO patterns anymore. Its really sad.
     
  18. crag

    crag

    Joined:
    Dec 13, 2013
    Posts:
    145
    This thread is diverging.

    On topic:
    Only use Singletons for items that will never need additional instance. As example, you will usually only ever have one audio player. But database/network connections change all the time and therefore are not good candidates for Singleton usage.
     
  19. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Singleton is a tool, like any other code pattern and design. It serves a specific purpose. Avoiding it just for the sake of some coding philosophy is as dumb as someone can get.

    The entry point can easily be a singleton, because you will never have multiple network connection entry point. However, you can inject the proper communication protocol to your singleton. Also, singleton does not prevent polymorphism from taking effect. You can search for the self-referencing generic class pattern.
     
    spraycanmansam likes this.
  20. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Honestly I don't think the thing about singletons has anything to do with single instance or not. It's really just about having the convenience of static access to something (which is made possible by only having a single instance).

    Most likely the reason that people rely on them so heavily in unity is because you don't have good control over constructors. So it's sort of hard to pass data around, making that silky smooth static access all the more convenient.

    The problem is that the way you use a singleton really relies upon a ton of constraints - generally:
    - there is only one of them.
    - it's always available
    - it will always perform a single set of well defined tasks.

    What I've found personally (and it depends on your development cycle), is that a lot of times it's really convenient to be able to plug in a different implementation to a singleton. A lot of times, these separate implementations are not specific to the game but to the actual process of development. It's stuff like being able to rip out a segment of functionality and work on it / test it in isolation when you want to potentially make a dramatic change to the context in which the code functions where stuff like singletons generally become a real problem.

    My process for software generally involves a lot of rapid isolated tests (I don't do strict unit tests, but I do have tons of test scenes with some isolated piece of the game).

    When moving a chunk of code between a test scene and the main game, assumptions you make about a singleton might go out the window. Stuff like saving/loading state or reference data can take dramatically different forms. Player specific functionality might be entirely different. Gui functionality will often be very different.

    It's this kind of stuff that 'glues' different sub systems together where singletons are often the worst problem. Like you have a store screen and you have a player inventory. A lot of people might end up moving the data from the gui screen to the player's inventory using a singleton. That's the kind of thing that might make the shop screen impossible to test in isolation.
     
    DownstairsB likes this.
  21. hodx

    hodx

    Joined:
    May 11, 2013
    Posts:
    16
    they keep code in one place, otherwise code is attached all over the place.
     
  22. Saxi

    Saxi

    Joined:
    Jun 28, 2013
    Posts:
    381
    Kind of the point of OOP though. Otherwise you are making one giant file with all your code in serial.
     
  23. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I would have thought it was mostly because the alternative is using FindSceneObjectOfType
     
  24. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    You use an object when it makes sense to use. OOP is a tool, and should not be forces where it is not needed and another tool performs better.

    You should know also, that for a computer, an object doesn't exist anyway.

    You know, I have a few games in Unity so far... and I never needed FindObjectOfType or GameObject.Find.
     
    Polymorphik likes this.
  25. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Personally, I generally just walk the transform hierarchy usually looking for an interface or something on awake. I tend to only allow components to look for parents, never children to keep things from getting too messy.

    The nice thing about that - is that you can paste a hierarchy into a different root and your components end up using whatever you have set up there. So you can plug in different data or different logic really easily. It works really well in unity's environment.

    Previously I used an IOC container, but I found this is just better. I built a set of attributes so it works like:

    Code (csharp):
    1.  
    2. public class SomeComponent : BaseBehaviour{
    3.   [FromParents]
    4.   protected SomeManager SomeManager{ get; set; }
    5. }
    6.  
    and the property gets initialized.
     
  26. Zoodinger

    Zoodinger

    Joined:
    Jul 1, 2013
    Posts:
    43
    It's kind of hard to avoid them in Unity, especially considering how Unity itself uses singletons. You can use a Find method to get a component you want in the scene, but:
    • It's slow, unless you cache it, which makes it tedious if you need to do that a lot
    • It only works for classes which inherit from MonoBehaviour etc
    • What's the advantage over a Singleton anyway?
    When I feel like I absolutely have to use the Singleton pattern, I do what Unity does with the Camera class. Instead of having only one instance, I have a static member called main. You can create as many instances of that class (lets call it Foo), but you can also have a "singleton" version by using main.

    You can even have a special editor for your class which has a check box labelled "This is the main instance" and ticking it sets a hidden flag to true and sets it to false for all other scene objects of that type. In the Awake() method, you can have:
    Code (CSharp):
    1. if (_mainFlag == true) { main = this; }
    That way you can code your game as if there can be multiple instances of Foo, but still get the benefits of a singleton. This is not foolproof, of course, and doesn't even make a big difference, but I think it beats having static classes or enforcing just one instance of Foo.

    But here's a better solution, IMO:

    You can have a base class for your more standardized MonoBehaviours. It's usually a good idea to implement your own base class for in-game objects, because for each game these objects usually have common functionality. You can then take advantage of it like this: The base class can have a reference to your Foo class and its Start method can just use a Find method to get it from the scene if it's not yet set in the scene editor. Now all your game objects inheriting from that class can access this just as easily, without having a static method, and it will then be easier to change this logic if specific objects require a different Foo instance.

    You can even combine the main member solution with the base class solution instead of using a Find method.

    frosted's idea is also really nice and I'd never thought of that before.
     
  27. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Neither, but that's because anything that would have required such a call is a singleton manager.
     
  28. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    I could think of other ways than just a singleton to deal with getting references to other objects in a scene that avoid GameObject.Find (or its ilk) as well.

    Not just think, but actually do in my games.
     
  29. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I suppose I use a singleton - sort of. It's usually a manager component, with a single entry point. For all intents and purposes I would call it a singleton. I have about 10 or so at the moment, and they grow as needed. I never actually = new singleton though. It's always the component pattern instead. This is because I like to have exposed properties to tweak for each manager. Personal design preference.
     
  30. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Care to elaborate?
     
  31. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    He probably prefabs / drags ref of objects to his singleton.
     
  32. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Of course there's prefabs.

    Dragging references of object to a singleton would be... using a singleton. Which yeah, I have a couple. Like literally... 2. And one of them is more like a multiton.

    What you (JamesLeeNZ) said though was:

    and

    In reference to someone bringing up the difficulty of passing references around. You're suggesting that FindSceneObjectOfType or Singletons are the only option.

    I don't use FindSceneObjectOfType ever (except for editor scripts that I wrote to search a scene and highlight objects that the built in search tool doesn't support).

    I have 3 primary methods of receiving references between GameObjects (anything not GameObject/Component related I have constructor access to, so those can go other ways).

    1) a simple property that references the GameObject/Component that needs to be referenced. Say it's a 'Trigger' script that triggers a component that implements 'ITriggerableMechanism'. The 'Trigger' will have a GameObject property that I then get the corresponding component off of (I have a custom method for getting components by interface).

    2) Say I have to get a reference to a component that is related to this component. Lets say I have a GameObject that contains many GameObjects as a children/grandchildren. And components may be strewn about it for various things. Well the base GameObject of that "entity" is tagged as being the root, and off of that I can traverse the hierarchy looking for components through the 'Transform' object.

    3) Everything else is event based. On collided, on trigger, various other events like my sensor system that senses near by aspects, notifications that are dispatched. None of this needs singletons either, nor FindSceneObjectOfType. The GameObject that needs a reference to something on such event receives the information with whatever parameter is passed with the event.

    I guess the sensor finding near by aspects (a sensor is a component type, and an aspect is a component type as well) COULD use FindSceneObjectOfType. But I don't. All Aspects register themselves into a pool of aspects that are a static member of the Aspect class. This isn't a singleton either... there's no enforcement of a single instance of Aspect, there can be multiple Aspects.
     
  33. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    That's not quite what I was suggesting... If im reading what youre referring to correctly those situations are completely different (from what I was thinking about)... there is either a parent relation or some event occurs between them.. yes obviously its easy to get references between objects that way. I could drag and drop references also, but this isnt something I do.

    I thought you had some method of getting references between gameobjects that didnt require a root gameobject or any interaction, to which as far as im aware, the only way to do via code is Find.

    I guess it would be easier to explain how some of my managers work...

    MeshManager... loads all meshes from resources on start.

    Random script needs mesh, calls MeshManager.GiveMeMesh(name) - static method

    MeshManager enumerates its meshes and returns a match if it exists.

    There is no way im aware of other than FindSceneObjectOfType(MeshManager) that you could get this link other than a singleton/static setup.
     
  34. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    You said nothing about a specific scenario. You responded to the generic scenario of:

    and

    I didn't claim to have anything magic. I claimed that in the case of getting references to objects, I can think of more ways than just FindSceneObjectOfType and Singletons. I don't know what you were suggesting either, because you didn't suggest anything to you. I was responding directly to things you said to another individua

    As for you scenario. I can think of a few ways to deal with that with neither the need for a singleton or FindSceneObjectOfType.

    Of course the primary thing is that I probably wouldn't have a "MeshManager".

    In the same respect, I have nothing against Singletons. As I said early in the thread. I use them. I wasn't critiquing your use of Singletons. I was critiquing your assumption that the only alternative for passing data around is a Singleton or FindSceneObjectOfType.

    If that's not what you said, well, sorry... but your words were interpreted as such. You didn't clarify well enough what you meant.
     
    Last edited: Aug 29, 2014
  35. dterbeest

    dterbeest

    Joined:
    Mar 23, 2012
    Posts:
    389
    Though i do like Singletons i usually try to keep only 1 in my codebase. This is like the service locator pattern (or whatever it is called)

    I have a GameServices class which is singleton. That class holds instances of all needed managers. If, in any case, i would need a second instance of a certain manager, i can just add it to the GameServices class.

    I've also written a nice little function to create or get my managers.

    Code (csharp):
    1.  
    2. public class GameServices
    3. {
    4.   //singleton code and default constructor omitted
    5.   private SomeManager _someManager;
    6.   public SomeManager someManager
    7.   {
    8.     get
    9.     {
    10.       if (_someManager == null)
    11.         _someManager = GetManager<SomeManager>("SomeManager") as SomeManager;
    12.       return _someManager;
    13.     }
    14.   }
    15.  
    16.   private T GetManager<T>(string gameObjectName) where T: Component
    17.   {
    18.     //check if gameObjectName exists, if not create it and add component;
    19.   }
    20. }
    21.  
    This way you will always have an instance of your manager.
     
    lordofduct likes this.
  36. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    I hate maintaining stuff. I also hate placing GameObject in scenes. I believe when I have a scene, whatever it is, I should just press play and it works.

    It's why I coded a "universe" level management system for all the project I worked on.

    The entry point of all our games is a single empty scene with 1 GameObject holding 1 script; the Universe. We never have to add or remove stuff from that scene. No maintenance.
    By reflection, the Universe finds all the class that derives from "Manager<T> : MonoBehaviour where T : Manager<T>", and load the prefab holding it in Resources. The Universe and the Managers are automaticly flagged as DontDestroyOnLoad, so they exist for the whole game.

    If someone is in the Editor, and not in the entry point scene, we have an Editor script that creates a dummy Universe at runtime, so all scenes always work.

    If someone writes a new class deriving from Manager, the Editor detects it at the next reload and creates a prefab with that specific script in Resources. I never have to create those prefabs by hands.
     
    dterbeest likes this.
  37. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    That's an interesting approach.

    What are the team sizes most of you work with? I've always been a big believer in the code base reflecting the team and I'm curious. Are any of you on larger teams?

    Also possibly related - does anyone use a pub/sub system? I tend to think that a lot of singleton stuff becomes less of an issue if you do.
     
    Last edited: Aug 29, 2014
  38. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Currently... between 10 and 15. However, I'm not a good example of team size vs code approach since I'm used to team in the 70-150 people range.
     
  39. raycosantana

    raycosantana

    Joined:
    Dec 23, 2012
    Posts:
    319
    I use them for store things that would be used many times by different objects, for example a GUI skin, if the same GUI skin will be used by several scripts there is no reason to have it each script so I just have it in a singleton class called GraphicsManager that contains several heavy reused graphical resources (like Icons and such) I do the same with sounds & songs but people say I'm a bad programmer so don't take me too seriously. :D