Jump to content

  • Log In with Google      Sign In   
  • Create Account

questions about singletons


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
40 replies to this topic

#1 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 11:36 AM

questions about singletons:

 

1. the code that makes it so you can only create one singleton is just to prevent you from doing something stupid like creating two entity lists by accident, correct?

 

2. are singletons considered good, bad, indifferent?

 

 

 

 

 


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9604

Like
5Likes
Like

Posted 28 August 2013 - 11:46 AM

There are two parts to being a singleton: one is that you can only create one of that class, the other is that the class has a single point of global access. If if you can create only one of a class but it doesn't have global access it's not a singleton.

 

As a whole singletons seem to be regarded as a bad pattern due to the global access part. Global state is bad because it complicates multi-threaded code, makes testing and debugging more difficult and frequently makes code maintenance and refactoring a pain. The single instance of  a class part is largely regarded as usually pointless but not harmful in and of itself.



#3 nonoptimalrobot   Members   -  Reputation: 416

Like
0Likes
Like

Posted 28 August 2013 - 12:25 PM

1. the code that makes it so you can only create one singleton is just to prevent you from doing something stupid like creating two entity lists by accident, correct?

 

Yep along with the Global Access property SiCrane mentioned.  The third property of the Singleton paradigm is control over the relative order of construction of singleton objects, something that's not possible with object instances that are declared as globals.  As with most design paradigms Singletons are mostly used to show intent to would be modifiers of the system rather than to prevent bonehead mistakes by making them syntactically illegal. 

 

As a whole singletons seem to be regarded as a bad pattern due to the global access part. Global state is bad because it complicates multi-threaded code, makes testing and debugging more difficult and frequently makes code maintenance and refactoring a pain. The single instance of  a class part is largely regarded as usually pointless but not harmful in and of itself.

 

Mostly agree in the academic sense but in practice I would say they have their uses stemming primarily from convenience.  Sometimes you truly only want one instancing of something running around (assert tracker, GPU wrapper etc) in which case having a single point of access keeps things simple.  Avoiding the threading pit-falls can be done by proper constructing the singleton to deal with multi-threaded access and being vigilant about keeping singleton access out of code that doesn't absolutely need it.



#4 Ravyne   GDNet+   -  Reputation: 7490

Like
3Likes
Like

Posted 28 August 2013 - 12:26 PM

I'll add, that one of the great dangers of global state is not just that it makes reasoning about your program hard, but that it allows you to code merrily along without having to stop and reason about how your program should be before you write it. That is, if you can just access the data willy-nilly from anywhere, you never have to stop and ask yourself if that's a good idea, and as a result, data that maybe shouldn't be accessed directly from deep inside your program takes root there. Like any common weed, the deeper and more numerous the roots, the harder it is to remove. This is what makes re-factoring global state like singletons difficult.

 

Global state as a singleton adds another dangerous aspect to the problem, which is that many less-experienced programmers allow themselves the delusion that, "since Singleton is an 'OOP Pattern' that was even written about in a book once", that it is somehow less dangerous that global state in the form of simple globals. They think it must be OK if its a Pattern. In fact it is almost always an anti-pattern -- something that even the authors that popularized it now concede. Taken with the additional (if sometimes harmless) restriction on it being a unique representation of that information or resource, global state in the form of a singleton is nearly always worse than global state in the form of a common global (though both are very bad to begin with; its a bit like asking whether The Penguin or The Joker was more evil.)



#5 Ravyne   GDNet+   -  Reputation: 7490

Like
2Likes
Like

Posted 28 August 2013 - 12:35 PM


Sometimes you truly only want one instancing of something running around (assert tracker, GPU wrapper etc)

 

This is misleading -- You may "want" only one, but it's very, very seldom that one cannot imagine a scenario where, in fact, you actually need more than one, and even more seldom when having more than one would actually be incorrect. Usually when a programmer says "I'll use a singleton because I only want one of these." what he's really saying is "I'll use a singleton because I don't want to bother making my code robust enough to handle more than one of these."

 

