Brent Simmons has a long and thoughtful post about his way of doing large Cocoa projects. By all means read the original post and the comments. (Good reactions from Michael Tsai, Daniel Jalkut, Wolf Rentzsch, Blake Seely, I must have missed several others.)
Brent highlights some points: don’t overuse notifications, don’t overuse Key-Value Observing, bindings may be overkill for tables and outlines, C functions for global interfaces, flat source folder organization, learn tricks for fast project navigation. I agree with most. My own largest project is nowhere near’s Brent size of 345 .m files – perhaps also because I don’t mind larger files – but it’s not much simpler than NetNewsWire either. Anyway, bear in mind that my comments below just detail what works for me. YYMV and so forth.
Notifications. Everybody seems to agree they’re not a panacea. I listen to some Cocoa notifications and practically never generate my own. Notifications are great for posting notice of some application-wide event in the hope that some other parts of the application will want to know about it. That’s usually the case when some parts don’t know about other parts, or when one of the parts is a generic framework.
Like Brent, I prefer to use delegates for fast and specific notifications. Say a custom view is resized and someone needs to know when that happens; the logical pattern is to implement a delegate for that view and call it directly. Simple, fast, and easy to trace through. “Easy to trace through” is in fact my main debugging mantra. The bad thing about notifications is they’re difficult to step through in the debugger; you need to place a breakpoint at every listener. The obvious advantage over delegates is that you can have more than one listener – not that I ever needed more than one.
KVO and bindings: I haven’t had occasion yet to use those, although I’ll probably do so for preferences in XRay II. I tried using them in my first plug-in there but backed off fast; they’re certainly not suited to handling nested views that may be loaded and unloaded; the retain cycles get unmanageable. They’re also impossible to properly visualize in the current Interface Builder (though it seems that will change in Leopard?) and even harder than notifications to step through in the debugger. So I’d rather wait for a suitable application to present itself.
I suppose I also should point out that the upcoming Objective-C 2.0 properties look, so far, like another brilliant idea well-suited to specific purposes but not useable elsewhere. The property declaration syntax looks terrible, and the dot notation looks like Java. I can’t see myself using this any time soon – also, notice that the compiler will generate accessor code for them, meaning, you can’t step through.
High-level interface: in my first programs I noticed that I was jamming lots of methods into the application delegate. The app delegate is a singleton, so my other classes were full of lines like [[MyAppDelegate sharedInstance] checkSomethingWith:someStuff]. Later on I changed those to class methods like [MyAppDelegate checkSomethingWith:someStuff], and nowadays they’re just global C functions. I agree they may make it more difficult to refactor the design under certain circumstances, but after a while you learn to look ahead when deciding which functions to use. The only singleton object I have these days is the application delegate.
By the way, I use C functions a lot. Anywhere I see an instance method which doesn’t use “self” or any instance variable, it’s better to convert it into a C function. Same for most class methods. A bonus of C functions is that they’re harder to hack, of course.
Project Navigation: like Brent, I use the function popup a lot. I rarely have so many methods that sorting them into groups with #pragma mark is necessary. I use command-doubleclick and option-doubleclick a lot, and I keep AppKiDo open all the time. I noticed only recently that Xcode has a scripts menu with useful scripts and shortcuts, but the only one I use much is command-/ to comment and uncomment.
By the way, many people rave about using TextMate instead of Xcode for code editing. Apparently nearly all of those people are emacs fans who hate grabbing the mouse and prefer to do everything with memorized key shortcuts. Of course I’m an old fossil who still remembers the WordStar shortcuts and my shortcut neurons seem to be unable to learn new ones; I use the keyboard for cut, copy, paste and save, type short changes with my left hand, and for everything else I resent anything that forces me to take my right hand off the mouse. After all, that’s why we use Macs, right? </slight exaggeration for effect>
But then I suppose most of those people also like compiling their projects in the Terminal… Brent says, “Every time you touch the mouse, God kills a kitten”, but I’d say that for the command key instead
Flat folders: Yes, I too have a huge flat folder organization and 1 or 2 levels of grouping in the Xcode project. I never look at most of those files outside of Xcode anyway. I also include my readme and documentation files into the project, and edit them there (I create them in TextEdit however). Some people say this makes reusing code and source repositories harder. I prefer duplicating files or swatches of code when reusing; with some exceptions like RBSplitView, which I include as a subproject.
I seem to be notorious for not using version control systems; currently I keep my source on both my desktop and my laptop, and backup the entire project folder to a new disk image now and then. I very rarely need to refer to older versions anyway – I tend to comment out code instead of deleting it. I may try out Xcode 3’s subversion support, hopefully it won’t make me use the Terminal for anything. Of course, I’ve never worked in a programming team or had to share code with somebody else; blame it on history.
Leave a Comment