On Apr 17, 2011, at 12:03 PM, Kyle Sluder wrote:

> On Apr 16, 2011, at 10:20 PM, WT <jrca...@gmail.com> 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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to