Re: design question
Re: design question
- Subject: Re: design question
- From: Quincey Morris <email@hidden>
- Date: Tue, 22 Mar 2011 17:58:57 -0700
On Mar 22, 2011, at 16:53, Graham Cox wrote:
> That's because a) NSMutableArray IS a NSArray, and b) your method has told its clients it is returning an NSArray, so the client has no right to go any further than the methods of NSArray with that object, that is, it cannot make use of knowledge it doesn't have to treat it as mutable. If you want the client to know that the array really is mutable, your return type should say so.
I agree with this part. The client would have to examine the class at runtime to find out it was mutable, and that would be a bug.
> The only issue is whether having returned the array, its contents could mutate while someone else is retaining it. But if the client is holding onto it that long (in a synchronous situation) its contents won't reflect the reality of the content of the object it got it from in any case. Alternatively, once the tree is built from the XML document, why would the structure change? If you're writing an editor, the structure will change, but in that case you probably won't have a case where a stale copy of 'children' is cached anywhere. In all the typical cases, the copy is likely redundant. If a client knows that it will be holding on to the array for "a long time", and that it got it from an object whose contents are probably dynamic (according to this very common pattern) then it can make a copy itself if it needs to. It is in a better position than the vending object to know whether the copy is needed or not (which is why most copying that is done is implemented by an object setter, not in a getter).
>
> On the other hand whether to copy or not is really a (usually minor) performance issue rather than anything more fundamental, so worrying about it now is unlikely to be worthwhile. However I think that paranoia leading to copying everything everywhere indicates a basic lack of understanding about the design you're implementing. By habit and reflex, not copying is the norm, and copying should only be done when it is understood that it is truly necessary. Doing it "just in case" is pointless.
I disagree with you on this part. It's slightly more complex than that. There are 2 basic *semantic* possibilities:
1. This method is the implementation of a property (whether or not it's an @property isn't important).
2. This method is just a method.
If #2, there's nothing to be discussed. The behavior of the return value is a matter for the API contract for that method, and there's no general rule. Often, though, #2 isn't the intended meaning for a method that takes no parameters and returns a value.
If #1, then there's a second pair of more interesting possibilities:
1a. The property is an attribute.
1b. The property is a to-many relationship.
If #1a, then the return value should be unchangeable, in the sense that it should never change after being returned (regardless of whether the returned object is of a mutable class or not). That means, if an existing mutable array is the desired return value, which the owning class might mutate later, a copy *must* be returned instead.
If #1b, then the return value should be assumed to be changeable, in the sense that it could change any time after being returned. (Again, the return value's class's mutability is irrelevant.) *Semantically, what's being returned is a "proxy" for the relationship*, not an array. In this case, the return type merely indicates whether the caller can mutate the relationship via the "proxy" or not.
In practice, it works in reverse. If the method returns something unchangeable, the property is regarded as an attribute. If it returns something changeable, the property is regarded as a to-many relationship.
This is consistent with Core Data properties, and keeping the distinction clear keeps the API design honest and helps write correct code -- it makes it easy to decide whether to return a copy of the underlying array or not.
Your discussion about "how long" and "why" has different answers depending on which of the two kinds of properties is involved. The pitfall here is that if the property is intended to be a snapshot of the state of a relationship (an attribute, as opposed to the actual relationship), returning the underlying mutable array without copying is a bug, even if the return type is NSArray.
_______________________________________________
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