Category Archives: Development

A Real Gatekeeper


In the years since Apple released the iPhone, with its “locked-down-by-nature” approach to application security, the company has progressively chipped away at the freedoms Mac developers have historically had to do, more or less, whatever the heck they wanted.

With the introduction of the Mac Application Sandbox in 2012, Apple applied an iOS-like mechanism through which applications are entitled only to access their own data, and must explicitly request permission from Apple to access any resources “outside of their own sandbox.” At the time, I wrote that while the technology was promising, it left much to be desired.

Around the same time, they introduced Developer ID, a system for certifying at runtime that a given piece of software has been cryptographically signed by a developer whose identity is known to Apple. Applications that are not signed with Developer ID are allowed to run in macOS, but by default are met with a foreboding warning about the safety of doing so. The component of macOS that is responsible for limiting the launch of software from unknown developers is called “Gatekeeper.”

Last year, in 2018, Apple introduced a new notarization service, an expansion of Developer ID functionality. Developers submit their applications to Apple, where they are scanned for known malware, and have their use of specific system technologies vetted. The “notarization” on an app allows the system to verify at runtime that a given application passes a baseline safety metric for downloaded software.

Finally, in 2019, Apple announced that software signed with Developer ID certificates, that is to say all non-Mac App Store software, must also be notarized. The Catalina 10.15 public beta identifies software that has not been notarized as potentially risky because it “cannot be scanned for malware.”

In effect: developers who ship software directly to end-users are now required to notarize their apps.

While working on the notarization process for my own apps, and a company I work for, I noticed an interesting error from “altool”, the command line program that is used to submit binaries to Apple for verification:

1 package(s) were not uploaded because they had problems:
Error Messages:
To use this application, you must first sign in to 
iTunes Connect and sign the relevant contracts. (1048)

The error is easily worked around by logging in to App Store Connect and agreeing to any updates Apple has recently made to their contracts. I’m so used to more-or-less blindly agreeing to these changes, that it didn’t sink in for me at first what a potentially major change this is.

My colleague Patrick Machielse noticed right away what the larger implication is: all Mac software, inside or outside of the Mac App Store, can now be held up by unsigned contract agreements with Apple. In a rush to fix a horrible bug and get it out to customers? Better review that new contract ASAP.

For the past 35 years, any Mac developer who wanted to ship an update directly to customers could do so by recompiling a binary and distributing it. When macOS 10.15 ships this fall, the status quo will change. Mac developers must register with Apple and sign their products. They must submit their binaries to Apple for notarization. And most significantly of all, they must agree to the terms of Apple’s App Store developer contracts, even if they don’t distribute their apps through the App Store.

Saying Goodbye to NetNewsWire 3

In case you haven’t heard the news, Brent Simmons recently regained the rights to NetNewsWire, the groundbreaking Mac news reader, which also happens to be the progenitor of MarsEdit.

I have been a fan of NetNewsWire since before Brent sold it to NewsGator. Since before NewsGator sold MarsEdit to me. Before they sold NetNewsWire to Black Pixel. For a long time.

After Black Pixel took the reins, they put a lot of effort into a massive overhaul of the app, modernizing the look and feel and adding a robust, in-house syncing mechanism. When they released NetNewsWire 4 in 2015, it seemed as though the future for the app was bright.

As nice as NetNewsWire 4 was, it also differed a lot from NetNewsWire 3. They pared back the feature set a lot, in ways that made switching inconvenient to me. So I soldiered on with 3.3.2, thinking that I would update to 4.x eventually.

I never did. For whatever reason, work on NetNewsWire seemed to stall, and I never found the updated version of the app to fit my needs. NetNewsWire 3 worked just fine.

The meaning of “just fine” started to shift as macOS changed underneath the app. Subtle bugs emerged, the app’s lower-resolution graphics started to look fuzzy, and the networking infrastructure of the app is from an older era that is failing to connect to some SSL servers. In short, it’s no longer the great app that it once was. One particular bug with the size of the “Clippings” folder icon has been bugging me for years:

Screenshot of NetNewsWire showing blurry icons and a missized Clippings folder icon.

Over the years I considered other news readers such as Reeder (which is free for a limited time, by the way), but none of them scratched that NetNewsWire 3 itch. I rely upon some arcane features of the app including “scripted feeds,” which allow me for example to run Python scripts on my Mac that connect to Twitter and generate RSS feeds from search results. That’s not possible in most feed readers.