If you can justify choosing convenience over correctness you're free to do so, but you've made your bed once you've chosen a Singleton and you alone will have to lay in it.


Edited by Ravyne, 28 August 2013 - 12:36 PM.


#6 nonoptimalrobot   Members   -  Reputation: 416

Like
1Likes
Like

Posted 28 August 2013 - 02:21 PM

 


 Sometimes you truly only want one instancing of something running around (assert tracker, GPU wrapper etc)

 

This is misleading -- You may "want" only one, but it's very, very seldom that one cannot imagine a scenario where, in fact, you actually need more than one, and even more seldom when having more than one would actually be incorrect. Usually when a programmer says "I'll use a singleton because I only want one of these." what he's really saying is "I'll use a singleton because I don't want to bother making my code robust enough to handle more than one of these."

 

If you can justify choosing convenience over correctness you're free to do so, but you've made your bed once you've chosen a Singleton and you alone will have to lay in it.

 

 

...yeah, 'correctness' in software design; something that's largely considered undefinable.  We are not scientist doing good science or bad science; we are craftsman and what one paradigm holds over the other is simply the kinds of coding decisions that are discouraged vs encouraged.  The idea is to use designs that encourage use cases that pay productivity dividends down the road and discourage use cases that become time sinks.  In this sense Singletons are ALL BAD but making your life easier down the road shouldn't be a directive that is pathologically perused such that the productivity of the moment is drawn to a crawl.  I guess the point I'm trying to make is that a tipping point exists between writing infinitely sustainable code and getting the job done.  Here are some examples:

 

Singletons make sense for something like a GPU; it is a piece of hardware, there is only one of them and it has an internal state.  Of course you can write code such that the GPU appears virtualized and your application can instantiate any number of GPU objects and use them at will.  Indeed I would consider this good practice as it will force the code that relies on the GPU to be written better and should extend nicely to multi GPU platforms.  The flip side is that implementing all this properly comes at a cost in productivity at the moment and that cost needs to be considered over the probability of seeing the benefit.

 

Another example is collecting telemetry or profiling data.  It's nice to have something in place that tells everyone on the team: "Hey, telemetry data and performance measurements should be coalesced through these systems for the purposes of generating comprehensive reports."  A Singleton does this while a class declaration called Profiler and Telemetry does not.  Again, you can put the burden of managing and using instances of Profiler and Telemetry onto the various subsystem of your application and once again this may lead to better code but if the project never lives long enough to see that 'better code' pay productivity gains then what was the point?

 

I don't implement Singletons either personally or professionally (for the reasons outlined by Ravyne and SiCrane unless explicitly directed to do so) but I have worked on projects that did use them and overall I was glad they existed as they made me more productive on the whole.  In these instances the dangers of using other people's singletons in already singleton dependent systems never came to fruition and the time sink I made writing beautiful, self contained, stateless and singleton free code never paid off.  Academic excellence vs. pragmatism:  it's a tradeoff worth considering.  Mostly I'm playing devils advocate here as I find blanket statements about a design paradigm being all good or all bad misleading.  Anyway, this is likely to get flamey...it already is and people aren't even disagreeing yet. :)  I'm out.



#7 Satharis   Members   -  Reputation: 987

Like
1Likes
Like

Posted 28 August 2013 - 04:10 PM

