Mac app checklist

2007-03-18 02:11:53 UTC

A list of things that you must do for every app. Most of these should be done up front; some can be put off a little bit; some can be put off a long time, but ought to be done at some point rather than put off into the indefinite future.

Also available in TaskPaper format, in case you’re a TaskPaper user.

  1. Version control is mandatory. I recommend Subversion (which is free and open-source). The advantage of version-control is time travel: You can easily go back to any previous version of your code, or even certain files. This lets you delete with confidence. Be sure to follow the trunk+branches+tags layout for your repository; you can create branches for experimentation and tags for released versions. Both these operations are cheap in Subversion. The easy way to install Subversion is to use Martin Ott’s Subversion Installer package.

  2. Resolution independence. In particular, shun raster images (except for your Finder icons). Use vector graphics, either created in an app like Lineform or written in PostScript or Cocoa.

  3. Contextual menus. Much like AS support (listed below), effective contextual-menu support is a great way to make your app more efficient for its power users. In IB, create a top-level menu by dragging it from the palette into your nib, then ctrl-dragging from the view to the top-level menu and connecting to the menu outlet. If you create your views programmatically, you’ll need to override -menu (either returning a programmatically-created menu, or adding support for a -setMenu: method that you provide).

  4. Localize everything. Localize every string you show to the user, even if it’s only in English for now. If your app achieves any popularity (and you should hope it does), people will volunteer to localize it into their preferred language. If you use NSLocalizedString on every hard-coded string as you write it, your localizers will be able to localize your entire app, without having to ask you for app-side support because it will already be there.

  5. Maintain a bug- and feature-tracking system. Ideally, something like a locally-hosted Trac (don’t open it to the users, or you will be fighting lots of duplicates), but even a simple OmniOutliner or Opal document will save you having to remember all those things you need to fix/add.

    Its benefits aren’t as immediate as version-control: Version-control pays off the moment you want to bring back something you deleted, whereas a bug-tracker pays off months down the road, when you’re trying to remember what that last feature you wanted for 1.0 was, or what that one guy reported with the bug that only happened when he clicked on one of the windows with his left hand. But it’s the same kind of time-saver.

  6. Sell your shares in __MyCompanyName__. Especially important for open-source projects, since other people will be reading your code. Do this now, so you don’t need to do it after you create the project.

  7. Burninate NewApplication. The template nibs (including those in a new project) use “NewApplication” throughout the menus, where your application name is supposed to go. Make sure you replace “NewApplication” with your actual application name. (Even better, use Daniel Jalkut’s app template instead of Apple’s.) Take it from me, it’s embarrassing to ship an app whose menus still use the name “NewApplication”. ☺

  8. Thoroughly test everything in the stock menus. Especially the application menu (edit: used to say ; thanks Jesper) and Help menu. Services should work in any text view or text field, and ideally should work in any view that has data that your users may want to run a Service over. The Preferences menu item should be hooked up or deleted. Same for “Application Name Help”.

  9. Edit the credits. (No pun intended.) These are stored in the “Credits” file in Contents/Resources. The default Credits file is an RTF file; TN2179 says that the About panel looks for Credits.{html,rtf,rtfd}, in that order.

  10. An application icon. If you can’t draw a good icon, hire someone to draw one for you. (If yours is an open-source project and it becomes popular, somebody may volunteer.)

  11. Document icons. (For doc-based apps only, obviously.) One document icon for each document type you can write out, with different classes of type (e.g. movie vs. audio vs. text) being depicted in significantly different ways (e.g. QuickTime Player’s icons having sprocket-holes for video files vs. a waveform for audio files).

  12. Pick a creator code and register it. This still matters, especially for associating a specific document file with your app. (Say you’re writing a multi-track video editing app—please—and you want to have movie files that you save be owned by your app rather than QTP. That’s what a creator code is for.) Your creator code goes in the Properties tab of Target Info in Xcode. Keep in mind that creator codes are limited to MacRoman characters.

  13. Make sure your bundle ID, version, short version, and Get Info string are correct.

    • Your bundle ID should be something unique to you, and should use your domain—not Apple’s, not anyone else’s, yours. If you don’t have one, make one up. Be sure to use the domain that you’ll eventually actually own; when you finally register that domain (even if you don’t do it for years, but you should do it as soon as you can, IMO), you won’t have to change all your bundle IDs.
    • Dave Dribin discusses what to put in CFBundleVersion.
    • The short version string is the version that appears in Finder’s List View; it should be a simple major.minor.maint version-number string (e.g., 1.0), and nothing else.
    • For Get Info strings, include a copyright statement and your version—for awhile, Apple said to leave out the version, but they’ve since reverted that, as users (well, at least former Mac OS users like me) expect to see a version number there. The version number you have here should be the same one you have in the short version string.
  14. Run it with no prefs. The goal here is to see how your app looks and works the very first time it is run. In particular, anything fed by NSUserDefaultsController needs to handle nil values correctly if you didn’t put some default values into it in main.

  15. Do at least one private beta or release-candidate. This is your final attempt to discover any bugs that you haven’t found yourself. Maybe it’s a byte-order bug, or something that only happens in certain network situations, or a crash that doesn’t happen on your machine because xyz. Regardless, you’ll find the bug only when somebody else runs your program, and hopefully you’ll do that in a private beta or release-candidate phase rather than in your actual public release. (You’re welcome to do a public beta as well, but don’t stall—get to release quickly.)

  16. Include a license and a ReadMe. For open-source projects, picking a license is easy: Use new-BSD, MIT, LGPL, or GPL. I don’t know what you would do for a closed-source project—I suggest consulting an intellectual-property lawyer. And definitely include a ReadMe. Your ReadMe should cover the following points:

    • What does the app do? (This is in case it was delivered on a CD or other compilation. In that case, they didn’t read the description on your webpage.)
    • How would I use the app in its most basic operation?
    • Who owns this app? (Copyright statement.)
    • Where can I get a newer version of this app? (Link to your website for the product.)

    Also, if you present your ReadMe as an RTF file, make sure you choose “Prevent Editing” from TextEdit’s Format menu, so that your ReadMe file is read-only. This prevents your users from accidentally deleting important swaths of the file.

  17. Maintain a detailed version history. Include the version number, release date, and list of changes. Version control will help you here: It’s tedious, but not hard, to build a complete list of changes from an svn log. The version history should be on a page of your website.

  18. AppleScript support. This isn’t something you need right away, but it’s a definite plus, especially if you’ll be selling your app. Daniel Jalkut has good info on adding AppleScript support. Even just being able to script the preferences is a good start.

  19. Check for leaks. The leaks(1) utility will scan your app’s heap looking for memory that isn’t pointed-to anymore. It’s very easy to leak objects, especially when your autorelease-fu is not strong. Be sure to use MallocStackLogging, so you can see what allocated the leaked memory; this may give you a hint as to where the leak lies. You may also find heap(1) useful.

  20. Get a real website. No, your GeoCities website won’t cut it. Expect lots of traffic, and be on a server that can handle it. No such server is free. (Also, don’t host it yourself—most ISPs won’t allow you to run a server on a consumer account, you don’t have the bandwidth anyway, and professional hosting is cheaper than an ISP server-grade account.) I recommend TextDrive, though others[1] [2] [3] have their own recommendations.

