Re: design question
Re: design question
- Subject: Re: design question
- From: Graham Cox <email@hidden>
- Date: Wed, 23 Mar 2011 10:53:03 +1100
On 23/03/2011, at 6:29 AM, Ariel Feinerman wrote:
> Hi,
>
> can someone look at and say is a returning of immutable objects necessary or
> no?
>
> @interface XMLElement : NSObject {
>
>
> NSString *_name;
>
> NSMutableString *_text;
>
> NSMutableDictionary *_attributes;
>
> NSMutableArray *_children;
>
> XMLElement *_parent;
>
> }
>
> @implementation XMLElement
[]
> - (NSArray *) children {
>
> return [[_children copy] autorelease];
>
> }
No, but neither is performing all this excessive copying.
For example your -children method can simply be:
- (NSArray*) children
{
return _children;
}
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.
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.
By the way if you're building an XML tree (presumably from running NSXMLParser) perhaps the NSXMLNode family of objects would be a better choice. If you are writing a streaming parser where the elements are short-lived, I wouldn't expect the element lifetimes to be very long - there are unlikely to be clients that will hold your 'children' array beyond the existence of those children. I just wrote an XML parser like this myself - each parent element maintains a stack of children which are pushed and popped as each child element comes into being, gets processed and then is finished with. Thus the 'children' array (really a stack) is quite dynamic, and usually rather short. The only object that really cares about that stack is the object holding it, so while I do have a method for returning that array, it doesn't perform a copy, and that hasn't caused any problems (in fact, I couldn't swear it's ever used, but it's a habit to provide accessors for private container ivars in the base class for the implementing object - you never know when someone will want it).
To harp on this point about copying:
> - (NSArray *) elementsForName: (NSString *) name {
>
> NSMutableArray *children = [NSMutableArray new];
>
> for (XMLElement *element in _children)
>
> if ([[element name] isEqualToString: name])
>
> [children addObject: element];
>
> NSArray *lchildren = [children copy];
>
> [children release];
>
> return [lchildren autorelease];
>
> }
Why do you build an array in perfect isolation, then copy it before returning it? The array you just built is not used anywhere else and as soon as it's copied it is released and deallocated. The copy is just a waste of time - you are perfectly within your contract with your clients to simply return the mutable array.
--Graham
_______________________________________________
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