To be honest I just have very rarely(and by rarely I mean once, in C#) found a real use for a singleton and in that case it was more to cover a problem I couldn't get around, I think it related to a certain global having state or something. It had good reasoning at the time whatever it was.

 

Other than that a singleton is really just a global under a really thin blanket. There's no real reason architecture wise that you should need something to only function if it is the only copy of itself. Globals can be useful, sure, but the golden rule with globals usually is that they are objects that won't change, such as constants.

 

Of course even in that case they shouldn't really be bare globals, placing things in namespaces is always a helpful idea, and a global only really becomes a global if you include it anyway, otherwise your unit of code might as well not see that it exists.

 

In general using either a singleton or a global as a point of access for something just doesn't have much of a point, you can accomplish the same thing with dependency passing. I used to feel that it was messy to pass a top interface class like an "engine" or something abstract like that around to allow access to other objects but the fact is that such an object keeps the dependencies bundled together. When you use a full on global object or a singleton you're basically shooting it up into space and letting everyone touch it without you having a clue where they're touching it from or how much code you will break if you modify or remove it.


Edited by Satharis, 28 August 2013 - 04:11 PM.


#8 Ravyne   GDNet+   -  Reputation: 7490

Like
0Likes
Like

Posted 28 August 2013 - 04:14 PM

We may not be able to imperially measure the goodness of the code we write and systems we design, but we do have a reasonably strong understanding of what's good none-the-less. If we could make perfect statements about what is--now--and will remain--forever--single, then Singleton at least wouldn't introduce that very dangerous assumption. The trouble is: we can't. Not many years ago, the assumption that the GPU was singular in any system might have seemed reasonable. Now, multi-GPU setups are common, things like nVidia Optimus are common (switchable integrated+discrete GPUs), and Hydra (allocating graphics calls among multiple GPUs, even from different vendors) is a thing. Assumptions very often turn out wrong.

 

So now the point may be argued, correctly, that 'forever' is an awful long time to be concerned about. And it is. Probably most software (gaming, anyways) will be developed over a period of 12-36 months, and have an active support cycle of about twice that if the game continues to generate revenue. So, already we are predicting 3-6 years into the future. Now, if we base our next game on the same codebase, we can extend that number out another 12-36 months per iteration. We're now predicting things 4-9 years into the future. Not forever, but in a realm very few people are consistently right at guessing about.

 

So, if we are considering the potential productivity costs of choosing Singleton or not, we have to also consider the unknown cost of guessing wrongly about the uniqueness of the thing, multiplied by the likelihood of our being wrong. On the other hand, if we do not make the simplifying assumption of its singleness, then we do pay a cost now, but we probably have a decent idea of what it is and being more general, rather than less, is not likely to cause us any unexpected grief later on.



#9 SiCrane   Moderators   -  Reputation: 9604

Like
3Likes
Like

Posted 28 August 2013 - 04:22 PM

The third property of the Singleton paradigm is control over the relative order of construction of singleton objects, something that's not possible with object instances that are declared as globals.

That's not a property of a singleton. That's an implementation detail that some (not all) singletons have that can be extended to non-singleton objects.

#10 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 05:45 PM


The third property of the Singleton paradigm is control over the relative order of construction of singleton objects, something that's not possible with object instances that are declared as globals.

 

so its supposed to be manually new'ed on the heap by the coder so they control when the constructor runs?  

 

as opposed to some arbitrary order decided upon by the compiler for object instances declared global static?


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#11 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 05:53 PM


As with most design paradigms Singletons are mostly used to show intent to would be modifiers of the system rather than to prevent bonehead mistakes by making them syntactically illegal. 

 

so its more about code clarity and robustness for the coder who comes behind you to make mods later?

 

i was wondering, i mean, if you declare it, you know there's only one. the extra code seemed overkill. at least / especially for a release build of a game where you strip out all unnecessary error and type checking once its stable.    or better yet, don't let it become unstable, and don't put it in in the first place.


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#12 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 05:55 PM


Avoiding the threading pit-falls can be done by proper constructing the singleton to deal with multi-threaded access and being vigilant about keeping singleton access out of code that doesn't absolutely need it.

 

so then you just design it to be "thread safe", with locks, etc, right?


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#13 ApochPiQ   Moderators   -  Reputation: 15816

Like
1Likes
Like

Posted 28 August 2013 - 05:57 PM

It's actually harder than it sounds. Look up the double-checked lock idiom in Java for an example of a popular but thoroughly broken attempt at doing thread-safe singletons.

#14 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 06:00 PM


global state in the form of a singleton is nearly always worse than global state in the form of a common global (though both are very bad to begin with

 

so whats the alternative to a global state?

 

also, what precisely do you mean by global state?

 

a global variable like "int gameover;" ?

 

or a global data structure such as an array of pointers to texture com objects?

 

or both? IE any global?

 

or do you mean something else entirely?


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#15 ApochPiQ   Moderators   -  Reputation: 15816

Like
0Likes
Like

Posted 28 August 2013 - 06:07 PM

"State" is a general term for any data which reflects the properties of a changing system. A system has state or is stateful if it can change over time.

Mutable state is state that can take on different values over time. For instance, a global variable that stores player hit points would be an example of global mutable state. So would an array, or a class object, or whatever other linguistic construct you have available to represent values.

Immutable state is state that is always the same value, and does not change. Note that changing systems can still be represented in terms of immutable state, via designs like monads. In fact a good chunk of pure functional programming involves building systems that are described in terms of immutable state.


Generally, when people talk about globals being bad, they're talking about global mutable state, although not always.

The reason global mutable state is bad is that it permits invisible coupling between distant and unrelated parts of code. This should not be confused with "global" variables which are contained to individual modules, such as static file-level variables in C or C++.

#16 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 06:14 PM


That's not a property of a singleton. That's an implementation detail that some (not all) singletons have that can be extended to non-singleton objects.

 

so they're not necessarily intended to be new'ed, then ?


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#17 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 06:33 PM


Generally, when people talk about globals being bad, they're talking about global mutable state, although not always.

The reason global mutable state is bad is that it permits invisible coupling between distant and unrelated parts of code.

 

so then....     giving say, the renderer "global access" to an array of texture COM object pointers ( static textures - immutable data ) would not automatically be considered bad form?

 

if so, what might be considered a "better way" ?


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#18 Norman Barrows   Crossbones+   -  Reputation: 2158

Like
0Likes
Like

Posted 28 August 2013 - 06:40 PM

so i take it the "better practice" is to just create non-singleton classes, just in case you someday might need "more than one" mesh database, texture database, entity list, player list, projectile list, etc?

 

the difference in effort almost seems trivial. create a class - create one instance.  vs create a class with some special "singleton" code, and create one instance.  right?   am i missing something?


Norm Barrows

Rockland Software Productions

"Building PC games since 1988"

 

rocklandsoftware.net

 


#19 SiCrane   Moderators   -  Reputation: 9604

Like
0Likes
Like

Posted 28 August 2013 - 07:02 PM

That's not a property of a singleton. That's an implementation detail that some (not all) singletons have that can be extended to non-singleton objects.

 
so they're not necessarily intended to be new'ed, then ?

Singleton's have a single global point of access. If you could manually create a singleton, say with new, then you wouldn't have a single global point of access.

#20 Cornstalks   Crossbones+   -  Reputation: 6995

Like
4Likes
Like

Posted 28 August 2013 - 07:18 PM

so i take it the "better practice" is to just create non-singleton classes, just in case you someday might need "more than one" mesh database, texture database, entity list, player list, projectile list, etc?

 

the difference in effort almost seems trivial. create a class - create one instance.  vs create a class with some special "singleton" code, and create one instance.  right?   am i missing something?

You're missing something.

 

People bring up a valid point about the whole "you might need more than one," but it's not just about keeping future possibilities open. That's just one reason of many.

 

The thing is, once you settle on "one, only one, and always one (i.e. a singleton)" that starts to impact your program's/library's design. It's architecture. After all, it's a significant decision when you make a singleton. So it's not just about "might need more than one later," but it's also about how the whole thing impacts your design and architecture.

 

Singletons, by their global nature, lead to coupled, tangled, mixed-state code. As the project grows in complexity, so does its dependency on and interactions with the singletons (or any other globals, for that matter).

 

So yeah, sure, it's because "you might need more than one someday," but that's definitely not the only reason.

 

Think of all the reasons people hate global variables. Those apply to singletons too. On top of that, singletons have the restriction that "there is always one instance, never more, never less," which is not a restriction to be taken lightly.

 

If you have to ask "why are singleton's bad/when should I use one?" then I would argue that you're not experienced enough to be using them. I won't say never use globals or singletons, but I will say that they are not to be used lightly. There's a high chance that you're using them wrong if you use them at all, especially if you're not an expert at the software you're designing.

 

(note: when I say "you" I don't mean specifically Norman Barrows; it's a general "you")


[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS