• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Accessors (can we close it this way?)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Accessors (can we close it this way?)


  • Subject: Accessors (can we close it this way?)
  • From: Ondra Cada <email@hidden>
  • Date: Wed, 7 Aug 2002 16:22:11 +0200

First, anybody who feels he does not fully understand the issue, do please read the article

http://www.stepwise.com/Articles/Technical/2002-06-11.01.html

It explains all the details in a much more intelligible way than this discussion (well, the facts are almost identical, but the article is didactic, whilst the thread is chatoic ;)

On Wednesday, August 7, 2002, at 12:00 , Marcel Weiher wrote:

I am glad you brought this up: for a client, wether something is an accessor or not does not and should not matter. For a client, it is just a method that returns a value.

Very right. And, in Cocoa with its autorelease pools, unless documentation explicitly says otherwise,

THE VENDOR'S RESPONSIBILITY IS TO ENSURE THAT THE VALUE KEEPS VALID AT LEAST FOR THE SCOPE OF THE CURRENT AUTORELEASE POOL

I don't want to discuss again and again whether this contract is reasonable (as I think, for good reasons) or irrational (as Marcel thinks,
for perhaps even better reasons, though to me they don't seem such). Nevertheless, in Cocoa, it just is so:

On Wednesday, July 31, 2002, at 07:56 , Ali Ozer wrote:

The API contract for most Cocoa APIs is that the following is valid: (**)

{
str = [someObj title];
... do other stuff ...
... access str ...
}

For me, it's another of Cocoa great features. For Marcel, it probably is another of Cocoa design bugs. Any road, it is just so. That does not mean all classes should do so; OTOH, it *does* mean that classes which DO NOT do so *should be documented as such*.

(In current Cocoa frameworks, for historical reasons, they often are not. That is considered a documentation bug and should be eventually fixed.)

Furthermore, a client shouldn't have to distinguish between "simple collections" and "complex objects" or whatever else in order to know what to do.

(a) with a simple container, the methods are straighforward. You *do* know that -count or -objectEnumerator won't ever release any of the contained objects. With eg. a window title, though, you *don't* know whether *any* method might not, for some arcane implementation-hidden reason, release the title (and, for example, replace it with another string of the same contents).
(b) with simple containers, we HAVE TO put up with the inconvenient case of "not fulfilling the (**) contract" for efficiency reasons.

It should be emphasized that the difference can be VAST! A benchmark I've rigged up and Marcel considerably improved showed that

- in normal average code, the plain getter (return ivar) can be roughly TEN TIMES slower than the safe one (return [[ivar retain] autorelease]);
- if clients use IMP-based optimization, the difference can go up to FORTY FIVE TIMES!

Therefore, you should definitely consider the usage patterns; if there is probability of thousands or more getter accesses in succession, clients just have to put up with the plain getter (for otherwise the speed penalty would be too big).

Still though there are classes -- in my personal experience, a majority of them! -- usage of whose getters in any sensible design would stay in tens,
at the very worst low hundreds: things like NSTask, NSWindow, NS...Views,
or even the lightweight NSCells. For such classes, I would advocate usage of the safe getter (return [[ivar retain] autorelease]) for either conveniency (should you otherwise go the (a) way below) or safety (should you otherwise go the (b) way below).

(In current Cocoa, for historical reasons, these classes often don't use the safe getters. That is considered an implementation bug and should be eventually fixed. Some such cases were fixed already in Jaguar.)

Just follow the ownership rules and you'll be fine.

You WON'T, for the reasons stated below, (***). There are only two things you can do

(a) safe but quite inconvenient if used any time for any getter of any class

EVERYTIME use one of these four patterns:

id o=[foo getter];
// NO CODE HERE!!!!
[o whatever];
// o NEVER MORE USED

id o=[[[foo getter] retain] autorelease];
// all right here, for you precisely repeated what should have been done in the getter

id o=[[foo getter] retain];
// code you are sure won't raise
[o whatever]; // whatever can't raise either
[o release];

id o=[[foo getter] retain];
NS_DURING
// code which might raise (almost any nontrivial code in Cocoa!)
[o whatever];
[o release];
NS_HANDLER
[o release];
[localException raise];
NS_ENDHANDLER

(b) convenient, very often used, but with plain getters inherently unsafe (***)

id o=[foo getter];
... something ...
[o whatever];

This code *MOSTLY* works, I do agree with Marcel that cases when it does not are *RARE*.

The problem is that with complex classes (of foo) you CAN NEVER KNOW in which conditions the problem might occur (and therefore you CAN'T say "here it's safe, no need for (a) patterns"). Not even "not using foo in ...something..." is absolutely safe, for the class just *might*, say, respond to some notification (posted by ...something...) by sending the setter to itself!

So, the problem is that if you use plain getters with this client pattern,
the application might crash quite unexpectedly eg. with a future bug-fix framework release: the reason would be that you used a wrong code, which would crash only "RARELY". Myself, I prefer code which won't crash -- even if it is somewhat slower.

Marcel advocates that for the consistency sake it should be so with ALL classes. I do agree that it would be consistent; I don't think that would be a good idea though for it would mean we are back in the (a) solution for *any* class, and the inconvenience of it would be (from my subjective point of view) much worse than the gain of the consistency. OTOH, I'd like to point out again that the safe getter can be CONSIDERABLY slower, and thus should not be used if there is a possibility of a really heavy usage.
---
Ondra Cada
OCSoftware: email@hidden http://www.ocs.cz
private email@hidden http://www.ocs.cz/oc
_______________________________________________
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.
  • Follow-Ups:
    • Re: Accessors (can we close it this way?)
      • From: Marcel Weiher <email@hidden>
    • Re: Accessors (can we close it this way?)
      • From: Marco Scheurer <email@hidden>
    • Re: Accessors (can we close it this way?)
      • From: Ondra Cada <email@hidden>
References: 
 >Re: Accessors (From: Marcel Weiher <email@hidden>)

  • Prev by Date: Re: NSTableView setDoubleAction/NSControl setAction
  • Next by Date: forwardInvocation: Works Locally but crashes with DO
  • Previous by thread: Re: Accessors
  • Next by thread: Re: Accessors (can we close it this way?)
  • Index(es):
    • Date
    • Thread