On Aug 16, 2015, at 09:10 , Seth Willits <sli...@araelium.com> wrote:
> 
> Really? This list has no opinions? That's hard to imagine :-)

Well, I do, but I didn’t post it because I didn’t think you’d like it.

I don’t think it’s worth annotating private methods at all (in general — I’m 
sure there are specific cases where it’s a clear benefit). It seems to me there 
are 2 main reasons why you’d want to:

1. Documentation/API contract

When creating methods for *others* to use, such as at the API boundary of a 
framework, the more clarity the better, and the more the compiler can check the 
better. But for methods that are internal to an implementation, the chances are 
that the “client" code will have been written before the nullability is settled 
— or the nullability is obvious enough that the annotation isn’t needed.

2. Swift compatibility

This is the important case, because the nullability changes the type of the 
interface when bridged into Swift.


When neither of the above is a controlling consideration, for the majority of 
pure Obj-C code, nullability annotations seem rather redundant. I see 3 issues:

a. Origination

For a method that originates an object pointer — typically an ‘init’ method or 
a factory class method that basically wraps an ‘init’ — I think it’s better not 
to return nil at all, in most cases. That is, if super init may itself return 
nil, then you should test for that and crash, rather than just passing on the 
nil.

If the originating method does need to indicate failure by returning nil, the 
pattern I’ve adopted is *always* to return a NSError via a NSError** parameter 
in the normal way. Not only is this self-annotating, both in the interface and 
at every call site, it also promotes proper error handling by making it clear 
when you’ve left an error unhandled at the call site.

b. Propagation

Once you’ve adopted a consistent origination pattern, then propagating object 
pointers (that is, passing them around as parameters) stops being problematic, 
mostly, since they mostly aren’t nil by accident …

c. Optionality

… except in the the case where you specify nil literally, as in the case of an 
optional parameter value. Some such cases are already covered by Obj-C coding 
patterns. For example, if you’re passing a dictionary of options, passing nil 
instead of an empty dictionary is probably all the same to the called code.

Sometimes it does matter. For example, when passing a completion block, it 
really matters whether it can be nil or not, because invoking a nil block 
pointer will crash. In such cases, the implementation (having decided whether 
it will check for nil or require non-nil) *should*, I think, annotate the 
method parameter, but I’d be inclined to do that in *both* the @implementation 
and @interface if both exist, just like you would for something like ‘const’.


My argument in all this is that Obj-C has its own characteristic patterns for 
handling nil object pointers, which may be diverse and situational, but have 
been honed by time. The new annotations (including NS_DESIGNATED_INITIALIZER 
and generics) seem to me to be geared towards reducing the impedance mismatch 
with Swift, and I think it distorts Obj-C to Swift-ize it if it’s not actually 
being bridged.

In the relatively rare cases where annotations resolve an existing pain point 
(such as nil vs. non-nil completion block pointers), then use them. But I’m 
unconvinced about the need for wholesale adoption.



_______________________________________________

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

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

Reply via email to