Re: Proper way to create a singleton without @synchronized ?
Re: Proper way to create a singleton without @synchronized ?
- Subject: Re: Proper way to create a singleton without @synchronized ?
- From: WT <email@hidden>
- Date: Sun, 17 Apr 2011 15:43:13 -0300
On Apr 17, 2011, at 12:03 PM, Kyle Sluder wrote:
> On Apr 16, 2011, at 10:20 PM, WT <email@hidden> wrote:
>
>>
>> On Apr 17, 2011, at 12:31 AM, Kyle Sluder wrote:
>>
>>> Do you really need a singleton, or just a default instance?
>>
>> A singleton.
>
> Okay, next question: why? Is there a reason that you can't replace all your calls to +alloc/-init with +sharedInstance?
I suppose you meant to say replace alloc/init calls with +defaultInstance. I think I already explained why: I like to have few and well-defined responsibilities for each class. A true singleton - that's written, tested, and debugged once - has a very specific responsibility and is very reusable, even when it's used in place of a default instance.
>>> All of these could be made static variables within the method body,
>>> increasing readability and reducing pollution of the global scope
>>> without affecting storage longevity.
>>
>> It's the coding style I'm used to, listing the statically allocated variables at the top. I don't see how declaring them inside the methods that use them helps to reduce pollution of the global scope, since they have to be visible to different methods in the same compilation unit anyway.
>
> Because variables are scoped to their enclosing block. Top-level variables are global scoped. Variables within blocks are accessible only within that function's scope.
Top-level variables are global to the compilation unit, in this case the .m file. That's hardly polluting the global scope.
> If you find you only use a global static variable from within one function, you lose nothing by moving that static variable into the function. Well, except for the ability to access it from other functions, but you weren't using that.
You're correct about the dispatch_once() predicates, but the singleton sharedInstance static is accessed by different methods so it must be declared at the top level of the .m file.
>>> Rather than relying on -allocWithZone: to return the shared instance,
>>> why not assign to stSharedInstance here?
>>
>> No reason other than that this implementation is based on the singleton implementation I saw in some Apple documentation.
>
> Mike Ash had a good blog post about singletons which you may want to read: http://www.mikeash.com/pyblog/friday-qa-2009-10-02-care-and-feeding-of-singletons.html
Thank you for that link. That and the article Ken suggested will be my light afternoon reading for this Sunday. :)
>>> You are in a class method. self == [self class], so no need to call +class here.
>>
>> What if I'm trying to subclass this singleton?
>
> Hint: +class is defined to return self.
I'll say here what I said in my reply to Ken...
Tell that to Erik Buck and Donald Yacktman, the authors of 'Cocoa Design Patterns'. They explicitly assert on the second paragraph of page 151 that [self class] is used instead of self to support instantiating the appropriate subclass. Clearly there is some confusion regarding this matter, even among people more experienced than I, so I don't feel so bad by being confused about it too. :)
>>> Of course this means you can't subclass this class.
>>
>> Why not? As long as the subclass doesn't override +allocWithZone:, this shouldn't be a problem, no?
>
> See Dave's reply.
I get that the single static variable precludes subclassing. It was your singling out +allocWithZone: that made me think that there was something specific to it that prevented subclassing.
>> but the compiler complained that self is read-only within the scope of the block. I needed a way to write to self and I couldn't redeclare self, hence a writable tempSelf.
>
> Bah. I swear one of these days I'll remember the const copy thing that happens to non-__block variables. :) My use of blocks almost never touches self, so the relatively few self gymnastics I see or use are about avoiding leaks.
As I said above, there are things that sometimes confuse even those who are more experienced programmers than I, so I've learned not to be surprised when I or others fall for traps like that.
>> Well, it is if I need a true singleton and sometimes I do. In fact, I kinda often do. I tend to break down my code into classes with very well defined, and typically few, responsibilities. Often times, making them singletons simplifies my code.
>
> Making them singletons can never be simpler than just not creating more than one instance of a regular class.
It's amortized simplicity :) I'm a big fan of reusability.
>> For instance, I never put all the core data stack methods in the application delegate. I have a singleton that takes care of all things core data (well, all things that can be done generically). Likewise, I have a singleton for locale "utilities". All my number and date formatters are there, in one place, created once on demand and accessible everywhere else through the singleton. That's the kind of usage I have for singletons.
>
> As for the first example, do you bother to make your app delegate a singleton? Probably not.
The app delegate interacts with the rest of the application in a somewhat special way. For instance, an instance of it is in the main nib. Yes, I know that that's not anything magical, and that it's instantiated when the nib loads by having the good old alloc/init invoked, so I could make the app delegate a singleton and everything would still work. I don't, though, because I don't want to possibly break future interactions between the app delegate and the rest of the app. The other singletons in my projects, however, are entirely under my control.
> So why worry about the Core Data stack?
>
> As for the second, most "utility" methods can be written as categories and/or class methods or functions.
One of my primary design goals in any project of mine is division of responsibilities, because it simplifies the design, simplifies the code, and supports reusability. If I can duplicate a project (or have a custom template), and simply delete a couple of files and a line or two of code in my app delegate, rather than have to go through all the code in the app delegate that isn't applicable to my new project, then it's a win for me.
Here's another example. I have a ReachabilityMonitor singleton class that takes care of hiding the details of using the Reachability API from the rest of the app. It even deals with showing and hiding an alert view when appropriate, and doing so in a localized fashion.
The app delegate has only 2 lines that deal with it: the import of ReachabilityMonitor.h and a call to the singleton to start things up. That's it. So, if I duplicate a project that uses it but I then won't need it, those 2 lines are all I need to delete from the app delegate, in addition to removing the reachability source files from the project.
As for the utility singletons, I think you misinterpreted what I wrote. I wasn't referring simply to collecting utility methods in one place. My LocaleUtils singleton is a good example. It's a bona-fide concrete class that stores the most common date and number formatters I use, and they're instantiated in a lazy manner. Nowhere in my apps I need to create and configure them; I can simply access them from the singleton and I *know* that they will be correctly configured for the current locale, even changing automatically when the locale changes. Again, it's an issue of dividing responsibilities.
Now, you might argue that these classes don't necessarily need to be true singletons and that default instances would be just fine, and you'd have a good point. But, then, singletons can be used in place of default instances when there's no need for more than one instance, and the singleton boiler-plate code is already written and debugged (or will be, once I'm done).
> Granted, sometimes they don't *have* to be singletons (they don't represent expensive resources) and I could just as well have a default instance. The locale utilities is such an example. Then, again, why allow for that possibility when it's logically sound that I should only ever need one instance?
>
> Because code that never gets used is code that should never be written.
But it does get used.
>> Rather than go into a philosophical discussion of the kind "when/why singletons?", let me rephrase and focus my original plea for help: how would you implement a *true* singleton class that supports subclassing?
>
> This is s contradiction in terms. Because every subclass instance is also an instance of its superclass, there will be multiple superclass instances.
That's because obj-c isn't, in my view, as clean a language as java. There's no way in obj-c to enforce a class to be abstract. I can see valid reasons to subclass a singleton when the base class is supposed to be abstract. See Andy's reply to Dave for some examples of that.
WT
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden