Vincent Gable’s Blog

March 31, 2009

How To Write Cocoa Object Getters

Setters are more straightforward than getters, because you don’t need to worry about memory management.

The best practice is to let the compiler write getters for you, by using Declared Properties.

But when I have to implement a getter manually, I prefer the (to my knowledge) safest pattern,

- (TypeOfX*) x;
{
  return [[x retain] autorelease];
}

Note that by convention in Objective-C, a getter for the variable jabberwocky is simply called jabberwocky, not getJabberwocky.

Why retain Then autorelease

Basically return [[x retain] autorelease]; guarantees that what the getter returns will be valid for as long as any local objects in the code that called the the getter.

Consider,

NSString* oldName = [person name];
[person setName:@"Alice"];
NSLog(@"%@ has changed their name to Alice", oldName);

If -setName: immediately releasees the value that -name returned, oldName will be invalid when it’s used in NSLog. But if the implementation of [x name] used retain/autorelease, then oldName would still be valid, because it would not be destroyed until the autorelease pool around the NSLog was drained.

Also, autorelease pools are per thread; different threads have different autorelease pools that are drained at different times. retain/autorelease makes sure the object is on the calling thread’s pool.

If this cursory explanation isn’t enough, read Seth Willitis’ detailed explanation of retain/autorelease. I’m not going to explain it further here, because he’s done such a through job of it.

Ugly

return [[x retain] autorelease]; is more complicated, and harder to understand then a simple return x;. But sometimes that ugliness is necessary, and the best place to hide it is in a one-line getter method. It’s self documenting. And once you understand Cocoa memory management, it’s entirely clear what the method does. For me, the tiny readability cost is worth the safety guarantee.

Big

return [[x retain] autorelease]; increases peak memory pressure, because it can defer dealloc-ing unused objects until a few autorelease pools are drained. Honestly I’ve never measured memory usage, and found this to be a significant problem. It certainly could be, especially if the thing being returned is a large picture or chunk of data. But in my experience, it’s nothing to worry about for getters that return typical objects, unless there are measurements saying otherwise.

Slow

return [[x retain] autorelease]; is obviously slower then just return x;. But I doubt that optimizing an O(1) getter is going to make a significant difference to your application’s performance — especially compared to other things you could spend that time optimizing. So until I have data telling me otherwise, I don’t worry about adding an the extra method calls.

This is a Good Rule to Break

As I mentioned before, getters don’t need to worry about memory management. It could be argued that the return [[x retain] autorelease]; pattern is a premature optimization of theoretical safety at the expense of concrete performance.

Good programmers try to avoid premature optimization; so perhaps I’m wrong to follow this “safer” pattern. But until I have data showing otherwise, I like to do the safest thing.

How do you write getters, and why?

March 29, 2009

How To Write Cocoa Object Setters

There are several ways to write setters for Objective-C/Cocoa objects that work. But here are the practices I follow; to the best of my knowledge they produce the safest code.

Principle 0: Don’t Write a Setter

When possible, it’s best to write immutable objects. Generally they are safer, and easier to optimize, especially when it comes to concurrency.

By definition immutable objects have no setters, so always ask yourself if you really need a setter, before you write one, and whenever revisiting code.

I’ve removed many of my setters by making the thing they set an argument to the class’s -initWith: constructor. For example,

CustomWidget *widget = [[CustomWidget alloc] init];
[widget setController:self];

becomes,

CustomWidget *widget = [[CustomWidget alloc] initWithController:self];

This is less code, and now, widget is never in a partially-ready state with no controller.

It’s not always practical to do without setters. If an object looks like it needs a settable property, it probably does. But in my experience, questioning the assumption that a property needs to be changeable pays off consistently, if infrequently.

Principle 1: Use @synthesize

This should go without saying, but as long as I’m enumerating best-practices: if you are using Objective-C 2.0 (iPhone or Mac OS X 10.5 & up) you should use @synthesize-ed properties to implement your setters.

The obvious benefits are less code, and setters that are guaranteed to work by the compiler. A less obvious benefit is a clean, abstracted way to expose the state values of an object. Also, using properties can simplify you dealloc method.

But watch out for the a gotcha if you are using copy-assignment for an NSMutable object!