I used to fantasize about getting access to the NetNewsWire 3 source code and sprucing it up. I wondered how things might have turned out differently if, in addition to acquiring MarsEdit from NewsGator, I had acquired both? I can’t say I would have done a better job than Black Pixel, but I would have preserved the features I care about, and that Clippings folder icon would be the right size!

Because Brent and I are still close friends, we have been in conversation about NetNewsWire and the various options for moving it forward into the future. I’ve also been contributing to the NetNewsWire open source project, which is based on an entirely new code base unrelated to NetNewsWire 3.

Since I’m not the only stalwart NetNewsWire 3 user, one of the things Brent was curious about was whether he could give that version “one last hurrah,” so to speak. Fix a few of the most glaring bugs, build against a modern SDK, and not only create an artifact for history to more accurately judge the app’s virtues, but to give long-standing users something to tide them over while development continues on NetNewsWire 5.

I was honored when Brent handed me the keys to the castle, so to speak, by sending me a copy of NetNewsWire 3’s source code. To heavily paraphrase what he said, it was basically “let me know if it’s worth saving.”

I got the app building with Xcode 10 on macOS Mojave beta 9. There were some major glitches. The sidebar was pure black, fonts were rendering wrong. Probably whole subsets of functionality were not working, or working unreliably. I sent the source base back to him with a report that it builds and runs, but would probably take some work to get into shippable shape.

Brent made the pragmatic choice not to release an updated NetNewsWire 3. Putting the bugs aside, he recognized that any time invested in that old version is an investment in older technology that does not have a viable future. It’s a distraction from the New World NetNewsWire.

To be honest, the decision doesn’t sting at all. I’ve switched most of my news reading to development releases of NetNewsWire 5, and only use NetNewsWire 3 for a handful of those geeky script-based RSS feeds I am still relying on.

I was grateful to have the opportunity after all these years to take a peek at the source code to the app, and to get a feel for what it would take to salvage what’s left. I couldn’t resist fixing at least one bug before I passed it along though:

Screenshot of the NetNewsWire window with Clippings folder icon restored to normal size

If you’re curious: the Clippings icon is obtained from the Mac operating system. At one point in history it must have come from the system at just the perfect size to fit the source list in the app, but as Apple modernized and adapted to higher resolution Macs, they must have updated the icon to support drawing at much larger sizes. NetNewsWire 3.3.2 doesn’t manually set the size to the expected 16x16pt size, but 3.3.3j (for Jalkut!) does.

Goodbye, NetNewsWire 3. You were a great app, but your time has passed. Long live NetNewsWire 5.

More on Mojave’s Automation Sandbox

I wrote last month about macOS Mojave’s restrictions on automation, and how users can reset the database that controls them. In that post, I cited Felix Schwarz’s excellent article on the subject.

In recent weeks, Apple has made changes to the behavior of macOS Mojave, and added some API calls to help developers better handle the restrictions of the system. Felix is back with an updated post, describing the changes, and what he thinks can still be improved.

Unified Swift Playgrounds

Usually I write about “programmer stuff” on Indie Stack, and “other tech stuff” here.

Today I had it in mind to write about my belief that Apple should get rid of Xcode Playgrounds and instead focus on adapting the iOS Swift Playgrounds app to the Mac.

I thought at first I would post it here because it’s not strictly about programming, but I ended up posting it there instead:

Unified Swift Playgrounds

May be of some interest even to folks not strictly interested in programming!

Progressive Disclosure In Swift

In his excellent interview with the Accidental Tech Podcast, Chris Lattner defended the goal of Swift being suitable to both beginner and advanced programmers. He cites progressive disclosure, a design philosophy that is often employed in GUI applications, to make otherwise intimidating interfaces appear approachable. From episode 205 of the show:

The secret to Swift in being easy to learn, easy to use as a teaching vehicle, but also powerful enough to solve the problems that need to be solved, is that the complexity in the language needs to be progressively disclosed.

This resonates particularly with me not only because I strive to make the same kinds of design tradeoffs in my own software, but because this concept is particularly important to the history of the Macintosh. Progressive disclosure as a user accommodation is intrinsic to most Mac and iOS interface design.

An example that anybody who uses a Mac can relate to is the process of deleting files by way of the Trash. There’s a file on your Desktop, and you want to get rid of it. A naive user who has never used a Mac before will soon learn how to drag the icon onto the trash, and how to empty it through a variety of discoverable UI buttons and menus. This is the Mac, it’s easy to use.

After gaining some experience the same user might start to find all that clicking and dragging tedious, so they’ll be delighted to learn that the cryptic symbols on commonly-used menu items represent keyboard shortcuts. To throw away a file and empty the trash, just select the file, press Cmd-Delete, and then Cmd-Shift-Delete. This is the Mac, it’s streamlined for productivity.

When the standard menu items and shortcuts don’t cut it anymore, the same user will be inspired by the variety of nuanced variations that are unlocked by holding the Option key while selecting menu items, and that the incorporation of the Option key into existing keyboard shortcuts often maps perfectly to the same menu item that appears when the key is held down. “Move to Trash” becomes “Delete Immediately,” and “Empty Trash…” becomes “Empty Trash”. The omission of the ellipsis, they have come to discover, indicates an action that will take place immediately, without additional interaction. This is the Mac, it’s kind of complicated, but great for power users.

Finally, finding cause to delete a variety of files from a directory selectively, based on pattern-matching, they discover the Terminal app. They teach themselves the basics of a decades old interactive shell scripting wildcard notation, and are off to the races invoking the “rm” tool with wild abandon. This is the Mac, it’s got god-awful, nasty interfaces for accomplishing just about anything.

I worked at Apple from around 1995 to 2002, so I had the pleasure of witnessing reaction both within and outside the company as we transitioned from Mac OS 9 to Mac OS X. The Terminal, as it happens, was one of the most contentious new features. Mac OS 9 had standalone command-line developer tools such as MPW (Macintosh Programmers Workshop), but it was a sort of point of pride that it didn’t ship with a Terminal app. This wasn’t DOS, for crying out loud! Many people complained that Mac OS X was too complicated, and that the inclusion of a Terminal app was the beginning of the end for the system’s famous usability.

Fifteen years later, people are still performing incredibly simple, incredibly complex tasks with macOS Sierra. It ships with a Terminal and it ships with a Trash icon. This is the Mac, it spans the spectrum from simplicity to complexity. Apple’s turns out to be pretty good at this, so they deserve the benefit of the doubt that they’ll achieve the same type of goal with Swift. It seems like they’re off to a good start.

Log Littering

Apple has dramatically revamped its standard logging mechanism. Unified Logging, available in macOS 10.12 and iOS 10, replaces various file-based logging approaches with a centralized, database-backed repository for log information of all levels of interest.

The big win, both for developers and for users, is performance. Where the simple act of logging some debugging information used to have enough of a cost to dissuade rampant use, the new system makes it so cheap that developers inside Apple and out are being encouraged to “log like the dickens” in the name of generating more evidence for posthumous debugging. The new system also offer impressive data mining abilities, making it far easier to filter for what you’re looking for and to track logging information across specific activities, even if the activity spans multiple processes.

The two big losses, in my opinion, are that the sheer size, number, and variety of logging messages makes it impractical for users to skim the console for “real problems,” and that the resulting logging archives are so large that it’s impractical to casually include them with bug reports to Apple or 3rd party developers.

The WWDC session on the topic goes into detail on these points, but perhaps most useful for framing my complaints here are Apple’s stated goals for the revamp:

  • One common, efficient logging mechanism for both user and kernel mode
  • Maximize information collected while minimizing observer effect [the phenomenon that enabling or adding logging changes the behavior of the system you are trying to understand]
  • We want as much logging on all the time as possible
  • Design privacy into the system

Two of the stated goals, “maximizing information collection,” and “as much logging on all the time as possible,” exacerbate the problems of there being so much log data that it’s both difficult to skim, and cumbersome to share.

Imagine a society in which all packaging has been transformed into fast-composting, biodegradable materials. Your soda bottles, snack wrappers, cigarette packages, etc., all biodegrade to dirt within 48 hours of use. What a boon for the world: the major, global problem of trash accumulating in our towns and environment would be gone. Poof!

