Failure strategies vs Swift optionals

When writing code in any language, there’s a couple of ideals that I always try to follow around error handling:

  1. You should always process all possible error paths and respond accordingly.
  2. If the options are between crashing and getting into an inconsistent state, then crashing is better

These two tenants of error handling were drilled into me whilst at Bromium where I lead the team that built the Mac version of their vSentry security product. Every error, no matter how innocuous it may seem, will happen to you when you least expect it, so you should *never* ignore an error path. As a code author you're always chasing the success case, as that's the functionality your user wants, so it's easy to forget that a function might error or that some input to your bit of code might not be what you expect. One of the things I like about Swift (and to a lesser extent also in Go) is that error handling is made explicit and it’s opt out rather than opt in: if you want to ignore an error you can do, but you have to decided to do that, rather than just forget. Such a wonderful feature of the language (modulo the initial confusion because they used exception syntax for something that isn’t exception handling.

At the same time as doing this, there are points in your code where either you know that a failure case will never happen, or if it does it’s because of a programming error rather than something unanticipated in then input or the environment (or at least you expect some code called before yours will have done any input validation). For these cases it’s perfectly fine to just assert a particular state rather than handling it (but still you must acknowledge it!).

It always amazes me that people disable such asserts in production builds though. On most modern event driven code there’s no performance justification for doing this, so the reason given is that you don’t want your program to crash on the user. But to me the alternative is far worse: if an assertion would fail and your asserts have been removed, then your program is now in a state you never designed for it. If you’re lucky nothing serious will happen, but at worst you can cause the user confusion and potentially data loss (very early in my career I failed to validate that I’d detected the temporary folder on disk correctly, and thus cleared out empty string on a disk, which is the root folder…). Yes, if you crash the user will be disappointed, but you will at least get feedback, hopefully a stack trace, and very quickly a bug fix. Otherwise your code can be mis-performing for years before you realise.

Crashes are obviously bad and to be avoided at all reasonable costs, but if you follow rule one, you should never have a crash, except where something you asserted would never go wrong does. In which case you’ve learned you should have handled that error despite what you assumed. If you don’t like asserts, then write more error handlers, but doing neither is not an option in my book.

I’ve finally come to my peace with the two variants of the optional value unwrapping in Swift, which initially to me seemed like an odd design decision for a language focused on program safety. In Swift if you have an optional variable (i.e., a variable that either contains a value or is null), you can either use the conditional unwrap (the ? operator) or an unconditional unwrap (the ! operator). I was of the opinion that you should always use the conditional version and provide suitable error handlers, and that the unconditional unwrap was akin to never bothering to check return values on functions in other languages. But I've been writing more iOS UI code in anger and it has made me realise that the unconditional operator is actually like an assert: I’m going to unwrap this optional and I assert it will always hold a value. This is very useful for where you have resources loaded from storyboards etc. where you “know” that the value won’t be nil and will point to a UI element but convention requires the variable be optional.

You still need to be fully cognisant of this decision, and distrusting of any code you see where an unconditional unwrap us used until you’ve convinced yourself it’s actually just an assert call, and in general explicit error handling is always better for the user, but I’m glad I’ve now found a place for what used to seem like a Swift feature that went against all the other things that make the language safer.

Why I moved to Hockey App

Until recently, if you were testing iOS apps, there was one third party service that was absolutely essential - TestFlight. TestFlight is a web service that helps you manage all the apps you develop and your app testers, and makes it easy for testers to install your apps on their iOS devices (something Apple have made quite tricky otherwise). Over time TestFlight added more and more functionality, making it easy to retrieve crash logs, add checkpoints to see which features were tested and which weren't, and provide reminders to testers when new versions are available. TestFlight was a godsend to both developers and testers alike. And on top of everything, it is totally free - how much better can you get?

However, I recently came to find TestFlight wanting, and switched to an alternative paid for service, HockeyApp. At a fundamental level HockeyApp does a fairly similar set of things to TestFlight, but is a little less slick than TestFlight, and costs money. A few people have asked why I switched, so here's a quick summary of where HockeyApp wins over TestFlight for me.

Multiple platform support

TestFlight only supports iOS, but of late I've been working on a couple of things for OS X, and HockeyApp supports testing OS X apps in addition to iOS (it also claims to support Android development, but that's not something I've had cause to investigate yet). In general, testing on the Mac is easier than testing on iOS, as Apple have no special technologies in place to limit how you distribute test applications on the Mac, but even here HockeyApp make the process much better with their help than without.

Sparkle is an all but ubiquitous open source library for rolling out app updates on the Mac, or at least it as before the Mac App Store took over that duty. Sparkle will sit in your app and monitor a appcast feed from a server (much like an RSS Feed) to check for updates. HockeyApp supports using Sparkle - when you upload test builds they'll appear in a private appcast feed, and if you tell your app to look at that all your users will get notified the moment there's a new update, ensuring everyone is up to date.

Even if you intend to ship through the Mac App Store, which doesn't allow you to use Sparkle, you can use Sparkle during testing and then remove it when you submit the app to Apple - it's just a huge time saver.