(Note: Some Cocoa programmers strongly dislike the dot-syntax that was introduced with properties and lets you say x.foo = 3; instead of [x setFoo:3];. But, you can use properties without using the dot-syntax. For the record, I think the dot syntax is an improvement. But don’t let a hatred of it it keep you from using properties.)

Principle 2: Prefer copy over retain

I covered this in detail here. In summary, use copy over retain whenever possible: copy is safer, and with most basic Foundation objects, copy is just as fast and efficient as retain.

The Preferred Pattern

When properties are unavailable, this is my “go-to” pattern:

- (void) setX:(TypeOfX*)newX;
{
  [memberVariableThatHoldsX autorelease];
  memberVariableThatHoldsX = [newX copy];
}

Sometimes I use use retain, or very rarely mutableCopy, instead of copy. But if autorelease won’t work, then I use a different pattern. I have a few reasons for writing setters this way.

Reason: Less Code

This pattern is only two lines of code, and has no conditionals. There is very little that can I can screw up when writing it. It always does the same thing, which simplifies debugging.

Reason: autorelease Defers Destruction

Using autorelease instead of release is just a little bit safer, because it does not immediately destroy the old value.

If the old value is immediately released in the setter then this code will sometimes crash,

NSString* oldName = [x name];
[x setName:@"Alice"];
NSLog(@"%@ has changed their name to Alice", oldName);

If -setName: immediately releasees the value that -name returned, oldName will be invalid when it’s used in NSLog.

But if If -setName: autorelease-ed the old value instead, this wouldn’t be a problem; oldName would still be valid until the current autorelease pool was drained.

Reason: Precedent

This is the pattern that google recommends.

When assigning a new object to a variable, one must first release the old object to avoid a memory leak. There are several “correct” ways to handle this. We’ve chosen the “autorelease then retain” approach because it’s less prone to error. Be aware in tight loops it can fill up the autorelease pool, and may be slightly less efficient, but we feel the tradeoffs are acceptable.

- (void)setFoo:(GMFoo *)aFoo {
  [foo_ autorelease];  // Won't dealloc if |foo_| == |aFoo|
  foo_ = [aFoo retain]; 
}

Backup Pattern (No autorelease)

When autorelease won’t work, my Plan-B is:

- (void) setX:(TypeOfX*)newX;
{
  id old = memberVariableThatHoldsX;
  memberVariableThatHoldsX = [newX copy];
  [old release];
}

Reason: Simple

Again, there are no conditionals in this pattern. There’s no if(oldX != newX) test for me to screw up. (Yes, I have done this. It wasn’t a hard bug to discover and fix, but it was a bug nonetheless.) When I’m debugging a problem, I know exactly what setX: did to it’s inputs, without having to know what they are.

On id old

I like naming my temporary old-value id old, because that name & type always works, and it’s short. It’s less to type, and less to think about than TypeOfX* oldX.

But I don’t think it’s necessarily the best choice for doing more to old than sending it release.

To be honest I’m still evaluating that naming practice. But so far I’ve been happy with it.

Principle 3: Only Optimize After You Measure

This is an old maxim of Computer Science, but it bears repeating.

The most common pattern for a setter feels like premature optimization:

- (void) setX:(TypeOfX*)newX;
{
  if(newX != memberVariableThatHoldsX){
    [memberVariableThatHoldsX release];
    memberVariableThatHoldsX = [newX copy];
  }
}

Testing if(newX != memberVariableThatHoldsX) can avoid an expensive copy.

But it also slows every call to setX:. if statements are more code, that takes time to execute. When the processor guesses wrong while loading instructions after the branch, if‘s become quite expensive.

To know what way is faster, you have to measure real-world conditions. Even if a copy is very slow, the conditional approach isn’t necessarily faster, unless there is code that sets a property to it’s current value. Which is kind of silly really. How often do you write code like,

[a setX:x1];
[a setX:x1]; //just to be sure!

or

[a setX:[a x]];

Does that look like code you want to optimize? (Trick question! You don’t know until you test.)

Hypocrisy!

I constantly break Principle 3 by declaring properties in iPhone code as nonatomic, since it’s the pattern Apple uses in their libraries. I assume Apple has good reason for it; and since I will need to write synchronization-code to safely use their libraries, I figure it’s not much more work to reuse the same code to protect access to my objects.

I can’t shake the feeling I’m wrong to do this. But it seems more wrong to not follow Apple’s example; they wrote the iPhone OS in the first place.

If you know a better best practice, say so!

There isn’t a way to write a setter that works optimally all the time, but there is a setter-pattern that works optimally more often then other patterns. With your help I can find it.

UPDATE 03-30-2009:

Wil Shiply disagrees. Essentially his argument is that setters are called a lot, so if they aren’t aggressive about freeing memory, you can have thousands of dead objects rotting in an autorelease pool. Plus, setters often do things like registering with the undo manager, and that’s expensive, so it’s a good idea to have conditional code that only does that when necessary.

My rebuttal is that you should optimize big programs by draining autorelease pools early anyway; and that mitigates the dead-object problem.

With complex setters I can see why it makes sense to check if you need to do something before doing it. I still prefer safer, unconditional, code as a simple first implementation. That’s why it’s my go-to pattern. But if most setters you write end up being more complex, it might be the wrong pattern.

Really you should read what Wil says, and decide for yourself. He’s got much more experience with Objective-C development then I do.

March 17, 2009

Mutable @property and Copy Gotcha

Filed under: Bug Bite,Cocoa,Objective-C,Programming | , , ,
― Vincent Gable on March 17, 2009

If you have a @property for an object who’s name starts with NSMutable, and you use the copy declaration attribute, then the code that is synthesized for you is not correct. Because it uses copy, not mutableCopy, to do the copy during assignment, the value will not be mutable.

Here’s a demonstration,

@interface Gotcha : NSObject {
	NSMutableString *mutableString;
}
@property (copy) NSMutableString *mutableString;
@end
@implementation Gotcha
@synthesize mutableString;
@end

... Gotcha *x = [[[Gotcha alloc] init] autorelease]; x.mutableString = [NSMutableString stringWithString:@"I am mutable."]; [x.mutableString appendString:@" Look at me change."];

It crashes with the message,

*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Attempt to mutate immutable object with appendString:’

copy vs mutableCopy

The copy method returns an immutable copy of an object, even if the object is mutable. Eg the copy of an NSMutableString is an immutable NSString.

The mutableCopy method returns a mutable copy of an object, even if the object is not mutable. Eg., the mutableCopy of an NSString is an NSMutableString object.

@synthesize always uses copy in the setters it generates. That means an immutable copy will always be stored, even if an NSMutable object is given.

Workarounds

Apple says, ” …In this situation, you have to provide your own implementation of the setter method..” (To me, this isn’t as satisfying of an answer as a mutablecopy attribute. But it’s what Apple has chosen, so all we can do is file enhancement requests and trust their reasoning).

Another workaround is to make any property that is a mutable value readonly. If something is mutable, you can change it’s contents directly, so there is rarely a need to set it. For example, with the Gotcha object, it’s just as easy to say

[x.mutableString setString:@"New String"];

as

x.mutableString = [NSMutableString stringWithString:@"New String"];

Finally, you might consider using an immutable readwrite property. In my experience, immutable objects are generally safer, and often faster (I owe you an article on this, but there are plenty of articles on the benefits of immutability). I know this sounds like a smart-ass suggestion, and it won’t be a good answer much of the time. But it’s surprising how often things turn out not to need mutability once a design matures. Since reducing the mutability of an object often improves it, and it does work around the problem, it’s worth at least considering this solution.

Why not Just Use retain?

Changing the copy to retain well let you assign a mutable object, but I do not like the idea. My article, Prefer copy Over retain explains in detail. My biggest worry is aliasing,

NSMutableString *aLocalString = [NSMutableString string];
x.mutableString = aLocalString;
[x doSomething];
//aLocalString might have been changed by doSomething!
//
// 300 lines later...
//
[aLocalString appendString:@" now with more bugs!"];
//x has been changed too!

Using retain with NSMutable objects is asking for bugs.

March 13, 2009

(Always) Showing a Window on Application Switch

Filed under: Cocoa,MacOSX,Objective-C,Programming | , ,
― Vincent Gable on March 13, 2009

Keith Lang said all Mac applications should show a window when you switch to them via command-tab or gestures. I agree. I do think it is best to show nothing when the last window is closed; otherwise closing a window might mean more stuff in your face, not less. But when context-switching back into an application I can’t think of a good reason why applications shouldn’t have something up that you can interact with right now.1