Or would it? When “littering has no cost,” I suspect that we’d face a new problem: far more people would litter. Why bother finding a place to throw out that bottle, when nature will take care of it in within 48 hours? Multiply this attitude out over even a small portion of the world’s billions of people, and we’d be guaranteed to be buried in trash. All trash that will be gone in 48 hours, mind you, but constantly replenished with a fresh supply.

I think this metaphor points to a similar problem with unified logging: the sudden onslaught of “low cost logging” has left our developer society unprepared in some specific ways to deal with the consequences of the new reality.

So, how can we, and Apple fix this? We need specific solutions that make skimming for problems, and sharing pertinent log data easier, yet don’t impact the very positive goals outlined by Apple above. Here is my advice:

  1. Don’t litter the logs. Just because you can log it, and just because doing so is cheap, doesn’t mean there isn’t a cost. Some of the recurring log messages littering my Console arrive at a rate of thousands per minute. There may be good arguments that certain subsystems, in certain states, should log this extensively if the resulting data will justify easier diagnosis of problems, but much of the junk I see are redundant reiterations of relatively useless information:
Not switching as we're not in ~/Library/Keychains...
...
CSSM Exception:...
...
Etc. Etc. Etc.

Some of these seem to be well and truly noise, but some of them, even if they seem highly redundant and noisy to me, could in fact represent useful logging if you happened to, for example, be tracking down a subtle bug in Apple’s security libraries. That’s fine, I’ll accept that some amount of log diarrhea in the name of better software, but only if the following accommodation is made…

  • Annotate high-frequency logs for easier filtering. The logging system offers a variety of tools for annotating log messages, but even internal Apple groups do not seem to use these extensively or appropriately. The system supports the notion of three levels of log message: default, info, and debug. Only the “default” level messages are displayed by default in the Console app, yet all of the above-described garbage is displayed in that default mode. The Console will become significantly more useful when the worst offenders have marked their messages for severity, subsystem, and category so that they can be effectively omitted from the default view, and so that they can be mined later for use by folks who can actually make sense of them.

  • Generate context-specific sysdiagnoses. One of the worst practical outcomes of unified logging is that capturing a “sysdiagnose” on my Mac now generates a compressed archive that is still larger than 400MB. These archives are typically requested by most groups at Apple in response to bug reports, regardless of how severe the bug is or how readily reproducable it appears to be. In the world of Apple bug reports, sysdiagnoses are treated like lightweight bits of information that should be appended to every issue, except they’re now anything but lightweight.

    All the annotation work advised above should really pay off when Apple provides a streamlined mechanism for capturing sysdiagnose information pertinent to a specific subsystem or product. The company already offers product-specific advice for capturing log information, sometimes requiring the installation of custom profiles and other shenanigans. The lightweight unified logging system empowers Apple to both require that internal groups properly annotate their log messages and to facilitate smarter gathering of that data.

    Currently if you want to capture a sysdiagnose at any time a Mac, you simply press Ctrl-Opt-Cmd-Shift-Period. On an iOS device it’s done by holding both volume keys and the power key, but you have to enable logging first with a custom profile. This shortcut will generate one of those mondo 400MB style sysdiagnose archives, which you can upload to attach to your bug reports in your copious spare time.

    I envision a prompt that appears after invoking the existing shortcut, or else a new shortcut for “interactive sysdiagnose” where you could specify the category of bug you are reporting. The prompt would list categories correlating to groups at Apple who had done the work of providing streamlined log filtering data that will effectively strip out all the useless (to that group) noise from your log data.

    In fact, sysdiagnose already takes a “process” parameter when invoked from the command line, and my understanding is that this enables it to capture data that is pertinent to the target process. The unified logging system seems to provide the infrastructure for even smarter capturing along these lines.

    I realize that in this time of flux, where much log data is not properly annotated, there is still an incentive for many groups to capture as much as possible and sort it out on Apple’s end. These groups should know, however, that the larger the sysdiagnose archive you ask users to upload, the lower the chances they will bother actually following through on filing the bug or on providing the pertinent information you have requested.

  • Annotate specifically for user-concerning issues. Power users on the Mac have, for years, counted on being able to skim the console log for information that might explain a slow Mac, persistent crashes, or other inexplicable behavior. Given the huge increase in number of log message and the lackluster annotation of these messages by Apple, the Console app is effectively useless to users for this purpose.

    On top of getting the annotation right in general, I think a new special level of log message should be created, indicating particular concern to end-users. These would identify log messages that developers specifically think users should take notice of and follow up about. I mentioned there are three basic levels of log message: default, info, and debug. On top of that, there are two special levels called “fault” and “error”, which can be filtered on in the Console, and which receive special treatment from the logging system.

    These special levels seem close to what users might find interest in, but they’re not quite right either.

    A “user interest” level of logging message would facilitate the kind of high level skimming that seems impossible in Sierra today. These log messages would convey information that a user might gain some insight from. They would stand in stark contrast to the noise of messages like these, from the filecoordinationd process:

    Claim D32EDEBE-C702-4638-800C-E4BAB9B767F3 granted in server

    Nobody knows what a claim is, or cares whether it was “granted in server” … unless they are actively debugging filecoordinationd. On the other hand, a message indicating the failure to grant a claim “because the disk is full,” could be very useful to users indeed.

    I realize the line could be difficult to draw in some circumstances, but a huge number of messages currently being logged are obviously not of user interest. Perhaps then, the opposite approach could be taken, and log messages could be annotated as being specifically useful for posthumous, internal debugging by developers.

