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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to