This is the behavior you get when switching between applications by clicking their icons in the dock. It’s unfortunate that you have to do more work for your application to behave consistently no matter how it’s switched-to. Here’s how I’ve done this in IMLocation,

In my NSApplication delegate I implemented - (void)applicationDidBecomeActive:(NSNotification *)aNotification to check if no windows were visible, and if so, put something up. Here’s the exact code I use, replace editCurrentLocation: with what’s right for you:

- (void)applicationDidBecomeActive:(NSNotification *)aNotification
{
	[self displayLocationWindowIfNoWindowIsOpen];
}
- (void) displayLocationWindowIfNoWindowIsOpen
{
	NSArray *visibleWindows = [[NSApp windows] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"isVisible == YES"]];
	if(IsEmpty(visibleWindows))
		[self editCurrentLocation:nil];
}


1Xcode, doesn’t put up anything when you click on it’s icon and you have turned off the “Getting Started” splash screen. This makes a bit of sense, because Xcode is a project editor, not a document editor. Projects are collections of many files, and having an “untitled” default one does not make sense. But by default Xcode shows a window, the splash screen. And there is an argument that it should show an empty file, like an Emacs “scratch buffer”.

March 6, 2009

A Good Basic Computer Science Book

Filed under: Announcement,Programming,Tips | , , , ,
― Vincent Gable on March 6, 2009

In high school, I literally wore out my copy of The New Turing Omnibus: Sixty-Six Excursions in Computer Science. The graphics topics are dated, and there is no discussion about newfangled topics in computing, like the internet. But the meat of the book are timeless computer science fundamentals. It still has the best explanation of what “NP-Complete” means (page 276) that I’ve run across.

The book covers some dense territory, but is still fairly accessible. When my mother asked me, “how can a computer make a random number, if it only does what it’s told?” I pointed her to the chapter 8, “RANDOM NUMBERS: The Chaitin-Kolmogoroff Theory” (page 49). The math was a bit over her head, but she could still read the chapter, and it answered her question. I recommend it to The New Turing Omnibus, without reservation, to anyone who’s considering Computer Science.

What are your favorite introductory Computer Science books?

Patrick Thomson suggests Godel, Escher, Bach: An Eternal Golden Braid. It’s an excellent and fun introduction to the essential theory behind computer science.

Here is an excellent overview of the current state of the P=NP question.

March 4, 2009

Retest Your (Low Level) Optimizations

Filed under: Programming,Quotes | , ,
― Vincent Gable on March 4, 2009

(Measuring before and after applying an optimization is) more important these days. With optimizing compilers and smart virtual machines, many of the standard optimizing techniques are not just ineffective but also counterintuitive. Craig Larman really brought this home when he told me about some comments he received after a talk at JavaOne about optimization in Java. One builder of an optimizing virtual machine said, in effect,

“The comments about thread pools were good, but you shouldn’t use object pools because they will slow down our VM.”

Then another VM builder said,

“The comments about object pools were good, but you shouldn’t use thread pools because they slow down our VM.”

Not only does this reinforce the need to measure with every optimization change, it also suggests that you should log every change made for optimization (a comment tag in the source code is a good option) and retest your optimizations after upgrading your compiler or VM. The optimization you did six months ago could be your bottleneck today.

Martin Fowler (PDF), 2002

I’ve written before about the decay of machine-specific optimization. Even if your code isn’t run by a VM, I think it’s reasonable to expect that (at least some of it) might be run on a smartphone in the near future.

March 3, 2009

Vincent’s Notes: End To End Arguments in System Design

Filed under: Programming | , , ,
― Vincent Gable on March 3, 2009

At Michael Tsai’s suggestion I listened to the paper End-To-End Arugments in System Design while driving. (Fair warning: Since I was also driving while listening, I didn’t absorb everything as well as I should have.)

The thrust of the paper is that you generally want to make your low level components (aka libraries) simpler then you think. Counter-intuitively, building extra reliability into a low-level component does not (usually) make it easier to build a reliable application that uses the component. That’s because the application has to work around all sorts of other errors from different components. So it must have error handling code. Making one low level component “smarter” does not change this. But it does make the component more complex. And some of that complexity is duplicate code that does just what the application’s error handling code does.

The “End to End” in the title of the paper is from a file transfer application having to do an “end to end” check to make sure that the files at both end of the transmission are the same.

Conclusions