I tell you, things are bleak. We’re swimming in a morass of useless console noise, and there is little we can do about it. There is room for optimism however, as the logging infrastructure is good, and seems to support many thoughtful measures that could attenuate the problems and make the system more useful and less cumbersome to developers, end-users, and well-meaning bug reporters.

The console is littered with trash. Sure, it will biodegrade in 48 hours, but that doesn’t mean we shouldn’t be concerned with cleaning it up. A combination of more thoughtful logging, proper annotation, and appropriate filtering will get us out of this mess.

Six In One

Craig Hockenberry’s “Half-Assed” calls out the disparity between Apple’s Mac and iOS App Stores with respect to app analytics, limiting customer reviews from beta OS releases, and support for beta testing with TestFlight:

Mac developers have never had access to TestFlight, either internally or externally. It’s “coming soon”, and until that day comes, there’s no way to test apps that use the iCloud servers. Which sucks for both the developer and the customer.

For years, I’ve harbored my own resentments about the way Apple seems to treat the Mac App Store as a second-class citizen. One point that has nagged at me since the Mac App Store launched five years ago is the lack of effort Apple makes in promoting these products through social networks. For years, the @AppStore account has been extremely active promoting iOS apps to its huge (now 3.8 Million people!) audience. It’s obviously a priority for Apple to promote the iOS App Store, and their Twitter account does a great job of it.

But there is no Twitter account for the Mac App Store, and the @AppStore account has nearly never mentioned Mac software. (Go ahead, do an advanced Twitter search for “from:AppStore mac“). Around four years ago at WWDC, I asked a group of App Store affiliated engineers what they made of this. They all looked at me blankly, paused, looked at each other blankly, paused, and then shrugged as if to say “Huh, I wonder why we don’t promote the Mac App Store?” I don’t know either! But they were all in a much better position than I to find out or push for a change. Evidently, that hasn’t happened.

The neglect makes sense on one hand: iOS and now watchOS are the new hotness, the platforms that represent the fastest and most culturally significant growth for Apple. They sell the most devices, generate the most revenue, and create the biggest headlines, worldwide. It still makes sense for Apple to prioritize the iOS App Store, but it’s a shame they haven’t done more over the past five years to integrate the systems that power the stores so that benefits to developers for one platform’s store would automatically benefit the developers for the other.

On the other hand, let’s acknowledge that the disparity is not all roses for iOS and weeds for the Mac. iOS developers continue to face obstacles for which we have long enjoyed simple solutions for on the Mac. As Craig points out, we can’t ship a useful beta testing app that fully exercises all of Apple’s locked down services such as iCloud, but what can we do? We can ship arbitrary binaries to an unlimited number of people, who can install and run those apps on whatever devices they choose. How do you like them, ahem, Apples?

And what about the absurd steps iOS developers must take in order to stay up to date with beta releases of the OS? Either they commit themselves to running guaranteed buggy and possibly unusable versions of the OS on their machine “machines,” or else they spend extra money on devices whose only purpose will be to act as testbeds for the risky new OS. Want to maintain backwards compatibility? Better keep multiple iPhones, iPod touches, and iPads, of varying generations handy, but be careful not to update them to a newer OS, as there’s no going back.