Feel free to suggest more items in the comments.

UPDATE 2007-04-02 15:15 PDT: The old #5 was controversial, and I concede that it’s too early to give that advice yet. I’ve replaced it with one that I posted in a comment. For posterity, here’s the old #5:

Test on both architectures. If you can’t do this, make your app Intel-only. Testers with ICBMs are easy to come by. Testers with PowerPC Macs aren’t so much, and they get harder to find every day. So if you have only a PowerPC, you can recruit somebody with an ICBM to test your UB, but if you have only an ICBM, it’s easiest to just make it Intel-only.

UPDATE 2007-04-02 20:17 PDT: Added a link to Martin Ott’s Subversion Installer package.

UPDATE 2007-07-23 20:15 PDT: Added discussion of the short version string to point #13.

UPDATE 2007-07-23 20:27 PDT: Formatted point #13 and clarified its discussion of Get Info strings.

UPDATE 2007-08-06 04:30 PDT: Added links to OmniOutliner and Opal.

UPDATE 2007-08-08 17:15 PDT: Added TaskPaper version.

UPDATE 2007-08-08 21:51 PDT: Added suggestion to Prevent Editing on your ReadMe.rtf file.

14 Responses to “Mac app checklist”

  1. Jesper Says:

    By the  in 8, I suppose you mean the App (bolded) menu, not the Apple menu, since none of the items in the Apple menu, except Shift+Force Quit, apply to the current application, and since you can’t change *any* of them within MainMenu.nib.

    To add to 4: make sure you only ever read data structures that contains strings or locale-sensitive information from a plist, and not from inside the app itself. Not only does this make it easier for you (or users) to change something, it also makes them automatically localizable without needing to change the app. In my Monocle app, I’ll be providing default search engines from localized plists, and so if I have translations for Japanese, French and Swedish users, they’ll also get different base search engines. (Another lesson: Localization is *not* just about translation. It’s about adopting to customs – date and time and currency format, text layouts and so on.)

    I’ll throw in extra tips that have more to do with the user/customer side of the story:

    Have big ears: Listen to all feedback. Realize that people aren’t trying to beat your app up when they’re being negative, and that an app that’s *just right* for a selection of people will make those people happier than an app that takes a swiss-army-knife approach solely in order to please the critics.

    Say no: Make your users work hard to win you over. Don’t implement every feature that’s requested of you unless it fills a gap in your application without changing its intended goal. Think long and hard about adding features that’ll extend your app’s intended goal or even add a second goal.

    Be swift: Do not pile up customer requests. Answer them right now. Even if you don’t know the answer, let them know you’re listening and that you’ll be looking into it. Allow for a maximum of 5 to 15 minutes of research, depending on how much mail you get. If the fix is a quick fix on the current release, send a special build and ask “does this fix the problem? could this be done in a better way? is this what you had in mind?”.

    Follow up: This goes hand in hand with the previous tip. Follow up, follow up, follow up. Did that work for them? Have they seen the bug since the last email? Was it properly fixed in the build that claimed to fix it?

    There are exceptions to these rules:

    If you’re a company with many, many demanding customers and a budget to uphold that are demanding a certain feature, without which they’ll go to the competition, consider supporting the feature, but be wary of what it’ll do to the perception of your app. Take Quark Xpress: it took long to get to Mac OS X and seemed bent on offering XML support (which InDesign had) instead of something that’s more like InDesign. Now they’re on their way out.

    If you’re doing consultation work, you should implement what’s asked of you and try to straighten any wrong-headed constructions. There’s room to get creative, but the room varies depending on the client. Often they’ll have exact ‘floor plans’ of what you should build and a formal process to get through; in a big enough organization (or in a small organization with few enough friends) it’s an easy step to toss the trouble-maker and get a new consultant. It’s up to you to decide whether that’s an organization you’ll want to work for.

  2. steve cooley Says:

    Holy cow, this is a great post. Big ups, dude. I don’t know if I’m ever going to get to the point of releasing ObjC-based projects, but this is a pretty amazing list you’ve compiled.

  3. David Smith Says:

    I disagree about avoiding raster images. Vector art is great for some stuff, but for certain types of images it behaves basically as a really inefficient bitmap (consider, for example, a vector representation of static). Remembering to not use lowres bitmaps is good though.

    Also I’m not sure what you mean by contextual menus. Use them? Here’s how you do them if you want them?

  4. Peter Hosey Says:

    Vector art is great for some stuff, but for certain types of images it behaves basically as a really inefficient bitmap (consider, for example, a vector representation of static).

    Hurrr?

    If you mean no-signal-on-the-TV static, I’d recommend writing a Core Image filter that takes no input and sets the pixel to a random gray value. Then your “static” image will look properly staticky at any resolution. Remember, you want each pixel to be random, not each point.

    Also I’m not sure what you mean by contextual menus. Use them? Here’s how you do them if you want them?

    Use them, and here’s how. (It’s a checklist, remember. Every list item is something to do.) Much like AS support, effective contextual-menu support is a great way to make your app more efficient for its power users.

    I think I’ll go add that to the list item, actually.

  5. Chris Hanson Says:

    No doubt one would expect me to say this, but: Unit test, unit test, unit test!

    Also, maintain a blog about your product. It’s a great way to keep your power users engaged.

    Finally, everybody working in product development should read Kathy Sierra’s “Creating Passionate Users” weblog. It’s all about helping you help your users kick ass.

  6. Peter Hosey Says:

    I have another one to add, myself: Maintain a bug- and feature-tracking system. Ideally, something like a locally-hosted Trac (don’t open it to the users, or you will be fighting lots of duplicates), but even a simple OmniOutliner or Opal document will save you having to remember all those things you need to fix/add.

    Its benefits aren’t as immediate as version-control: Version-control pays off the moment you want to bring back something you deleted, whereas a bug-tracker pays off months down the road, when you’re trying to remember what that last feature you wanted for 1.0 was, or what that one guy reported with the bug that only happened when he clicked on one of the windows with his left hand. But it’s the same kind of time-saver.

  7. Simone Manganelli Says:

    One other thing I would add: make your initial installation as easy as possible. i.e.: drag-and-drop installation, and include a background image with instructions and an Applications folder alias to make it super-simple for users to get your app on their hard drive so that it will stay there and they’re more likely to use it (especially with the good first-install impression).

  8. David Smith Says:

    “If you mean no-signal-on-the-TV static, I’d recommend writing a Core Image filter that takes no input and sets the pixel to a random gray value.” (argh, what’s wordpress’s reply syntax?)

    That’s definitely the correct way to do it, but a) the effort/reward ratio is likely very poor (and it may be impossible if your vector format is not rich enough to support things like Core Image or SVG filters), and b) my point was an example, not a specific problem to solve. If you want a harder example consider this image: http://www.infogirl.org/img/may05/forgetmenots.jpg

    In general I would consider vector art to be appropriate for many application uses (it tends to match up with graphic designer’s work like icons better than with painter’s work), but I don’t think bitmaps will be obsolete anytime soon.

  9. Peter Hosey Says:

    (argh, what’s wordpress’s reply syntax?)

    It’s XHTML, but I want to change it to Markdown at some point. Last time I tried it, Text Control was broken with that.

  10. Manton Reece Says:

    Nice list! I disagree with your explanation of number 5, though. Going Intel-only is not a good way to make a first impression. If you are at all serious about writing Mac software, find a beta tester on PowerPC or even pick up a cheap used machine for yourself. New developers to the Mac (who will get the most out of this checklist) are likely to start with a simple app that will work out of the box on both Intel and PowerPC anyway.

  11. Peter Hosey Says:

    Manton Reece: It’ll only make a bad impression on PowerPC Macs. Those are only getting fewer, and I think most Mac users who download third-party software from the internets have an Intel Mac by now. You’re already seeing this in high-end markets (look at Adobe, for example), and I think it’s going to get more common and it’s not a bad thing.

    More to the point, if all you have is an Intel Mac, and especially if all anyone you know has is an Intel Mac, then you’re not going to be able to test your app on a PowerPC. You shouldn’t distribute untested software (at least without copious “It’s beta!” warnings), so the solution there is to simply declare it Intel-only.

  12. Nat Says:

    I’d like to see any data backing up your assumption that “most Mac users who download third-party software from the internets have an Intel Mac by now”. Even if that weren’t absurd, ignoring PPC machines also shuns potential customers who have at least one machine of each architecture, which strike me as a likely plurality.

    Omni’s usage statistics, which are going to be strongly biased in favor of early adopters and of the Intel Mac customers who get Omni products preloaded, show that the crossover point wasn’t reached until late last summer. Even their PPC customer base is above 30%, and would be a black eye to ignore for years to come.

    You shouldn’t distribute untested software (at least without copious “It’s beta!” warnings), so the solution there is to simply declare it Intel-only.

    The civil solution is to spend a couple hundred bucks on a G4 from Craigslist. A big part of the reason that people like Macs is because they don’t crumble into dust after two years. Software developers who make assumptions to the contrary deserve what they get.

    Adobe notwithstanding, if you want to release an Intel-only app without a negative reaction before about 2010, your company name had better be Parallels.

  13. Peter Hosey Says:

    Nat: Data is proving me wrong on the “most Mac users who download third-party software… have a Mac by now” assertion. Not just the Omni stats, but also the Adium stats, which show Adium’s userbase at about half and half (just slightly more Intel than PPC).

    I think I’ll withdraw that point and move the bug-reporter one into its place.

  14. EmptySet Says:

    Apple is presumably releasing Leopard for Intel AND PPC. Thankfully they aren’t following your advice.

Leave a Reply

Do not delete the second sentence.