And needless to say, that Hockey App supports both iOS and Mac means I can just use one service rather than two, which is always good.

Uptime

After almost a year of flawless service, TestFlight had some unfortunate downtime recently. Running a web service is difficult, so I appreciate that sometimes things go down, and they have my sympathy there. But I hit a situation where TestFlight went down twice for the better part of a UK working day (they're a US company, so they're most likely asleep at that point), and during the second event there was no acknowledgement that I could see from TestFlight that anything had gone wrong, and during that time I couldn't get important test builds out to my clients, leading me to have to apologise to people for something beyond my control.

This is where the \"free\" suddenly is less appealing. I don't really feel I can complain when something offered for free goes away. It's not that you get what you pay for, but it's more that there's no way in which TestFlight are particularly beholden to users when the users don't pay.

HockeyApp do charge, which makes the relationship much easier to understand. HockeyApp's uptime has been thus far been very good, but of course all web services will have times when someone goes wrong beyond anyone's control, so I don't expect HockeyApp to be above the occasional outage. But I feel they'll take it more seriously given that I'm paying for the service.

Integration with Xcode

I gather TestFlight does something similar now, but at the time when I switched I still had to upload apps to TestFlight by hand via a browser upload. HockeyApp have a little app for the Mac that you can integrate with Xcode as part of the app archive process, which will upload new builds to HockeyApp directly. Combining this with automatically generating version numbers from git means I now don't need to lift a finger when getting new test version of my apps to testers.

Nothing is prefect

This all makes it seem like HockeyApp must clearly be the way and anyone that uses TestFlight is in the wrong, but we must give TestFlight its due here - there's still some things that TestFlight do better than HockeyApp. TestFlight's website is just generally a little more slick than HockeyApp - be it setting up new apps, adding users, and so forth. TestFlight's library for getting crash logs, adding checkpoints from apps, and grabbing new builds is just a single library - you need to add two for HockeyApp and it's just a little bit more involved. But none of this adds up to much more friction in the long run, but it might be enough to keep some people from switching.

I started trying out HockeyApp just for my Mac OS X projects, but at the end of the day I switched wholeheartedly when I was unfortunate that their downtime coincided with a critical time in my app development and was unable to reach my testers twice in a month. I suspect that's atypical, and you should have a look at both services for yourself, but I think it shows that is just how important to developers apps like TestFlight and HockeyApp are now - they're essential infrastructure for developers, and we're severally impacted when they go away. I'm happy to pay for a service like this in order to try to ensure it's reliable - I just can't work without it.

Update: I got a nice note from the people at HockeyApp letting me know that they'll be moving to having just a single library for managing in app updates and crash logging etc., which is great news.

A new year, a new look for PlaceWhisper.com

It's the new year, so time to release some things we've been working on for the last month or so - the new look PlaceWhisper website, and our new features: collections and embeddable maps.

When we first released PlaceWhisper 2 website back in August we enabled you to log in to the PlaceWhisper website and explore the things you'd created and collected on the web. However, it didn't add much to the experience of PlaceWhisper other than a larger canvas on which to view things. We said it was still being worked on, and here's the first fruits of that effort.

Welcome-to-PlaceWhisper!.png

The new look

The first cut of the PlaceWhisper website initially tried to pack too much in, then when we released we removed unfinished features, and it left a website that was functional, but didn't hang together quite right. So we've gone back and simplified and cleaned up the website, so now it's a lot more functional and practical.

When you log in you'll be presented with an event list of what's happening in your bit of PlaceWhisper: who's been collecting your Whispers, what your friends have been creating for you to find, and so on. From there you can find a map of everything you've created and collectioned, and view those things in detail, and from there share them with your friends via Facebook, Twitter, and Google Plus. You can now more readily manage your contacts and your own account too.

Collections

If you're a PlaceWhisper subscriber then you'll be able to create Collections - this is a new way to organise your Whispers. If you create a series of Whispers around a single theme, but they don't fit the notion of a trail, then you can put them together in a Collection. Collections will show up in the PlaceWhisper app's "what's local" menu, so they're a great way to get your content noticed by people, and people can then filter the PlaceWhisper app's view to just show the contents of a given collection.

Collections currently can only be managed and modified by you, but in the new year we'll be expanding that feature so that you can share your Collection with friends, and so you can build up the contents of a Collection as a team rather than as an individual.

Embedding your collections

One important new feature of collections is you can optionally turn them into a map that you and others can embed in your own website or blog. When you enable embedding for a collection, you'll be provided with the HTML code to place the map in another website. This map will then show all the Whispers in that Collection on the map, and people can click on the Whispers and read their contents.

This makes PlaceWhisper an excellent way to build up location content not just for mobile access, but also for the web.

Looking forward to the new year

2011 saw lots of development on PlaceWhisper, and we're really pleased with where we've got to, but there's still more to come. We hope you'll join us as we grow in 2012, but until then, we hope you have a merry festive period and new year!