On the Mac, we enjoy the ability to erase and reinstall whatever version of the OS we choose, whenever we choose. Furthermore, we can maintain parallel installations of the same or different versions of the OS, on easily switchable partitions of the same disk. Even in the context of a single OS install, we enjoy the ability to test varying user scenarios by configuring test accounts and “Fast-User Switching” between them from the comfort of our Mac’s menu bar. Heck, we can even virtualize whole Macs thanks to VMware, Parallels and VirtualBox. When it comes to testing various configurations affordably and expeditiously, it’s the iOS developers who should be crying to Apple that their priorities are skewed.

I guess it’s lucky the Mac was around for so many years before the dawn of iOS, it’s had time to accumulate many developer-empowering features. Although Apple’s priorities with respect to development resources and marketing seem to be focused on iOS today, we enjoy many privileges on the Mac that I doubt iOS developers will ever see. And to top this off with a bit of true optimism for the future: the weird thing is, Apple keeps improving OS X. I’m sometimes surprised by the amount of attention Apple continues to give to the OS given its apparent relative lack of importance. But I guess Apple is well and truly stocked with a bunch of Mac softies, after all.

There’s a ton of totally vexing behavior that seems to be ill-spirited towards Mac developers, but also a ton that seems to hold iOS developers in low regard. I think this speaks to the likely truth that Apple is, more than anything, under-staffed and not well situated to deploy solutions to both platforms in tandem. It truly is a case of six in one, a half-dozen in the other. But wouldn’t it be great if iOS and Mac developers could each enjoy the benefits of all twelve? I’ll hold out hope that one day Apple will unlock the secret of organizing their efforts so that developers on all their platforms can benefit more or less equally from the technologies the company provides.

First Impressions

I recently bought my first TiVo (the baseline Roamio), and was excited to get it up and running so I could start collecting shows. I started the process last night and only finished this morning, after investing about 3 hours of my time. Granted, it didn’t help that I forgot to plug the coaxial cable in when I first turned on the machine, but everything that happened after that was a bona fide shit-show, from the cryptic error feedback of the device, to the hit-or-miss activation of the cable card, to the dreadfully long support call with Verizon.

Knee-deep in the trouble, I kept second-guessing my expectation that TiVo would actually turn out to be of value to me. Why was I investing hundreds of dollars into a product that treats me like a grade-A jerk from the start? Ardent fans of TiVo assure me that once it’s setup it truly is a better experience than most of the clumsy cable-company DVR boxes provide, but my confidence was eroded by a “first launch” experience that seemed hostile in every respect. I tweeted:

But as I’m also trying to turn over a new leaf with respect to blogging, I also added a note to my TODO list:

  • ▢ Blog about “the first launch”

The idea being, I bet I have plenty to say on this topic and I should sit down with MarsEdit and write about it! Great idea, except … I already did that six years ago. From the Red Sweater Blog’s Designing for the First Launch:

Every product has shortcomings that will cause some users to run away screaming. The best we can do is try, with each iteration, to make fewer and fewer people do so. If 100 people download your product, and 90 of them run away screaming after launching it once, then you’ve only got a chance of selling to 10 of them. We can assume that statistically, some fixed percentage of the people who remain will end up buying. So cut the flee factor down to 80 and you’ve just doubled your sales.

And my post was itself a response to Brent Simmons’s On the Design of the First-Run Assistant:

Present as little friction as possible—don’t overwhelm the new user so that he quits without trying the app. Ask for just the minimum required to make an account: username and password.

Given that I barely remember reading this, and barely remember responding to it, how likely is it that I’ve followed this sage advice over the past six years? Looking back at how MarsEdit treated new users then, compared with how it treats them now, I have definitely made some improvements, but these have come in fits and starts. There were long lulls during which I just took it for granted that the current “onboarding” experience was good enough, and focused on features that, unfortunately, will only be appreciated by users who don’t run away screaming.

My experience with TiVo, and review of these old blog posts, reminds me that good enough almost never is, and that the single most important feature of any app is keeping new users engaged long enough to appreciate the rest of them.

File A Bug

My friend Marco Arment laments that of the 15 bugs he’s filed since 2009, eight have been marked as duplicates, and seven have received no significant response.

