Convenience #DEFINEs

Update: Lazy programmer, indeed! After doing some research myself this afternoon (at the prompting of Karsten), I’d recommend not using anything but the ZNCGAutoRelease() method below — the others aren’t dangerous, but they’re really not necessary and just obscure your ability to properly debug your code. As for using macros, well, I guess that’s a matter of personal preference — what I’ve seen so far is that it does make debugging harder — you’re probably better off implementing proper methods for repeatable tasks. But it works if you want to use it.

When I first started working on VirtueDesktops (all those years ago), I was still new to Objective-​C and very new to the concept of (mostly) manual memory management. Thankfully Thomas (the previous developer) had the foresight to do what all good, lazy programmers should do and write himself a few small convenience methods into his codebase.

They’ve had a couple of minor additions and changes since then, but line-​for-​line, they’ve stood the test of time and I find them an invaluable way to reduce some of the fuss involved in manually managing your object assignments, copies and releases.

#define ZNCGAutoRelease(x) (__typeof(x))[NSMakeCollectable(x) autorelease]

#define ZNAssign(aTarget, aSource)  \
if (aTarget != nil) {               \
    [aTarget autorelease];          \
}                                   \
aTarget = [aSource retain];

#define ZNAssignCopy(aTarget, aSource)  \
if (aTarget != nil) {                   \
    [aTarget autorelease];              \
}                                       \
aTarget = [aSource copy];

#define ZNRelease(aTarget)          \
if (aTarget != nil) {               \
    id oldObject = aTarget;     \
    aTarget = nil;                  \
    [oldObject release];            \
}

I use these everywhere in my code, but just the other day I discovered the absolutely incredibly wonderful CLANG Static Analysis tools (more on this shortly!), and based on some feedback it gave around these calls (nothing bad!) it made me wonder — should I be #DEFINEing convenience methods? Is this best practice? Should I go back to doing this all by hand?

I’m hoping some of my CocoaPeers™ will be able to provide me with some advice here, but if you think the code’s good for your needs — go for your life and use it.

Oh, and happy 4th of July to our friends in the states. We’re waiting for you here on the 5th :)

Comments

Gravatar for Karsten.

you don’t need to do all those nil checks. Unlike in Smalltalk, you can send mes­sages to nil in Objective-​C. If a mes­sage is sent to nil, noth­ing hap­pens. You should read this post about Nil over at redicu​lous​fish​.com: <http://​ridicu​lous​fish​.com/​b​l​o​g​/​a​r​c​h​i​v​e​s​/​2005​/​05​/​29​/nil/> there’re plenty of other highly inter­est­ing posts there about Objective-​C in general.

Any­way, in gen­eral I’d avoid using Macro Func­tions. The com­piler already opti­mizes the hell out of your code. Macro Func­tions are also unness­esar­ily hard to debug and prone to errors. If you do want to use such snip­pets, using them as c-​functions should do :-)

just my two cents… Kind Regards Karsten

Posted by Karsten on

Gravatar for Tony Arnold.

Thanks Karsten — that’s exactly the sort of feed­back I was look­ing for!

The main rea­son for ZNRelease() is that I often deal with Core­Foun­da­tion objects — ZNRelease() just means I use the same release state­ment for both types (which is lazy, I know!). Does this still count as valid?

Posted by Tony Arnold on

Gravatar for Samuel Williams.

I think your use of macros in this case is okay. The rea­son being is that not repeat­ing your­self is gen­er­ally a good thing, and I think that using these macros will gen­er­ally reduce the num­ber of errors in your code. Mem­ory man­age­ment errors are typ­i­cally fairly severe when they occur, and thus avoid­ing them (i.e. seg­faults, etc) is good.

Being sys­tem­atic and reduc­ing code com­plex­ity is gen­er­ally a good thing, and that is what these macros are help­ing with. The only thing you would be doing by remov­ing these macros and replac­ing them with code, is adding many more lines of boiler plate mem­ory man­age­ment and many places for typos and errors to creep in.

Posted by Samuel Williams on

Gravatar for Tony Arnold.

After a lit­tle more research, it looks like you can’t send release to nil (which I’d always assumed). This makes ZNRe­lease() a lit­tle more inter­est­ing, but still a macro. I’m going to try doing this all by hand for now.

Posted by Tony Arnold on

Sorry, this conversation has finished.

This post is a bit old now, so I've closed the conversation. If you're keen to keep talking about it, please email me directly.