End-to-end arguments are a kind of “Occam’s razor” when it comes to
choosing the functions to be provided in a communication subsystem.
Because the communication subsystem is frequently specified before
applications that use the subsystem are known, the designer may be
tempted to “help” the users by taking on more function than necessary.
Awareness of end-to-end arguments can help to reduce such temptations….

February 19, 2009

Security vs? Usability

Filed under: Design,Programming,Quotes,Security,Usability |
― Vincent Gable on February 19, 2009

In most cases, how an authentication system works when a legitimate user tries to log on is much more important than how it works when an impostor tries to log on. No security system is perfect, and there is some level of fraud associated with any (authentication method). But the instances of fraud are rare compared to the number of times someone tries to log on legitimately.

Bruce Schneier on balancing security and usability

I like thinking about security. But, inspite of all the dramatic headlines, I believe bad usability causes far more damage then the bad security.

A more usable system should make recovering from a security breech easier. It’s easier to make things right, when it’s easier to make things.

Usability limits what people can do with something. Is it just coincidence, or does that sound like a partial definition of security?

February 18, 2009

Competing Software Engineering Approaches

Filed under: Cocoa,Programming,Quotes,UNIX | , , , , ,
― Vincent Gable on February 18, 2009

Tim Bray,

…Palm’s approach is
radically different from both Android’s and Apple’s. Since they’re all here
at more or less the same time, running the
same Web browser on roughly
equivalent hardware, this represents an unprecedented experiment in
competitive software-engineering approaches.

Language Framework Notes
Apple Objective-C Cocoa Old-school object-oriented language compiled to the metal; general-purpose UI
framework with roots reaching back to NeXT.
Android Java Android Java language, custom VM, built-from-scratch UI
framework aimed at small-form-factor devices, fairly abstraction-free, based
on “Actions” and “Intents”.
web OS JavaScript “Mojo” All Web technology all the time. Innovative and visually-impressive
“card”-based UI.

(I think it’s interesting to see Windows Mobile on the list:

Windows Mobile C/C++ Windows CE/.NET Micro Philosophically tries to bring Windows to the phone. When I did WinCE development it felt like doing C++ for a Windows OS from the past.

)

I see way too many other factors to attribute success/failure of the devices to the language. So I wouldn’t call this an experiment.

But it is interesting how much development for each platform diverges at a fundamental level!

Historically most operating systems —
UNIX, OS/2, Linux, Windows, Solaris, Mac (Classic and OS X) — were predominantly, written in C/C++. While each platform has it’s own frameworks, they all have strong support for C++ development. (Although Mac OS X has is slowly dropping support for it’s C/C++ “Carbon” API, and Windows wants to be moving to C# .NET)

It’s really cool to see mobile platforms doing something radically different from each other. There are good arguments for each approach — may the best one win.

February 16, 2009

Simplifying by Adding Features

Filed under: Accessibility,Design,Programming,Quotes,Usability | , , ,
― Vincent Gable on February 16, 2009

One of the oldest canards in the interface business is the one that says “Maximizing functionality and maintaining simplicity work against each other in the interface” (Microsoft 1995, p.8). What is true is that adding ad hoc features works against simplicity. But that’s just bad design. It is often, but not always, possible to increase functionality without increasing difficulty at a greater rate. Often, added functionality can be had without any added interface complexity; note the difference between interface complexity and task complexity. If the added functionality unifies what had previously been disparate features, the interface can get simpler.

— Jeff Raskin, The Humane Interface (page 201)

Examples of this are the exception, not the rule. Usually, more features means more complexity.

The best example I can think of is Coda, an award-winning web development IDE.

text editor + file transfer + svn + css + terminal + books + more = whoah.

The story of Coda.

So, we code web sites by hand. And one day, it hit us: our web workflow was wonky. We’d have our text editor open, with Transmit open to save files to the server. We’d be previewing in Safari, adjusting SQL in a Terminal, using a CSS editor and reading references on the web. “This could be easier,” we declared. “And much cooler.”

(To really get a sense of Coda you should check out the website, or try it for free).

Even though Coda’s interface is more complicated because it does more then just edit code, it simplifies the task of web-design, by unifying tasks that used to be done in different applications with different interfaces.

What other examples of things becoming simpler through added functionality can you think of? Please share in the comments below.

« Newer PostsOlder Posts »

Powered by WordPress