Since 2009, I’ve reported 161 bugs. It’s much harder for me to do a stone-cold analysis of the results of my efforts. Yes, I’ve “wasted some time,” but often in the process of doing so I have also gained a deeper understanding of the problems I was reporting.

Having filed 161 bugs over six years, I can guarantee you that I’ve had far more bugs ignored or filed as duplicate than Marco has. I’ve had my share of bugs for which I’ve had to send back a sternly worded note to the bug screeners, implying in as polite a language as I could muster that they were not doing their jobs well.

I’ve also burdened Apple with a good number of false alarms: bug reports that I filed hastily only to discover were actually my own problem. Sometimes these were reported with confident, dismissive words that I later felt like eating. Sometimes I am not a great bug reporter.

And sometimes I am a great bug reporter. I’ve received notes of personal thanks on Twitter, via email, and in person at conferences such as WWDC. Engineers at Apple have said things such as “I wish all bug reports were as good as yours,” and “your bug report spelled out exactly how to fix the bug, so that’s exactly what we did.” I can’t remember a major OS X release when at least one of my reported bugs was not addressed during the beta release period, before the software ever saw the light of day. If we stretch the timeline back to 2008, I’ve even had the unexpected honor of being credited in a security update for what I thought was a simple networking bug.

I’ve had my share of frustrations with Apple’s bug reporting system, but I’m a developer. I can take it. I’m used to rejection. 9 times out of 10 when we developers press Cmd-R in Xcode to “Build and Run” our projects, they don’t even make it past the compile phase. But we keep trying. Why? Because we know how great it feels when we finally get something to work. We don’t need to be constantly reassured that we’re great, that our input matters, or that our concerns have been heard. Would it be nice? Sure. But so would Objective-C namespaces and a pony.

If we developers want Apple’s platforms to work as well as they can, the sad and short truth of the matter is we have to report bugs. If you’ve only reported 15 bugs over 6 years, as Marco has, I’m afraid to say that you haven’t done enough. To stand a statistical chance of either helping the cause or of being gratified by a personalized response, you’ll have to step it up, grin and bear the frustration and continue to press “Build and Run” on the Apple Bug Reporter and see what comes out the other end.

Stagnation Or Stability?

Michael Lopp is moving on from Things, a popular to-do management app.

That’s an understatement. The title of the post is “R.I.P. Things,” and he wastes no time explaining that he is “throwing away” the app. This sounds juicy. What could have him so riled up?

How can I trust that I’m using the state of the art in productivity systems when I’m using an application that took over two years to land sync I could easily use? What other innovations are they struggling to land in the application? Why hasn’t the artwork changed in forever? What is that smell? That smell is stagnation.

The nut of Lopp’s rationale for tossing Things to the curb is the relatively slow pace of its development over the years. Delays in delivering long-desired features, namely sync, made him conclude that the software will not evolve in ways that suit his needs moving forward. He’s not giving up on Things because of specific shortcomings, but because of anticipated shortcomings and a loss of confidence in the developers of the app.

This line of reasoning gets my hackles up in part because I’m a cautious, deliberate developer. I tend to add features, rework user interfaces, and adopt new platforms at a pace that frustrates even my most loyal customers. I’m slow, but I’m good! When Lopp attacks Cultured Code, the makers of Things, and questions their core competence, I feel that I am being attacked as well.

But what really frustrates me in this case is the software has served him perfectly, and he thanks it with a slap to the face. It’s one thing to denigrate a product for failing to meet your expectations, or for exhibiting a clear lack of craftsmanship, but Lopp admits that those problems do not apply:

Part of me has been fine with this lack of change because I don’t need my productivity system to do much more than capture a task, allow me to easily categorize and prioritize tasks, make it easy to search and filter them, and do all this work frictionlessly. “Things does these things well,” I thought to myself, “I don’t need anything else.”

He applauds the app for allowing him to do his work “frictionlessly.” How does a software developer achieve this level of performance? By first building a quality product and then working deliberately over months and years to address the minor issues that remain. Woodworking makes a reasonable analogy: after a chair has been carved and assembled the job is functionally complete. It’s a chair, you can sit in it. It’s done. But customers will gripe with good cause about its crudeness unless the hard work of detailing, sanding, and lacquering are carried out. Only then will it be considered finely crafted.

