6 ms·
Singletons aren't always bad. I use a few in my Objective-C Cocoa apps to share common behavior. For example in my music player Bahamut[1], I have a singleton f
by sdegutis 13y ago
Singletons aren't always bad. I use a few in my Objective-C Cocoa apps to share common behavior. For example in my music player Bahamut[1], I have a singleton for actually playing music. This way, you can have several Bahamut windows open at a time which all control the same music player.
Sure, you could store this variable as a property on AppDelegate or some other parent in the object graph, and then either pass it down to each window controller which needs it, or give them access to it, either directly or via delegates or something. But these are all very convoluted compared to having a single class-method in the class itself which returns a shared (static) object.
The only caveat is to make sure that you don't introduce race conditions by poor design. For example, don't do stuff in -init on your singleton, and especially don't do stuff that might call other stuff that might access the singleton via the public accessor. Doing so could turn into an infinite loop if -init is called when creating the singleton. (I've done this before.) Instead, just add a new -setup method and call that somewhere in -applicationDidFinishLaunching: or whatever. It's also a good idea to use dispatch_once to create the singleton[2].
EDIT: Of course, these suggestions don't only apply to Objective-C apps, although your entry points and race-condition-avoiding functions will certainly be different in other environments.
[1]: https://github.com/sdegutis/bahamut https://github.com/sdegutis/bahamut
[2]: https://github.com/sdegutis/bahamut/blob/master/Bahamut/SDMusicPlayer.m#L44-L51 https://github.com/sdegutis/bahamut/blob/master/Bahamut/SDMu...
- sdegutis 13y agoI'm aware that the example provided makes it slightly harder to test, since it's more tightly coupled than other options. It's a trade-off, simplicity over testability. In this case, I manually test my music player object when I make changes to it. So using a simple singleton here makes sense. I find the same true for most GUI controllers. But I'm not willing to get into a debate about whether or how you should test your GUI. I'm just stating how I do things, and it's worked well for me.
- deleted 13y ago[deleted]
- kenrikm 13y agoObjective C land there a specific API interfaces that really should be wrapped in a single instance if you're going to be accessing them a lot because they are costly to make I.E EventKit.
- ep103 13y agoTo quote either pragmatic programmer or the gang of four (I can't remember which), singletons make sense when, if the singleton doesn't exist, it doesn't change behavior through the application. So for example, setting up a logging singleton probably makes a lot more sense than adding a logging dependency through every class in your code. But conversely, if the behavior you are putting in your singleton actually has effects, and can be deemed a dependency on the code that uses it, then it makes sense to make that blatant by passing the reference into each of the dependent modules, if only for unit testing, clarity and mockability.
- jarrett 13y ago> But these are all very convoluted compared to having a single class-method in the class itself which returns a shared (static) object. I used to think the same thing. But lately, I've come to think it's better for code to explicitly reveal its dependencies via its public API. If class Foo uses the singleton class Bar, you can't see that dependency just by looking at Foo's API. My preferred solution in OOP is either: a) have Foo's constructor accept a reference to an instance of Bar, or b) for any method on Foo that requires a Bar, have that method accept a reference to an instance of Bar. I find this disciplined approach helps me reason about my code and understand how units of code relate to each other. I only developed this insight after diving into functional programming. Prior to that, I was all about convenience. Singletons were convenient, and I didn't want to pass a references around all the time. It seemed like a lot of pointless ceremony. Now I've changed my tune. Rather than pointless ceremony, it's a form of self-documentation.
- sdegutis 13y agoWhat's the benefit of doing it that way? The only one you mentioned is self-documentation, but that seems like a weak argument against these kind of singletons. It sounds like you're giving up the convenience of singletons solely for the sake of not having singletons, which seems pointless in itself.
- stcredzero 13y agoI read that as not having singletons for the sake of self documenting code dependencies. In a way, a singleton is a "magic" dependency that can reach into the middle of your code without a trace. By always passing it in, you're making it explicit. This is the same as the pure functional discipline of having all values passed in, never coded into a function.
- evanspa 13y agoThis article echoes the same idea (instead of big singleton, view controllers should accept the data they require in their initializer (constructor)) and gives some reasons why to do it this way: http://www.hollance.com/2012/02/dont-abuse-the-app-delegate/ http://www.hollance.com/2012/02/dont-abuse-the-app-delegate/
- robmcm 13y agoYou have highlighted the good parts about using singletons. Now say your application wanted to play two different music streams (lets pretend you added a mix feature), you are now stumped. I first ran into the pain of singletons when using them in a framework. This framework formed the bases for small modules, which when loaded together into the same application domain blew up. My solution was to use IOC/DI. I could still have singletons , but they are just instanced managed by the container. This mean I am not relying on static values for state, which in my view is as bad as global variables. I guess this is really the problem most people associate with the singleton model, not that there is a single instance in your application, but that typically people use static variables to store the instance.
- sdegutis 13y ago> you are now stumped No, I just refactor my code to not use a singleton anymore. This only involves deleting the static accessor, adding a few properties, and passing a value downward. It would take all of 5 minutes. I don't see any value in designing my architecture around a feature I might never add.
- robmcm 13y agoI depends on the complexity of your application, sure it could be easy, it could also be a nightmare. People make the same arguments about using interfaces (think Java not Objective-C ones), they are only useful when you need them, but almost all of the time it's easier to do it in advance than at a later date. At the end of the day it's your call as the architect of your application. If you can convince yourself using a singleton is a better fit that another method go for it, chances are you'll know your application better than a one of the GOF. If it then trips you up down the line, you learn from it and revise your thinking the next time you face this problem.
- deleted 13y ago[deleted]
- bradenb 13y agoIf it's a simple 5 minute change, why not implement it and use DI for a single instance? I imagine you would save a good amount of time by being able to run automated tests now rather than the manual tests you described in your other reply.