Re: Future Objective-C changes
Re: Future Objective-C changes
- Subject: Re: Future Objective-C changes
- From: Chris Meyer <email@hidden>
- Date: Wed, 21 May 2003 09:31:52 -0700
<CodingHorror>
class MyGraphicsContextSaver
{
MyGraphicsContextSaver( NSGraphicsContext *gc ) { [gc
saveGraphicsContext]; }
~MyGraphicsContextSaver() { [gc restoreGraphicsContext]; }
}
Then in my Objective-C++ method I could write:
- (void)drawMyObject
{
MyGraphicsContextSaver gcs;
DoSomeStuffWhichMightThrowExceptions();
}
</CodingHorror>
Actually, the first time I saw this construct, I thought: Wow! How
cool is that!
On further examination, and having absorbed Kent Beck's Best Practice
Patterns, it struck me just how awful this sort of code is.
Talking bout non-intention-revealing code! How much more obscure can
you get than an *automatic variable declaration* causing a global
state change. Let me say it again: you are simply declaring a
local, automatic variable, but what you are *intending* to do is
modify some global state.
Restated: How much more obscure can you get than a local function call
causing global state change? Best practices: DON'T USE GLOBAL
VARIABLES! The graphics context, like it or not, is a global variable
in this version of Cocoa.
Yep, it has some 'interesting' properties, but the price is just too
high, there must be other ways of achieving the desired effect.
[snip]
If Objective-C++ is the future, then integrating the exceptions
mechanisms is essential.
This may be the case, but I haven't actually seen a crucial need for
it in my last 15+ years of Objective-C hacking.
How many times have you:
1) forgot to restore graphics context?
2) forgot to super dealloc?
3) forgot to retain/release properly?
4) forgot to restore clipping state?
5) forgot to release an autorelease pool?
And how much time over 15 years has been spent searching source code
for the memory leaks and other problems associated with those foibles?
I would guess that if you honestly add up all of that time you can
begin to see the need for these types of niceties.
I'm really not proposing any new features to the language just yet. Nor
am I sold on Objective-C++ yet. And I don't see a clean way to
implement some of this stuff (although the HOM stuff presents some cool
ideas). But I do recognize that there COULD be language and/or
convention improvements to make it easier to do Objective-C programming
which eliminated the problems above:
1) use a solution similar to HOM. the problem with this is that it
doesn't allow you to write inline blocks of code. you would need a
separate method.
2) implement - (void)autoDealloc which is invoked automatically by the
regular dealloc implemented at the NSObject level. it would iterate
through the hierarchy of classes.
3) macros can help here perhaps.
4) HOM solution.
5) HOM solution.
If Objective-C is the way to go, then an extension to move towards
the functionality of smart pointers would be nice. It might solve
issues with reference counting (which aren't difficult once you
master them, but definitely error prone),
Hmm...I don't find it error prone. If you use convenience factor
methods for temporary objects, then the only place you need to deal
with reference counting is the accessor. If you use accessor-macros,
the accessors, and especially the refcounting that goes on inside them
essentially disappears, and the whole thing is automatic (apart from
dealloc, but that is so straightforward/boiler-plate that it just
disappears in the other syntactic noise of creating a class).
So I don't quite see what smart-pointers would add, except for
overhead because they generally have to refcount on every assignment,
right?
I think its safe to say that every single person writing Objective-C
has at one time or another failed to retain or autorelease at the right
time (just try to close some project windows in PB sometime heh heh).
In C++ with smart pointers it was nearly impossible to make an error
like that.
issues with dealloc (I often forget to invoke [super dealloc]), and
other assorted memory leak problems.
Tip: when you write your dealloc method, start it off like this:
-(void)dealloc
{
[super dealloc];
}
I do this but it is still error prone. With smart pointers and
destructors in C++ it is impossible to make this kind of error. Now C++
has its own set of problems and I'm not advocating adding templates or
classes with auto destructors to Objective-C; I'm just pointing out the
nice things about C++ that are missing when doing Objective-C (not C++)
programming.
Only then start to add your local deallocation.
Imagine that you could write code like the following:
- (void)myThread
{
smart_pointer<NSAutoreleasePool> pool = [[NSAutoreleasePool alloc]
init];
my_thread_code();
}
And [pool release] would guarantee to be called no matter what
exceptions were thrown in my_thread_code()!
Not sure what that would bring me, since threading is pretty rare, and
if there are exceptions, I would want to know about them anyway, so I
need to put in my handler and then putting the pool-release code
outside is no big deal either.
You're dating yourself by stating "threading is pretty rare." :)
Again -- no big deal if 1) you know what you're doing; 2) you NEVER
forget. Forgetting just once costs you an inordinate amount of
debugging time since these types of bugs are typically difficult to
locate. (And please don't tell me about some tool that helps the job;
my definition is that if I have to launch another tool IT IS DIFFICULT!)
I'd rather have that sort of stuff explicit rather than magical, I
think. The tiny amount you save when typing is, IMHO, far outweighed
by the obscurity that results.
It's not typing that you save. It's debugging. Typing has nothing to do
with it.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.