As a seasoned software manager, I know Lopp appreciates how hard it is to achieve the stability Things has provided for him. But as a user, he’s as excited as any of us to see new, fresh designs. As an onlooker, it’s easy to associate dramatic change and motion with competence, and quiet refinement with laziness. We must draw on our own experiences attempting to build great things to appreciate how much work takes place in stillness, to have faith that even though things may appear stagnant, a benefit of frictionlessness is resulting. An app at rest may be in that long, arduous phase of becoming finely crafted.

There is a time for dramatic change as well, but it comes with costs. If after years of careful refinement a product is found to be lacking in some important way, bring out the hatchets. Chop it all to bits and rebuild from scratch. The possibilities of positive change in major reworks are exhilarating as a developer, and tantalizing to customers. But every reworked component of a product also resets that process of refinement.

Software should be criticized. Even apps that consistently wow me with their intuitiveness and polish leave me scratching my head about perplexing, nuanced failures. But criticize an app for its failure to do something important, not for an unspecific failure to change in general.

I’ve whined about stagnation, too. I waited years for an update to Keynote and over time, become more and more grumpy about the lack of change. The fact that it’s just about the best application I’ve ever used slowly lost sway in my judgement of the software and, by association, the team of developers who build it.

The next time I’m tempted to think harshly of a developer working at a slower pace than I’d like, I’ll try to step back and appreciate that I care enough about their software to be concerned. And more importantly to appreciate that they care about their software too. So much that they work slowly, deliberately, painstakingly in the pursuit of a frictionless experience for myself and other users.

The Imperfect Craft

For much of my career I viewed software development as a craft: a constructive endeavor with fixed standards of excellence. I thought that over a lifetime, I could assiduously refine my skills, inching toward some level of subjective mastery until eventually myself and others would agree that I had become “a real expert.”

Unfortunately it doesn’t work that way with software. The technological context in which software is developed and used changes constantly and dramatically. So most of the stringent guidelines we impose upon ourselves in the name of craftsmanship are at risk of being obsoleted by some new advance in hardware, in programming languages, or in the baseline services of the operating systems we develop for.

Ask yourself, or a software developer of a certain age: what were the guidelines for crafting excellent software 5 years ago? 10 years ago? 20 years ago? The farther back one goes, the less relevant the answers will be to our modern craft. Memory management? Not a significant issue for most programmers today. Multitasking? Obliterated by modern operating systems with efficient context switches. Concurrent programming? Constantly reinvented in the wake of multi-core CPUs, GPUs, and higher-level programming language features.

I have spent a lot of my professional life honing “the skills of programming.” That is, the set of skills that seemed important at the start of my career. But I’ve seen what happens to people who cling to outdated standards of craftsmanship: they become self-righteous, bitter, and delusional. Guided only by the hallowed rules of yesteryear’s geniuses, they and their work become marginalized. Without a foothold in the modern technological context, programmers who should be great are rendered effectively incapable of developing their craft.

I’m sure this problem is not limited to software development, but given the world’s obsession with computers and related technology, the software landscape is changing much faster than many of us can easily keep up with. The world demands that this craft change. The technology for sculpting, firing, and glazing a ceramic bowl has also changed over the years, but not at the same mind-boggling rate as prototyping, programming, and testing a software application has.

What if you happen to enjoy old-school programming? There’s nothing inherently wrong with crafting “retro software.” In fact, I’m sure that dabbling in outdated techniques will serve to round out a modern programmer’s abilities. But while a classics scholar may be intrigued or even obsessed with ancient Greek or Latin, she knows that in order to remain relevant she must publish her papers in modern English. And if Esperanto were to become the lingua franca for her craft, that is the language she would have to use.

In software, the lingua franca is changing all the time, whether by adoption of new programming languages, through nuanced idiomatic changes in the ways that we use languages, or because of evolving operating-system level facilities. We don’t have the luxury of assuming that the tools and techniques of our parents, or even our younger selves, are sufficient to move the profession forward.

As a modern software developer, I derive as much joy from remaining relevant as I do from the thrill of identifying and solving the particular problems in my work. To remain relevant, I have to reject my previous assumption that I would spend a lifetime refining my craft. Instead, I will spend a lifetime adapting the techniques of yesterday’s craft to the sometimes radically different challenges of today. I may never become “a real expert,” as I hoped I might be. But by diligently throwing out the old rules and embracing the new ones, I hope to come close.