Why I Develop For The Mac
By Evan Miller
May 4, 2013
UPDATE, 5/7/2013: Some off-hand remarks in this article about HTML5 drawing speeds generated some controversy in the hackersphere. To read more, see Adrian Holovaty's post In Defense of <canvas>, and my response, Hackers and <canvas>.
Why isn't this a web application?
The second question is almost always:
Are these graphics pre-computed?
In this post I'll attempt to explain why, when it comes to desktop development, I choose to develop OS-specific applications rather than cross-platform web applications.
As a word of warning, my reasons are fairly specific to my situation and application domain, so don't take this post as a jeremiad about Why Everyone Should Renounce Web Development And Return To The Desktop. You should probably keep developing your web app, but hopefully after reading this, you'll stop wondering why I've gone native.
Try running a profiler on a native Mac application that does a fair amount of drawing. You'll see references to function calls like:
sse64? It refers of course to Intel's Streaming SIMD Extensions instruction set. In other words, Apple has carefully tuned its Quartz drawing routines to squeeze every last drop out of performance of the computers that the company ships. Browser vendors with cross-platform drawing kits just don't invest the same kind of effort into drawing lines and circles. As a result, large
<canvas> areas seem laggy on most browsers, whereas native apps “just work”. (“Are the graphics pre-computed?”)
WebGL has captured a lot of web developers' imaginations for its 3D graphics capabilities, but for my applications, 3D would mostly be a distraction. OpenGL is simply not a good option for 2D text-heavy graphics. So I'm left with
<canvas> is slow.
Then there's the garbage collector. Ah, good old unpredictable UI-freezing garbage collectors. People complain about how awful it is to manually manage memory in Objective-C, but, to turn the phrase around, with great responsibility comes great power. I can re-use hot memory for better performance, I can free memory as soon as I'm done with it, and I don't worry about users encountering strange freezes or their browser eating up all the RAM on their computer. Sure, there's a risk of introducing memory leaks with manual memory management, but Clang's static analyzer catches almost all of them.
As for my own code, my typical workflow is something like:
- Write function in Objective-C. If fast enough, stop.
- Rewrite function to use a better algorithm or data structure. If fast enough, stop.
- Rewrite function in C. If fast enough, stop.
- Rewrite function in multi-threaded C with Grand Central Dispatch. If fast enough, stop.
- Rewrite function in OpenCL.
The Three L's
So then why don't I do the computations on the server? Three reasons: latency, locality, and laziness.
Even after optimizing the bejeezus out of a computation, sometimes I can barely return the answer in an acceptable time frame on a decent-sized data set. (Acceptable to me is “feels instantaneous to the user” — about 150ms — and decent-sized to me is about 500,000 rows of data.) Adding another 50ms, 100ms, or heaven forbid, 200ms round-trip time would kill the experience. Server CPUs aren't much faster than the average desktop, so there would be no latency gain moving to a server — only cost.
Instantaneous feedback is “magical”. It feels like you have something in your hands, instead of pulling it around on the end of a leash. Sure, your web app might feel instantaneous when your server is sitting across the LAN, but many users have crappy Internet connections, or are downloading a Torrent, or are living in New Zealand, or whatever. I have DSL broadband in a “hub” city and it still acts funky for no apparent reason from time to time. If I did computations on the server, the vagaries of last-mile Internet connections would constrain my ability to provide a consistent experience to my users.
I make data analysis programs, which sometimes operate on medium-size datasets. Nothing like “Big Data”, but often hundreds of megabytes. Having the code run locally is a big advantage. With a server program, it would take at least several minutes, maybe an hour depending on the connection, just to get the data uploaded. With a desktop program, I can import a gigabyte file and start playing around with it in a matter of seconds.
Many developers assume that everyone wants their data to be “in the cloud”, but that's actually not true for a lot of my customers. Professional researchers often sign agreements in their children's blood stating that their data will be stored on an encrypted disk, won't leave their laptop, and will be destroyed when the research project is completed. “The cloud” is the last place they want their data to go.
Of course, I'm also lazy. With a client-server architecture, I'd have to worry about cache contention with multiple simultaneous requests. I'd have to worry about Amazon EC2 outages. I'd have to worry about scaling, back-ups, and dealing with users who try to do stupid things that manage to crash the server. With a desktop application, the worst a user can do is crash their own program and leave me an unfavorable review.
I also don't have to worry about malicious users. My apps are sandboxed and are forbidden by the operating system from going anywhere near the network. So then what would a malicious script even do? Calculate digits of pi?
Here are a few features that I get “for free” by developing for Mac OS X, but which would either be impossible or entail a world of pain in a web browser.
Have you noticed that Undo support on almost all web applications is either nonexistent or terrible? It's hard to implement, but Core Data solves the problem elegantly. An Undo button encourages users to experiment with the application and not be afraid of making mistakes.
NeXTSTEP, the precursor to OS X, was designed from the ground up to be PDF-friendly. It's trivial to export Quartz images as PDF. The images in my apps exist in a wider context of documents, presentations, and publications, and my users love being able to copy-paste vector versions of the graphics they create.
Remember the 90s?
Zooming is awkward without multitouch. Browsers added Touch APIs a while back, but these only apply to smartphones and tablets. Laptop trackpads, the Magic Trackpad, and the Magic Mouse can't participate. Multitouch interfaces in native Mac OS X applications make navigating a large canvas feel easy and natural.
I don't expect web developers to rush out and starting writing desktop applications upon receiving the news of these three excellent features, but they're a definite bonus, and help to set my apps apart from web-based alternatives.
As a desktop developer, I have almost no operational costs or concerns. If my (static) website goes down, or if the App Store goes down for that matter, I might lose a few sales, but it won't stop my customers from going about their work. If I ever decide to take a long vacation, I'll just put my whole website on S3, and let Apple and Amazon worry about keeping my business running.
If I had enough money to afford dedicated operations people, I might be more inclined to run a complicated web service. But as an independent developer, being able to sleep at night without the fear of being paged is quite a luxury. One thing that most “lifestyle developers” don't tell you is that the lifestyle often includes being chained to a web server.
Life wasn't always this easy. The first few versions of both my apps were quite rough, even with the benefit of professional QA and volunteer beta testers. I barely slept after a couple of critical bugs wormed their way into final releases, and had to beg Apple to perform an expedited review of the fixes.
Nowadays, I have quite a few more beta testers, and it's been a while since I introduced a major regression into a release. Testing a desktop program is an order of magnitude easier than testing a web application. Manually testing against three recent versions of the operating system is sufficient; with a web application, I'd need to test dozens of combinations of browsers, versions, and operating systems. I realize that many companies use automated testing to handle this problem, but for a single developer, developing a comprehensive test suite would be a major undertaking. It's a lot easier just to send builds to a few eager beta testers and tell them what to look for.
The other reason I sleep well is that I don't worry about competition. Not in the proverbial sense of focus on the product, but because I don't think anyone else is crazy enough to develop Mac applications like the ones I've written. If a potential competitor is VC-funded, they'll be writing a web application, or maybe a Windows application; their Mac version (if there ever is one) will be an afterthought, and will almost certainly suck in comparison to mine. If there's a hobbyist Mac developer out there who just wants to “scratch an itch”, well, I already scratched it, and can sell them a backscratcher for a reasonable price.
Mac desktop development, of course, isn't all sunshine and rosebuds.
My market is small. The latest reports show Mac is at about 7.5% of desktop market share. If I had written the software for the web or for Windows, my potential market would be about 10 times larger.
Very few organizations are all Mac, so I can't expect my software to be a line on any company's budget anytime soon. I have to set my prices to be discretionary-fund-friendly. So the diminutive size of the Mac market limits both my volume and my price point.
The flip side is that it's easier to get attention in a small market. Apple recently placed one of my apps next to their own Numbers in a “Data and Analysis” App Store feature. I have a harder time imagining Microsoft featuring my app next to Excel.
I sell through the App Store, which means I collect a one-time sale price. Although cash in hand is nice, it would be more profitable to sell the software on a subscription basis like most web applications.
Viral marketing is difficult. With a web application I would be able to create cool demos and example documents, link to them, and see what sticks. It's impossible to generate buzz around a desktop application using only example files. You need a slick video that plays in a web browser.
Data synchronization would be an issue if I actually supported multiple platforms. But I don't, so it's not.
There's a final advantage that I alluded to earlier, but I haven't discussed yet. By developing for desktop, I have fewer customers, but the ones I do have really like my apps. Really like them. By using Mac-specific technologies — and carefully managing CPU and memory resources — I can deliver a unique software experience that makes even cutting-edge web applications seem dated. As a result, it's easy to build trusting relationships with my customers, and I never hesitate to ask them to test out new builds; they're excited to help, and they want to see me succeed. They love having direct access to the so-called brains behind the product.
That, I think, is the best part. One of the difficult aspects of being an independent software developer is that you can't turn to a colleague to revel in your small daily triumphs. But as I develop relationships with customers, and constantly send them new builds to test out, I receive a steady stream of encouragement from them, and I get to hear first-hand how new features and fixes make their lives just a little bit easier. It makes the development process that much more gratifying and meaningful. It may sound silly, but I just don't think my customers would be as excited for the imaginary web versions of my software that exist out there in some alternate Mac-free universe.
After all that warmth and fuzziness, I hate to talk about money, but I have a final bit of related advice for anyone considering Mac desktop development.
As I mentioned, I sell two titles: one is low-priced and has a somewhat clunky interface (I developed it first); the other is higher-priced and has a more refined interface. If you have the choice, go high price, and put in the extra effort to make the program's quality worth its price tag. A high product price will filter out the bozos and semi-literate demands for refunds; high product quality will filter out unnecessary support emails. All that will be left in your inbox are thank-you letters and a few well-written, almost apologetic, bug reports.
You're reading evanmiller.org, a random collection of math, tech, and musings. If you enjoyed this, you should read the follow-up post, Hackers and <canvas>. Or check out my desktop apps: Magic Maps, a simple mapping program, and Wizard, an easy-to-use statistical analyzer.