Archive for April 25, 2007

Wednesday, April 25, 2007

Large Cocoa Projects

Brent Simmons has posted some good tips for managing large Cocoa projects.

Notifications can make code hard to follow

Singletons, of which the notification center is one, are basically global variables. They’re useful, and they can decouple two classes from one another, but only at the expense of coupling them to the global thing. So I agree with Brent’s advice that two objects that have a relationship should just talk directly; if they’re logically coupled, don’t obscure things with notifications. I think NSNotificationQueue is underappreciated, and perhaps a good smell test is that if you don’t mind your notification being queued and delayed, then your objects are coupled loosely enough that notifications are the right choice.

Key-Value Observing: for prefs only

None of my apps use KVO. I just haven’t had a situation where I thought it would help enough to be worth the expense in complexity. To me, it’s like less explicit notifications with a more convoluted control path. Plus, I get a bad code smell from +setKeys:triggerChangeNotificationsForDependentKey:. The idea that my objects should publish the interdependencies of their properties seems wrong. The whole KVC/KVO system seems to be designed around the idea that objects are dumb structs, and I prefer smart objects that manage their own state and interactions. Other objects should ask them to do things, not set or observe key paths into them.

Bindings are for basic stuff

I really wanted to like bindings, and at one point in the Jaguar days I started designing a framework that would address the same problem that bindings do (in a different way). But after giving them a good try, I’ve decided that they’re not for me. The only place my code currently uses them is in DropDMG’s Automator plug-in, where it’s sort of mandated. Bindings are like the opposite of Perl. They make the easy things a little easier but the harder things much harder. Since the benefit is small, and simple requirements may grow with time, I stay away from the garden path of bindings. Also, I don’t like the code structure that results from using bindings. I find it harder to write automated tests for, harder to debug, and harder to do what Brent calls “research” because some of the information is in nib files, which aren’t as easily searched or diffed. Plus, I don’t like putting my logic into nib files or strings. That’s what code is for. I wish Apple had provided a controller framework that was based on objects.

High-level Interface

I agree with the general idea of having different “levels” of interfaces and being conscious of where everything goes. This ties in with the point about notifications; generally, I use notifications to let lower (inner) objects broadcast messages to higher (outer) ones. Using C functions rather than methods is a neat trick to make the levels stand out visually. Personally, I prefer classes because (a) they force me to think about whether I should pass in an object or use a singleton, and (b) it’s easier to access classes/methods via AppleScript or PyObjC.

Use #pragma mark, use the function popup

Both are great. I have BBEdit’s function pop-up bound to Command-Control-N to avoid killing kittens.

Opening Files

I don’t use Open Quickly (though I do use Open Selection) because neither BBEdit nor Xcode offers auto-completion of the filename. Instead, I use LaunchBar, and I have sub-searches setup for each project that I work on. Or, if the file is already open, I use Command-Control-F to open the file pop-up menu and then type-select a file. Plus Control-Tab to switch between counterparts, of course. I also have Command-Control-B bound to a script that opens the current file in a BBEdit disk browser.

Managing Files: flat folder on disk

I go with multiple frameworks, each with a flat list of files.

(More comments from Daniel Jalkut and Jonathan Rentzsch.)