Re: Core Data debugging
Re: Core Data debugging
- Subject: Re: Core Data debugging
- From: Timothy Wood <email@hidden>
- Date: Thu, 16 Jul 2009 16:49:13 -0700
On Jul 16, 2009, at 3:54 PM, Quincey Morris wrote:
Aside: If the developer of bar "forgot" to set *outError, then the
developer of bar forgot to set an output parameter, and that's not
just a bug on the developer's part, but a *horrible* bug.
Sure. And clang-sa should check for this and help you remember to
do it.
On Jul 16, 2009, at 4:16 PM, Quincey Morris wrote:
On Jul 16, 2009, at 15:54, Quincey Morris wrote:
On Jul 16, 2009, at 15:19, Timothy Wood wrote:
then at "xxx" you'd like to build a new NSError that has *outError
(if outError != NULL) as the underlying error....
It seems to be you have this precisely upside-down. outError is an
output parameter, not an an input-output parameter. There *is* no
input value of *outError that can become the underlying error.
Well, I did misunderstand, by not reading carefully enough. But I'd
still be interested to see an example of the code with the macro in
place. Is 'outError' a parameter to the macro at xxx? If so, why
wouldn't you just pass nil as the parameter at yyy?
Yes, outError is a parameter to the macro. You'd not pass nil
along at yyy since you don't want to have to remember to change your
error creation code 3 months later when you are updating. This is
error-prone — you'll forget to change it some percentage of the time —
and it is easily avoidable with clang-sa and better rules in some
future world.
So, as an example, I might want do do something like:
- (BOOL)saveSomething:(NSError **)outError;
{
NSData *data = build some data;
if ([data writeToFile:path options:someOptions error:outError])
return YES;
OBError(outError, ErrorCodeEnum, @"some reason", ... other user info
k/v pairs ...);
return NO;
}
The OBError macro can then:
- Look at outError. If it is NULL, do nothing.
- Build a userInfo dictionary from the vararg list
- Also including NSUnderlyingError = the old *outError
- … perfectly valid here since I'm on the failure path and NSData
should have set it
- Also including file & line number information for help in tracking
this down in user reports
- Build an NSError instance with the correct domain and the passed in
code
- Stuff the error in *outError
This is all find and good. AND it gets it done in _one_ line of
code.
The problem comes when I decide someday that writing this as its
own file isn't right and I switch to storing it using some NSError
oblivious API. As a strawman, maybe NSUserDefaults:
- (BOOL)saveSomething:(NSError **)outError;
{
NSData *data = build some data;
// strawman, remember, I'd not do it this way… =)
[defaults setObject:data forKey:someKey];
if ([defaults synchronize])
return YES;
OBError(outError, ErrorCode, @"some reason", ... other user info k/v
pairs ...);
return NO;
}
Well, now I'm screwed due to these NSError rules. I'm reading
*outError for an optional chained NSUnderlyingError and it might be
trash.
Sure, I should remember to ignore it or initialize it to nil myself
or have a OBBaseError macro, but one day I'll forget. The current
rules make me write more and more fragile code than I'd need to if we
could just all depend on setting NSError locals to nil before passing
them down. I know we can't right now, but I'm saying that makes life
harder than it could be. Cocoa is supposed to round off the rough
corners in programming! =)
-tim
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden