Re: NSError: why returned directly?
Re: NSError: why returned directly?
- Subject: Re: NSError: why returned directly?
- From: Ondra Cada <email@hidden>
- Date: Wed, 26 Apr 2006 14:17:36 +0200
Scott,
On 26.4.2006, at 7:11, Scott Anguish wrote:
if a method returns nil instead of an object, and provides an
error parameter, the error will provide more information. You can
tell that it failed because it is nil. the error will tell you WHY
it failed. this is info you can use to present more feedback.
Yup, of course. What I am asking is what were the reasons behind it
been designed this way, since it forces me to adopt some quite
inconvenient and error-prone patterns (using by-ref returns, manual
unrolling stack, details below). That would mean
(a) Most probably, I am overlooking something important, and am using
NSError the wrong way. If so, I am asking in what I err.
(b) Or perhaps I am using it right and others actually use the same
patterns, but the patterns have advantages over the alternate ones
which exception-like design, outlined below, would allow for. If so,
I am asking what do I overlook and what are advantages of the current
NSError patterns;
(c) Or perhaps (with a very small probability, nonetheless not a zero
one) I am perfectly right and the alternate exception-like patterns
would be better, having no (or negligible) drawbacks and serious
advantages. In this case, if there are no drawbacks I am overlooking,
I would at least turn my private frameworks to use this, to glue the
better (if so) behaviour over "plain" Cocoa.
As for the aforementioned patterns: using NSError for runtime errors,
I found myself in a situation *very* similar to reporting
programmer's errors before exceptions:
// this may detect a runtime error: very often (though not always)
the innermost, model-level code
-(id)innermostMethodWithError:(NSError**)error {
...
if (something) {
if (error) *error=[NSError errorWithDomain:...];
return nil;
}
...
}
// does not detect a runtime error directly, but uses methods which
do, and itself conveys it to upper code levels (sometimes the NSError
gets changed in this level, but myself, I've found such cases very
rare in my code). That's what I call "manual stack unrolling" and
what I very much dislike, for it is tedious and error-prone. I've
found there is comparatively a big number of methods like this: that
would probably mean I use a bad code design?
-(id)intermediateMethodWithError:(NSError**)error {
...
if (![foo anotherMethodWithError:error]) return nil;
...
if (![bar justAnotherMethodWithError:error]) return nil;
...
// and so forth
}
// presents the error: comparatively little number of methods like
this, but they tend to use the same code (pointed out below) which
kinda leads to copy/paste programming (error-prone)
-(IBAction)guiLevelMethodWhichUsesError {
...
if (![foo someMethodWhichGeneratesError:error]) {
[self presentError:error modalForWindow:...]; // a number of
arguments, ...
return;
}
...
if (![bar anotherMethodWhichGeneratesError:error]) {
[self presentError:error modalForWindow:...]; // ... copy/pasted
here and to other methods, too
return;
}
...
// and so forth
}
Presumably since I am overlooking some vast drawback of that, I would
think using the @try/@throw support for *both* NSExceptions (which
would of course still serve for programming errors) and NSErrors
(which would of course still server for runtime errors, keeping the
current proper distinction between errors and exceptions unchanged).
It seems to me it would
(i) make the innermost level simpler, using plain @throw instead of
somewhat error-prone by-ref return (Joar's suggestion of using a
thread variable would achieve this, too, though still the code would
be slightly more complex by having to use an explicit return);
(ii) make the intermediate level *ways* simpler, since it would not
have to cope with errors at all (Joar's suggestion would not achieve
this);
(iii) make the topmost/gui level simpler and cleaner using separate
error handlers in @catch blocks, instead of number of error-prone ifs
(Joar's suggestion would not achieve this);
(iv) it would even make possible to automatically catch and present
errors if the gui level code neglects to do that, which I think is
desirable for simple/test applications (Joar's suggestion would
achieve this with extra effort, like zeroing the thread-global in
presentError:).
At the moment, the one possible drawback I can foresee is a very
remote probability of a need of different @try scopes for catching
NSErrors and NSExceptions (which would cause complex intertwined @try
block patterns). Perhaps, but I have not been able to devise any
concrete example of such a code :)
Thanks a lot for your opinions,
---
Ondra Čada
OCSoftware: email@hidden http://www.ocs.cz
private email@hidden http://www.ocs.cz/oc
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden