Monday, September 18, 2017

A short rant on XML - the Good, the Bad, and the Ugly

[editor's note: This blog post has been in "Drafts" for 11 years. In the spirit of just getting stuff out there, I'm publishing it basically as-is. Look for a follow-up blog post next week with some additional observations on structured data transfer from the 21st century]

So, let's see if I can keep myself to less than ten pages of text this time...

XML is the eXtensible Markup Language. It's closely related to both HTML, the markup language used to make the World Wide Web, and SGML, a document format that you've probably never dealt with unless you're either a government contractor, or you used the Internet back in the days before the Web. For the pedants out there, I do know that HTML is actually an SGML "application" and that XML is a proper subset of SGML. Let's not get caught up in the petty details at this point.

XML is used for a variety of different tasks these days, but the most common by far is as a kind of "neutral" format for exchanging structured data between different applications. To keep this short and simple, I'm going to look at XML strictly from the perspective of a data storage and interchange format.


The good

Unicode support

XML Documents can be encoded using the Unicode character encoding, which means that nearly any written character in any language can be easily represented in an XML document.

Uniform hierarchical structure

XML defines a simple tree structure for all the elements in a file - there's one root element, it has zero or more children, which each have zero or more children, ad infinitum. All elements must have an open and close tag, and elements can't overlap. This simple structure makes it relatively easy to parse XML documents.

Human-readable (more or less)

XML is a text format, so it's possible to read and edit an XML document "by hand" in a text editor. This is often useful when you're learning the format of an XML document in order to write a program to read or translate it. Actually writing or modifying XML documents in a text editor can be incredibly tedious, though a syntax-coloring editor makes it easier.

Widely supported

Modern languages like C# and Java have XML support "built in" in their standard libraries. Most other languages have well-supported free libraries for working with XML. Chances are, whatever messed up environment you have to work in, there's an XML reader/writer library available.


The bad

Legacy encoding support

XML Documents can also be encoded in whatever wacky character set your nasty legacy system uses. You can put a simple encoding="Ancient-Elbonian-EBCDIC" attribute in the XML declaration element, and you can write well-formed XML documents in your favorite character encoding. You probably shouldn't expect that anyone else will actually be able to read it, though.

Strictly hierarchical format

Not every data set you might want to interchange between two systems is structured hierarchically. In particular, representing a relational database or an in-memory graph of objects is problematic in XML. A number of approaches are used to get around this issue, but they're all outside the scope of standardized XML (obviously), and different systems tend to solve this problem in different ways, neatly turning the "standardized interchange format for data" into yet another proprietary format, which is only readable by the software that created it.

XML is verbose

A typical XML document can be 30% markup, sometimes more. This makes it larger than desired in many cases. There have been several attempts to define a "binary XML" format (most recently by the W3C group), but they really haven't caught on yet. For most applications where size or transmission speed is an issue, you probably ought to look into compressing the XML document using a standard compression algorithm (gzip, or zlib, or whatever), then decompressing it on the other end. You'll save quite a bit more that way than by trying to make the XML itself less wordy.

Some XML processing libraries are extremely memory-intensive

There are two basic approaches to reading an XML document. You can read the whole thing into memory and re-construct the structure of the file into a tree of nodes in memory, and then the application can use standard pointer manipulation to scan through the tree of nodes, looking for whatever information it needs, or further-transforming the tree into the program's native data structures. One XML processing library I've used loaded the whole file into memory all at once, then created a second copy of all the data in the tags. Actually, it could end up using up to the size of the file, plus twice the combined size of all the tags.

Alternatively, the reader can take a more stream-oriented approach, scanning through the file from beginning to end, and calling into the application code whenever an element starts or ends. This can be implemented with a callback to your code for every tag start/end, which gives you a simple interface, and doesn't require holding large amounts of data in memory during the parsing.

No random access

This is just fallout from the strict hierarchy, but it's extremely labor intensive to do any kind of data extraction from a large XML document. If you only want a subset of nodes from a couple levels down in the hierarchy, you've still got to step your way down there, and keep scanning throught the rest of the file to figure out when you've gone up a level.


The ugly

By far, the biggest problems with XML don't have anything to do with the technology itself, but with the often perverse ways in which it's misapplied to the wrong problems. Here are a couple of examples from my own experience.

Archiving an object graph, and the UUID curse

XML is a fairly reasonable format for transferring "documents", as humans understand them. That is, a primarily linear bunch of text, with some attributes that apply to certain sections of the text.

These days, a lot of data interchange between computer programs is in the form of relational data (databases), or complex graphs of objects, where you'll frequently need to make references back to previous parts of the document, or forward to parts that haven't come across yet.

The obvious way to solve this problem is by having a unique ID that you can reference to find one entity from another. Unfortunately, the "obvious" way to ensure that a key is unique is to generate a globally-unique key, and so you end up with a bunch of 64-bit or 128-bit GUIDs stuck in your XML, which makes it really difficult to follow the links, and basically impossible to "diff' the files, visually.

One way to avoid UUID proliferation is to use "natural unique IDs, if your data has some attribute that needs to be unique anyway.

What's the worst possible way to represent a tree?

I doubt anybody's ever actually asked this question, but I have seen some XML structures that make a pretty good case that that's how they were created. XML, by its heirarchical nature, is actually a really good fit for hierarchical data. Here is one way to store a tree in XML:

<pants color="blue" material="denim">
  <pocket location="back-right">
    <wallet color="brown" material="leather">  
      <bill currency="USD" value="10"></bill>  
      <bill currency="EURO" value="5"></bill>  
    </wallet>
  </pocket>  
</pants>  

And here's another:

<object>
  <id>
    20D06E38-60C1-433C-8D37-2FDBA090E197
  </id>
  <class>
    pants
  </class>
  <color>
    blue
  </color>
  <material>
     denim
  </material>
</object>
<object>
  <id>
    1C728378-904D-43D8-8441-FF93497B10AC
  </id>
  <parent>
    20D06E38-60C1-433C-8D37-2FDBA090E197
  </parent>
  <class>
    pocket
  </class>
  <location>
    right-back
  </location>
</object>
<object>
  <id>
    AFBD4915-212F-4B47-B6B8-A2663025E350
  </id>
  <parent>
    1C728378-904D-43D8-8441-FF93497B10AC
  </parent>
  <class>
    wallet
  </class>
  <color>
    brown
  </color>
  <material>
    leather
  </material>
</object>
<object>
  <id>
    E197AA8D-842D-4434-AAC9-A57DF4543E43
  </id>
  <parent>
    AFBD4915-212F-4B47-B6B8-A2663025E350
  </parent>
  <class>
    bill
  </class>
  <currency>
    USD
  </currency>
  <denomination>
    10
  </denomination>
</object>
<object>
  <id>
    AF723BDD-80A1-4DAB-AD16-5B37133941D0
  </id>
  <parent>
    AFBD4915-212F-4B47-B6B8-A2663025E350
  </parent>
  <class>
    bill
  </class>
  <currency>
    EURO
  </currency>
  <denomination>
    10
  </denomination>
</object>

So, which one of those is easier to read? And did you notice that I added another 5 Euro to my wallet, while translating the structure? Key point here: try to have the structure of your XML follow the structure of your data.


Monday, September 04, 2017

Post-trip review: Telestial “International Travel SIM”

For our recent trip to Europe, Yvette and I tried the seasoned-traveler technique of swapping out the SIM cards in our phones, rather than paying AT&T’s fairly extortionate international roaming fees. It was an interesting experience, and we learned a few things along the way, which I’ll share here.


We used Telestial, which is apparently Jersey Telecom. Not New Jersey: JT is headquartered in the Jersey Isles, off the coast of Britain. JT/Telestial's claim to fame is really their wide roaming capability. Their standard “I’m traveling to Europe” SIM is good pretty much across all of Europe. It definitely worked just fine in Germany, Denmark, Sweden, Austria, Estonia, Russia, and Finland. They claim a few dozen more, and I don’t doubt it works equally-well in those countries.


Why not just get a local SIM in the country you’re visiting? Isn’t that cheaper?

People who frequently travel overseas will often just pop into a phone retailer, or buy a SIM from a kiosk in the airport. Based on the comparison shopping I did while we were traveling, this is definitely cheaper tan the Telestial solution. However, it’s not at all clear in many cases how well an Austrian SIM is going to work in Finland (for example), and just how much you’ll be paying for international roaming.


So, I think if you’re traveling to just one country (especially one with really cheap mobile phone service costs), buying a local SIM is definitely the way to go. I didn’t really want to keep updating people with new contact numbers every other day as we switched countries. I might look into one of the “virtual phone number” solutions, like Google Voice, for the next multi-country trip. Being able to give people one number, and still roam internationally, seems like it’d be useful, but I don’t know what the restrictions are.


What does setup look like?

First of all, you need a compatible phone. Not all American mobile phones will wrk in Europe. You can check the technical specs for the particular phone mode you have, to see which radio frequencies it supports. Alternatively, you can buy any iPhone more-recent than the iPhone 4s, all of which are “world phones”, as far as I know. Verizon and Sprint still some phones that are CDMA-only, which means they can’t work anywhere but the USA, but most CDMA smartphones also have a GSM SIM slot, so it’s worth taking a look to see, even if you’re on Verizon.


Secondly, your phone needs to not be “activation locked” to a particular carrier. Most phones sold on contract in the US are set up this way, so you can’t just default on the contract and get a phone you can use on another network. Ideally, your phone would get unlocked automatically at the end of the contract, but US law doesn’t require this, so you’ll need to request an unlock from your carrier. AT&T has made this process a lot easier since the last time I tried to do it, which is great, because I forgot to check that Yvette’s phone was unlocked before we left. I did manage to make the unlock request from the other phone while we were in a taxi on the freeway in Austria, which is a testament to how easy this stuff is these days, I guess.


Assuming you have a compatible phone, then process is basically power off phone, pop out the SIM tray with a paper clip, swap the SIMS, turn on the phone, and wait. For the Telestial SIM, you probably really want to activate it and pre-pay for some amount of credit before your trip, which is easy to do on their website.


What kind of plan did you get?

We had a pre-paid fixed allowance for calls and text, and 2GB of data for each phone. Calls were $0.35 a minute, and texts were $0.35 each. Pre-loading $30 on the phone was enough for and hour and a half of phone calls, or a fairly large number of texts. When we had data coverage, we could use iMessage or WhatsApp fro basically free text messages. I don't know whether Voice Over LTE actually worked, and if it avoided the per-minute charge, since we just didn't call that much.

Did you actually save any money?

Compared to what it cost to pay AT&T for an international roaming plan while Yvette was in the UK for a month, we definitely did save a substantial amount of money. This is true even with the crazy cruise ship issue (see below). Without that, it would have been massively less-expensive. And compared to AT&T’s “no plan” international rates (which I got to try out in Israel), there’s absolutely no comparison.

What happened on the cruise ship?

Most of the time, the cruise ship did not have cell service. Which was pretty much fine - we had good coverage when we were in port, and there was WiFi on the ship, if we wanted to pay for it (we did not). We had, on two occasions, a weird thing were our phones managed to connect to a shipboard cell network (maybe on another passing ship?), where we were charged truly outrageous roaming data rates - several dollars a megabyte, which obviously burned through the $30 in prepaid credit really fast. On the other hand, prepaid means that we didn't lose more than $30 (twice, so $60 total). I still don't know exactly what happened there, but if I do this again sometime, I'm going to keep data turned off on the phone when not in port.

The good:


  1. Pre-paid, which limits crazy bills
  2. Easy setup
  3. Easy to recharge, either over the phone, or using the app
  4. Per-minute and per-text rates not too terrible
  5. Works pretty much anywhere in Europe


The bad:
  1. Cruise ship roaming will use up your data allowance right quick
  2. Fixed recharge sizes, and monthly expiration
  3. Forwarding doesn’t work for texts
  4. Some weirdness with “from” numbers on texts (apparently Austria-only)?
  5. No tethering
  6. Email support non-responsive

Conclusion: would we do it again?

Overall, the process was fairly-painless, other than the cruise ship issue. If there’s a simple way to fix that, I’d have no problem doing this again. Otherwise, I’d have to recommend during cell data off when you’re not in port, to avoid accidentally costing yourself a bunch of money.

Monday, August 28, 2017

A brief history of the Future

A brief history of the Future

Lessons learned from API design under pressure

It was August of 2009, and the WebOS project was in a bit of trouble. The decision had been made to change the underlying structure of the OS from using a mixture of JavaScript for applications, and Java for the system services, to using JavaScript for both the UI and the system services. This decision was made for a variety of reasons, primarily in a bid to simplify and unify the programming models used for application development and services development. It was hoped that a more-familiar service development environment would be helpful in getting more developers on board with the platform. It was also hoped that by having only one virtual machine running, we'd save on memory.

Initially, this was all built on top of a customized standalone V8 JavaScript interpreter, with a few hooks to system services. Eventually, we migrated over to Node.js, when Node was far enough along that it looked like an obvious win, and after working with the Node developers to improve performance on our memory-limited platform.

The problem with going from Java to JavaScript

As you probably already know, despite the similarity in the names, Java and JavaScript are very different languages. In fact, the superficial similarities in syntax were only making things harder for the application and system services authors trying to translate things from Java to JavaScript.

In particular, the Java developers were used to a multi-threaded environment, where they could spin off threads to do background tasks, and have them call blocking APIs in a straightforward fashion. Transitioning from that to JavaScript's single-threaded, events and callbacks model was proving to be quite a challenge. Our code was rapidly starting to look like a bunch of "callback hell" spaghetti.

The proposed solution

As one of the most-recent additions to the architecture group, I was asked to look into this problem, and see if there was something we could do to make it easier for the application and service developers to write readable and maintainable code. I went away and did some research, and came back with an idea, which we called a FutureThe Future was a construct based on the idea of a value that would be available "in the future". You could write your code in a more-or-less straight-line fashion, and as soon as the data was available, it'd flow right through the queued operations.

If you're an experienced JavaScript developer, you might be thinking at this point "this sounds a lot like a Promise", and you'd be right. So, why didn't we use Promises? At this point in history, the Proamises/A spec was still in active discussion amongst the CommonJS folks, and it was not at all obvious that it'd become a popular standard (and in fact, it took Promises/A+ for that to happen). The Node.js core had in fact just removed their own Promises API in favor of a callback-based API (this would have been around Node.js v0.1, I think).

The design of the Future

Future was based on ideas from SmallTalk(promise), Java(future/promise), Dojo.js(deferred), and a number of other places. The primary design goals were:
  • Make it easy to read through a piece of asynchronous code, and understand how it was supposed to flow, in the "happy path" case
  • Simplify error handling - in particular, make it easy to bail out of an operation if errors occur along the way
  • To the extent possible, use Future for all asynchronous control flow
You can see the code for Future, because it got released along with the rest of the WebOS Foundations library as open source for the Open WebOS project.

My design brief looked something like this:
A Future is an object with these properties and methods:
.result The current value of the Future. If the future does not yet have a value, accessing the result property raises an exception. Setting the result of the Future causes it to execute the next "then" function in the Future's pipeline.  
.then(next, error) Adds a stage to the Future's pipeline of steps. The Future is passed as a parameter to the function "next". The "next" function is invoked when a value is assigned to the future's result, and the (optional) "error" function is invoked if the previous stage threw an exception. If the "next" function throws an exception, the exception is stored in the Future, and will be re-thrown if the result of the Future is accessed.
This is more-or-less what we ended up implementing, but the API did get more-complicated along the way. Some of this was an attempt to simplify common cases that didn't match the initial design well. Some of it was to make it easier to weld Futures into callback-based code, which was ultimately a waste of time, in that Future pretty much wiped out all competing approaches to flow control. And one particular set of changes was thrown in at the last minute to satisfy a request that should just have been denied (see What went wrong, below).

What went right

We shipped a "minimal viable product" extremely quickly

Working from the initial API design document, Tim got an initial version of Future out to the development team in just a couple of days, which had all of the basics working. We continued to iterate for quite a while afterwards, but we were able to start the process of bring people up to speed quickly.

We did, in fact, eliminate "callback hell" from our code base

After the predictable learning curve, the former Java developers really took to the new asynchronous programming model. We went from "it sometimes kind of works", to "it mostly works" in an impressively-short time. Generally speaking, the Future-based code was shorter, clearer, and much easier to read. We did suffer a bit in ease of debugging, but that was as much due to the primitive debugging tools on Node as it was to the new asynchronous model.

We doubled-down on our one big abstraction

Somewhat surprisingly to me, the application teams also embraced Futures. They actually re-wrote significant parts of their code to switch over to Future-based APIs at a deeper level, and to allow much more code sharing between the front end and back end of the Mail application, for example. This code re-use was on the "potential benefits" list, but it was much more of a win than anyone originally expected.

We wrote a bunch of additional libraries on top of Future, for all sorts of asynchronous tasks - for file I/O, database access, network and telecoms, for the system bus (dbus) interface, basically anything that you might have wanted to access on the platform, was available as a Future-based API.

The Future-based code was very easy to reason about in the "happy path" case

One of the best things about all this, is that with persistent use of Futures everywhere, you could write code that looked like this:
downloadContacts().then(mergeContacts).then(writeNewContacts).then(success, error)
Most cases were a bit more-complicated than that (often using inline functions), but the pattern of  only handling the success case, and just letting errors propagate, was very common. And in fact, the "error" case was, as often as not, logging a message and rescheduling the task for later.

The all-or-nothing error propagation technique fit (most of) our use cases really well

The initial use case of the Future was for a WebOS feature called "Synergy". This was a framework for combining data from multiple sources into a single uniform format for the applications. So, for example, you could combine your contacts from Facebook, Google, and Yahoo into a single address book list, and WebOS would automatically de-dubplicate and link related contacts, and sync changes made on the phone to the proper remote service that the data originally came from. Similarly, all of your incoming e-mail went into the same "Mail" database on-device.

In a multi-stage synchronization process like this, there are all sorts of ways that the operation can fail - the remote server might be down, or the network might be flaky, or the user might decide to put the phone into airplane mode in the middle of a sync operation. In the vast majority of cases, we didn't actually care what the error was, just that an error had occurred. When an error happened, the usual response was to leave the on-phone data the way it was, and try again later. In those cases where "fuck it, I give up" was not the right error handling strategy, the rough edges of the error-handling model were a bit easier to see.

What went wrong

The API could have been cleaner/simpler

It didn't take long before we were adding convenience features to make some of the use cases simpler. Hence, the "whilst" function on Future, which was intended to make it easier to iterate over a function that returned Futures. There were a couple of other additions that also got a very small amount of use, and could have easily been replaced by documentation of the "right" way to do things.

Future had more-complex internal state than was strictly needed

If you look at Promises, they've really only got the minimal amount of state, and you chain functions together by returning a Promise from each stage. Instead of having lots and lots of Futures linked together to make a pipeline of operations, Future was the pipeline. I think that at some level this both decreased heap churn by not creating a bunch of small objects, and it probably made it somewhat easier to debug broken pipelines (since all of the stages were visible). Obviously, if we'd known that Promises were going to become a big thing in JavaScript, we would have stayed a lot closer to the Promises/A spec.

Error handling was still a bit touchy, for non-transactional cases

If you had to write code that actually cared about handling errors, then the "error" function was actually located in a pretty terrible place, you'd have all these happy-path "then" functions, and one error handler in the middle. Using named functions instead of anonymous inline functions helped a bit with this, but I would still occasionally get called in to help debug a thrown exception that the developer couldn't find the source for.

It would have been really nice to have a complete stack trace for the exception that was getting re-thrown, but we unfortunately didn't have stack traces available in both the application context and the service context. In the end, "thou shalt not throw an exception unless it's uniquely identifiable" was almost sufficient to resolve this.

I caved on a change to the API that I should have rejected

Fairly late in the process, someone came to me and said "I don't like the 'magic' in the way the result property works. People don't expect that accessing a property will throw an exception, so you should provide an API to access the state of the Future via function calls, rather than property access".  At this point, we had dozens of people successfully using the .result API, and very little in the way of complaints about that part of the design.

I agreed to make the addition, so we could "try it out" and see whether the functional API was really easier or clearer to use. Nobody seemed to think so, except for the person who asked for it. Since they were using it, it ended up having to stay in the implementation. and since it was in the implementation, it got documented, which just confused later users (especially third parties), who didn't understand why there were two different ways to accomplish the same tasks.


How do I feel about this, 8 years later?

Pretty good, actually. Absent a way to see into the future, I think we made a pretty reasonable decision with the information we had available. The Bedlam team did an amazing bit of work, and WebOS got rapidly better after the big re-architecturing. In the end, it was never quite enough to displace any of the major mobile OSes, but I still miss some features of Synergy, even today. After all the work Apple has done over the years to improve contact sync, it's still not quite as good (and not nearly as open to third parties) as our solution was.

Monday, August 21, 2017

What your Internet Of Things startup can learn from LockState

The company LockState has been in the news recently for sending an over-the-air update to one of their smart lock products which "bricked" over 500 of these locks. This is a pretty spectacular failure on their part, and it's the kind of thing that ought to be impossible in any kind of well-run software development organization, so I think it's worthwhile to go through a couple of the common-sense processes that you can use to avoid being the next company in the news for something like this.

The first couple of these are specific to the problem of shipping the wrong firmware to a particular model, but the others apply equally well to an update that's for the right target, but is fundamentally broken, which is probably the more-likely scenario for most folks.

Mark your updates with the product they go to
The root cause of this incident was apparently that LockState had produced an update intended for one model of their smart locks, and somehow managed to send that to a bunch of locks that were a different model. Once the update was installed, those locks were unable to connect to the Internet (one presumes they don't even boot), and so there was no way for them to update again to replace the botched update.

It's trivially-easy to avoid this issue, using a variety of different techniques. Something as simple as using a different file name for firmware for different devices would suffice. If not that, you can have a "magic number" at a known offset in the file, or a digital signature that uses a key unique to the device model. Digitally-signed firmware updates are a good idea for a variety of other reasons, especially for a security product, so I'm not sure how they managed to screw this up.

Have an automated build & deployment process
Even if you've got a good system for marking updates as being for a particular device, that doesn't help if there are manual steps that require someone to explicitly set them. You should have a "one button" build process which allows you to say "I want to build a firmware update for *this model* of our device, and at the end you get a build that was compiled for the right device, and is marked as being for that device.

Have a staging environment
Every remote firmware update process should have the ability to be tested internally via the same process end-users would use, but from a staging environment. Ideally, this staging environment would be as similar as possible to what customers use, but available in-company only. Installing the bad update on a single lock in-house before shipping it to customers would have helped LockState avoid bricking any customer devices. And, again - this process should be automated.

Do customer rollouts incrementally
LockState might have actually done this, since they say only 10% of their locks were affected by this problem. Or they possibly just got lucky, and their update process is just naturally slow. Or maybe this model doesn't make up much of the installed base. In any case, rolling out updates to a small fraction of the installed base, then gradually ramping it up over time, is a great way to ensure that you don't inconvenience a huge slice of your user base all at once.

Have good telemetry built into your product
Tying into the previous point, wouldn't it be great if you could measure the percentage of systems that were successfully updating, and automatically throttle the update process based on that feedback? This eliminates another potential human in-the-loop situation, and could have reduced the damage in this case by detecting automatically that the updated systems were not coming back up properly.

Have an easy way to revert firmware updates
Not everybody has the storage budget for this, but these days, it seems like practically every embedded system is running Linux off of a massive Flash storage device. If you can, have two operating system partitions, one for the "current" firmware, and one for the "previous" firmware. At startup, have a key combination that swaps the active install. That way, if there is a catastrophic failure, you can get customers back up and running without having them disassemble their products and send them in to you, which is apparently how LockState is handling this.

If your software/hardware allows for it, you can even potentially automate this entirely - have a reset watchdog timer that gets disabled at the end of boot, and if the system reboots more than once without checking in with the watchdog, switch back to the previous firmware.

Don't update unnecessarily
No matter how careful you are, there are always going to be some cases where a firmware update goes bad. This can happen for reasons entirely out of your control, like defective hardware that just happens to work with version A of the software, but crashes hard on version B.

And of course the easiest way to avoid having to ship lots of updates is sufficient testing (so you have fewer critical product defects to fix), and reducing the attack surface of your product (so you have fewer critical security issues that yo need to address on a short deadline.


Sunday, August 13, 2017

Why I hate the MacBook Pro Touchbar

Why I hate the MacBook Pro Touchbar

The Touchbar that Apple added to the MacBook Pro is one of those relatively-rare instances in which they have apparently struck the wrong balance between form and function. The line between “elegant design” and “design for its own sake” is one that they frequently dance on the edge of, and occasionally fall over. But they get it right often enough that it’s worth sitting with things for a while to see if the initial gut reaction is really accurate.

I hated the Touchbar pretty much right away, and I generally haven’t warmed up to it at all over the last 6 months. Even though I’ve been living with it for a while, I have only recently really figured out why I don’t like it.

What does the Touchbar do?

One of the functions of the Touchbar, of course, is serving as a replacement for the mechanical function keys at the top of the keyboard. It can also do other things, like acting as a slider control for brightness, or quickly allowing you to quickly select elements from a list. Interestingly, it’s the “replacement for function keys” part of the functionality that gets most of the ire, and I think this is useful for figuring out where the design fails.

What is a “button” on a screen, anyway?

Back in the dark ages of the 1980s, when the world was just getting used to the idea of the Graphical User Interface, the industry gradually settled on a series of interactions, largely based on the conventions of the Macintosh UI. Among other things, this means “push buttons” that highlight when you click the mouse button on them, but don’t actually take an action until you release the mouse button. If you’ve used a GUI that’s takes actions immediately on mouse-down, you might have noticed that they feel a bit “jumpy”, and one reason the Mac, and Windows, and iOS (mostly)  perform actions on release is exactly because action on mouse-down feels “bad”.

Why action on release is good:

Feedback — When you mouse-down, or press with your finger, you can see what control is being activated. This is really important to give your brain context for what happens next. If there’s any kind of delay before the action completes, you will see that the button is “pressed”, and know that your input was accepted. This reduces both user anxiety, and double-presses.

Cancelability — In a mouse-and-pointer GUI, you can press a button, change your mind, and move the mouse off before releasing to avoid the action. Similar functionality exits on iOS, by moving your finger before lifting it. Even if you hardly ever use this gesture, it’s there, and it promotes a feeling of being in control.

Both of these interaction choices were made to make the on-screen “buttons” feel and act more like real buttons in the physical world. In the case of physical buttons or keyswitches, the feedback and the cancelability are mostly provided by the mechanical motion of the switch. You can rest your finger on a switch, look at which switch it is, and then decide that you’d rather do something else and take your finger off, with no harm done. The interaction with a GUI button isn’t exactly the same, but it provides for “breathing space” in your interaction with the machine, which is the important thing.

The Touchbar is (mostly) action on finger-down

With a very few exceptions [maybe worth exploring those more?], the Touchbar is designed to launch actions on finger-down. This is inconsistent with the rest of the user experience, and it puts a very high price on having your finger slip off of a key at the top of the keyboard. This is exacerbated by bad decisions made by third-party developers like Microsoft, who ridiculously put the “send” function in Outlook on the Touchbar, because if there was ever anything I wanted to make easier, it’s sending an email before I’m quite finished with it.

How did it end up working that way?

I’m not sure why the designers at Apple decided to make things work that way, given their previous experience with GUI design on both the Mac and iOS. If I had to take a guess, the logic might have gone something like this:

The Touchbar is, essentially, a replacement for the top row of keys on the keyboard. Given that the majority of computer users are touch-typists, then it makes sense to have the Touchbar buttons take effect immediately, in the same way that the physical keyswitches do. Since the user won’t be looking at the Touchbar anyway, there’s no need to provide the kind of selection feedback and cancelability that the main UI does.

There are a couple of places where this logic goes horribly wrong. First off, a whole lot of people are not touch typists, so that’s not necessarily the the right angle to come at this from. Even if they were, part of the whole selling point of the Touchbar is that it can change, in response to the requirements of the app. So you’re going to have to look at it some of the time, unless you’ve decide to lock it into “function key only” mode. In which case, it’s a strictly-worse replacement for the keys that used to be there, and you’re not getting the benefits of the reconfigurability.

Even if you were going to use the Touchbar strictly as an F-key replacement, it still doesn’t have the key edges to let you know whether you’re about to hit one key or two, so you’ll want to look at what you’re doing anyway. I know there are people out there who use the function keys without looking at them, but the functions there are rarely-enough used that I suspect the vast majority of users end up having to look at the keyboard anyway, in order to figure out which one is the “volume up” key, or at least the keyboard-brightness controls.

How can Apple fix this?

First, and primarily, make it less-likely for users to accidentally activate functions on the Touchbar. I think that some amount of vertical relief could make this failure mode less-likely, though I’m not sure if the Touchbar should be higher or lower than it is now. I have even considered trying to fabricate a thin divider to stick to the keyboard to keep my finger away from accidentally activating the “escape” key, which is my personal pet-peeve with the touch bar.

A better solution to that problem is probably to include some amount of pressure-sensitivity and haptic feedback. The haptic home button on the iPhone 7 does a really good job of providing satisfying feedback without any visuals, so we know thiscan work well. Failing that, at least some way to bail out of hitting the Touchbar icons would be worth pursuing - possibly making them less senstive to grazing contact, though that would increase the cases where you didn’t activate a button while actually trying to.

Another option would be bringing back the physical function keys. This doesn’t necessarily mean killing the Touchbar, but maybe just moving it away from the rest of the keyboard a bit. This pretty much kills the “you can use it without taking your eyes off the screen or your hands off the home row” argument, but I’m really not convinced that’s at all realistic, unless you only ever use one application.

So, is Apple going to do anything to address these issues?

Honestly? You can never tell with them. Apple’s history of pushing customers forward against their will (see above) argues that they’ll pursue this for a good while, even if it’s clearly a bad idea. On the other hand, the pressure-sensitivity option seems like the kind of thing they might easily decide to add all by themselves. In the meantime, I’ll be working out my Stick On Escape Key Guard…

Sunday, December 18, 2016

Rogue One: A Star Wars Review

Spoiler-free intro

If you haven't seen the movie yet, you might want to not read past the spoiler alert warning below.

So, you've no doubt seen reviews that say Rogue One is the best Star Wars film, and reviews that claim it's utterly disappointing. I liked it a lot, and I think it's a movie that gets better the closer you look at it. I definitely plan to see it again, and see how much more I can pick out of it.

I have a theory about how people's enjoyment of Rogue One related to their overall level of nerdiness, specifically their level of Star Wars nerdiness. The theory goes like this: I think that the graph of enjoyment vs Star Wars nerdiness has two peaks, one on the low end, and one on the high end, with a substantial dip in between.

If you only know the Star Wars films a little bit, or just aren't that much of nerd, in general, Rogue One is a pretty serviceable Sci-Fi action adventure, with some shootouts, some chases, and some amazing visual effects. If you're a super-fan, you get all of that, AND a truly prodigious number of cameos, offhand references, and call-outs to just about every Star Wars movie or TV series, from the original trilogy, to the prequels, to The Force Awakens, to Rogue One  to Rebels. I wouldn't be surprised if there's a reference to the Star Wars Christmas Special hidden in there somewhere.

In the middle, we run into the unfortunate people who just really liked the original 3 films (and maybe The Force Awakens), and are headed into Rogue One expecting more of the same I expect these people to come out a little disappointed with Rogue One, because it's really quite different from the original Star Wars movies. This is, I believe, intentional, and brilliant in its own way, but it's definitely going to turn some people off.

Here are some of the ways in which Rogue One carves out new territory in the Star Wars universe, and some of my favorite bits of clever film-making in it.





SPOILERS START HERE!!!!





Mirrors and reflections

We all remember how the original Star Wars started, I hope. There's the opening text crawl, and then we jump right into the action. A small space ship, fleeing under heavy fire, retreats into the background, and then their pursuer comes into view - a mind-bogglingly-massive grey wedge of death, the Super Star Destroyer.

Roque One has no text crawl, but it does open on a scene in space, relatively peaceful, or so it seems. And then a great grey wedge starts to intrude into the scene. For just a fraction of a moment, your brain says "Oh, it's one of those giant Imperial ships", but then you realize it just doesn't look right, and the camera tilts and pans, revealing that you're looking at the edge of a planetary ring. As you're settling in, waiting to see what happens, a small ship (an Imperial shuttle, this time) crosses the frame, and heads into the background. Where as in Star Wars, we're immediately ready to cheer on the rebels, in this scene, we don't yet know what to think of this spaceship, heading alone down to land on the planet. It's obviously not good news for the locals, though...

So, there's an obvious echo here between the original and the prequel. There's just enough similarity to trip you up if you think you know what you're about to see. It's a bit like watching the original Star Wars through a blurry lens, or in a fun-house mirror. Rogue One does a lot of this.

It's in the nature of sequels, and even more so in the nature of prequels, to be defined to some extent by how they fit together with, and how they differ from, the original film. It's a bit like how people who have a twin will often grow up to define themselves in terms of their differences from their sibling.

As an immediate prequel to the original movie, Rogue One basically ends right where Star Wars begins. This single moment becomes the mirror in which the original Star Wars is reflected both back in time and backwards in outlook.

When The Empire Strikes Back was released, Star Wars was re-titled as Star Wars: A New Hope. What comes before hope? Despair. Rogue One's story picks up at probably the lowest point of the Rebellion agains the Empire. The rebels can't decide on strategy, they've lost control over some of their own best operatives, and now they've learned of a super-weapon, the Death Star, which has been created specifically to crush the rebellion once and for all.

It's very dark in here

Some people have called Rogue One a "dark" film, and that's true on all sorts of different levels. First off, it's actually literally dark in places where the original is light, and vice-versa. Tatooine, the location of most of the beginning of Star Wars, is a blindingly-bright, glaring white sand desert. The first location we visit in Rogue One is a black sand beach, with clouds overhead. It's literally exactly the opposite of Tatooine.

When we first see the main bad guy (Darth Vader) in Star Wars, he's in a black outfit, surrounded by foot soldiers wearing white armor. In Rogue One, the main villain appears wearing a white outfit, accompanied by a squad of stormtroopers in black armor.

This is a fairly subtle bit of film-making, but I think it's brilliant. It could have easily gone some other way, with Orson Krennic, the weapons director, wearing any of the other Imperial uniforms we've seen before, and accompanied by the traditional white-armored Storm Troopers. But it's subtly "off", and sets up the expectation that this movie is not going to follow the familiar conventions and story arcs of the series.

War is hell, and hell is the Middle East (or Jedha)

Somewhat ironically, for a series of films called "Star Wars", the previous films never really touched on the chaos, terror, and moral grey areas of fighting a war. Rogue One finally does that, in a big way. There has been a lot of talk about the "it's a war movie" aspect of the film, with critics comparing it to WWII movies or Vietnam movies. There are obvious parallels there, but this also feels to me like a war movie with its roots in Afghanistan and Syria, a throughly-modern take on the nature of fighting a war.

There's a scene where a group of rebels ambush an Imperial patrol, disabling their armored vehicle and killing the stormtroopers. It's the first real fighting we see in the movie, and it's important for setting the tone of the "rebellion on the ground", as opposed to the "rebellion in theory" that we're introduced to when Jyn meets Mon Mothma and the rest of the Rebel leadership after being rescued from imperial custody.

The whole sequence is just fraught with references to recent middle eastern conflicts. There's the tank ambush itself, which feels like a reference to 1988's The Beast, a film about the Soviet invasion of Afghanistan. Then there are the rebels hiding in caves outside the city proper, a definite nod the the Mujahideen of Afghanistan, as well as the later Al-Qaeda in Pakistan.

The war machines of the Empire are literally powered by the ancient religious treasures of the local population, a reference to both ISIL's destruction of historic sites, and their use of captured oil production infrastructure to finance their war against the governments of the region.

In the middle of the chaos of the tank battle, the nominally-heroic Captain Cassian shoots one of the local rebels, in order to keep Jyn safe. He doesn't even hesitate, he just does it. That kind of divided loyalty is the very essence of modern coalition warfare.

In the end, the Empire solves their rebel "problem" by blasting the entire city from space, with a "precision" shot from the Death Star. Just like the "smart bombs" used in recent real-world conflicts, the single-reactor shot from the Death Star does far less damage than the Empire is easily capable of, but it still causes massive amounts of "collateral damage". It's a very Apocalypse Now, "We had to destroy the village in order to save it" moment.

And speaking of Apocalypse Now, what about Saw Gerrera? Here's a high-ranking Rebel commander, who's gone off the grid on Jedha, commanding his own personal band of fanatics in a mountain stronghold, leading guerrilla attacks on the Imperial troops, in a way that the "official" rebellion leadership does't approve of. The Rebel leadership dispatches an intelligence officer / field agent to track Gerrerra down, but because this film doesn't perfectly copy any of its inspirations, Captain Caspian isn't ordered to kill Gerrerra, but instead is supposed to use him to find Galen Erso, who he is ordered (secretly) to kill.

You call these people "heroes"?

We've got Galen Erso, a collaborator, complete with the classic "If I didn't do it, they'd just get someone else to" excuse. He tries to sabotage the Empire's war machine form the inside, perhaps in guilt over what he's helped to build. In the end, this man, who nobody in the rebellion will even remember, is in fact the only reason the Empire didn't manage to totally destroy the Rebellion, one planet at a time.

Saw Gerrera, an insane ex-rebel, who's decided to fight the war on his own terms. Bodhi Rook, the Imperial shuttle pilot, defects on Galen Erso's orders. He's supposed to take the news of the Death Star's weakness to the rebellion. Unfortunately, Erso sends him to Gerrera, not knowing that his former friend has gone off the deep end. Gerrera's men blindfold Rook, in a scene that echoes the CIA's "extraordinary rendition" program, and deliver him to Gerrara, who tortures Rook, just to be sure of the truth of the message from his former friend. After torturing him, Gerrera just discards Rook, even though we later learn that it would take very little actual effort to help him recover from his experience.

Let's hear it for Captain Cassian. He's the anti- Han Solo. Instead of being a smuggler who reluctantly gets pulled into the rebellion, he's a Special Ops soldier who's engaged in all sorts of dirty tactics for the rebellion, a man who's so completely bought in to the cause, that's he's perfectly happy to lie to everybody who's working with him, and accept a mission to use a young woman to get to her father, then assassinate him. When he finally has that moment of clarity, and realizes that he can't just execute Erso in cold blood, it actually feels like it means something.

And then there's the hero/viewpoint character, Jyn. She's an orphan, of course (what is it with orphans in Star Wars?), but instead of secretly being the child of the big bad guy, who's been raised by the rebels until she can challenge her parent and save the galaxy, she's...basically a nobody. Her father's kind of important to the Death Star project, but I'd bet that other than his boss (who has a much higher opinion of his skills than even Erso does), nobody in the Imperial hierarchy has even heard of him.

Miscellaneous cool bits

Darth Vader is back, and he's completely terrifying. The scene in Vader's castle establishes the quiet menace with which Vader keeps the Empire under tight control. And the scene at the end of Rogue One, where he's in full-on psycho killer mode, stabbing rebel soldiers left and right, slicing through bulkheads? That's the Vader we know from the end of The Empire Strikes Back, and from the climactic lightsaber duel at the end of Return of The Jedi - a dark Jedi who's perfectly willing to give in to his hate, to his savage bloodlust, and use that power to beat down whatever gets in his way. Also a great call-out to The Force Awakens' Kylo Ren, who has those same emotional tendencies, without the control to go with it.

I love everything about Chirrut Îmwe, the blind monastic warrior. He's not a Jedi Knight, but he's everything that we loved about Ben Kenobi from the original, and he finally puts the "Midichlorian" nonsense from the prequels to rest for good. The Force isn't a bacterial infection, it's a mystical connection between every living thing, and if you believe, if you give yourself over to it, you can achieve amazing things.

One subtle bit that I loved was his reciting his mantra, walking utterly unharmed through a killing field of covering fire, right up to the control console for the communication relay...and then totally fumbling for the switch. Because of course, he can't just see the switch - he's blind. He can "see" all of the soldiers via the Force, he can get all of them to miss him (or maybe not shoot in his particular direction?), but the switch is just a dead metal lever - it can't be easily seen or influenced through the Force.

Alan Tudyk plays K-2SO, who's a sarcastic pilot who dies on the final mission to try to "get the signal out". That one's a bit heavy-handed by Rogue One standards, but I loved Firefly, so I'll let that one slide.

And this is now two Star Wars films in a row with a female lead, and a major secondary male character, who don't fall in love, but do develop a strong friendship through their adventures. I get really sick of the idea that every movie needs to have a romantic sub-plot, and I'm glad to see the idea of platonic friendships between men and women being treated as just as relevant as romantic entanglements.

Monday, February 22, 2016

Apple vs the FBI

What's up with Apple and the FBI?

Several of my friends and family have asked me about this case, which has been in the news a lot recently. A whole lot of news stories have been written trying more-or-less successfully to explain what's going on here, often with ill-fitting analogies to locks and keys, and it seems like a lot of people (including some of our presidential candidates) are just as confused about what's going on now as they were when the whole thing started. The Wired article above is really very good, but it's long, fairly-technical, and doesn't cover the non-technical side of things particularly well.

So, since y'all asked, here are some of my thoughts on the case. I'm going to be kind of all over the map here, because I've gotten questions about the moral side of things as well as the technical. I'm going to mostly skip over the legal side of things (because I'm unqualified to comment), except for a couple of specific points.

On the off-chance that someone stumbles across this who doesn't already know who I am, I'm a computer programmer, and I have worked on encryption and digital security software for a number of different companies, including 3 of the 5 largest PC manufacturers.

I'm going to try to stay away from using any analogies, and just explain the actual technology involved as simply as I can, since I know you can handle a bit of jargon, and the analogy-slinging I see on Facebook isn't making things any clearer for people, as far as I can see. There will be links to Wikipedia articles in here. You don't need to read them, but they are there in case you want to read more about those subjects.

First, a very quick run-down of what this is all about:
  • The FBI has an iPhone that was used by Syed Rizwan Farook, one of the shooters in the San Bernardino shootings last December.
  • The phone is locked (of course), and the FBI wants Apple to help them unlock it, and in fact has a court order requiring Apple to do so.
  • Apple is refusing to do what the FBI wants, for some fairly-complicated reasons.
  • A whole lot of people, including information security experts, law experts, and politicians, have weighed in on how they think this should go.

So, what's my take on all this?

Encryption does not work the way you might think it does, from watching movies or TV.


In the movies, you always see "hackers" running some piece of software that puts up a progress bar, and the software makes gradual progress over the course of seconds or minutes, until the encryption is "broken", and the spy gets access to the data they need. In the real world, unless the encryption implementation is fundamentally-broken by design, the only way to break in is by trying every possible key (we call this a "brute force attack"), and there are an enormous number of possible keys. You could get in with the very first key you try, or you might end up checking every possible key before you find the right one. Nothing about this process gives you any information about whether you're "close" to getting the right key, or whether you've still got billions of keys to try.

The data on the iPhone is encrypted with a key long enough that trying to decrypt it through brute force is essentially impossible.

The data on the iPhone is encrypted using AES, the Advanced Encryption Standard, which was developed by the US government for companies like Apple to use to secure data for their customers. as far as anybody knows, brute-force is the only way to attack AES, and with a 256-bit key (as is used on the iPhone), it'd take literally billions of years to try every possible key, if you used all of the computing power in the world.

Apple doesn't have that key to hand it over to the FBI

The key used to encrypt data on the iPhone is derived from a combination of a device-specific key, and the pass-code which the user has set on the phone. There's no way to extract the device-specific key from the phone, and there's no record of which phone uses which device-specific key. This is done on purpose, because if you could get that data, it'd make it much easier for anyone to extract your personal data from your phone.

Given that you can't get the device-specific key, then even if all of the data was extracted from the phone, you'd be faced with performing a brute-force attack on the encryption (which is impossible, see above).

You don't need the device-specific key if you can guess the pass-code to the phone

Obviously, if the phone has a 4-digit pass-code, you only need to try 1,000 10,000 different codes in order to unlock it (0000-9999). You could sit an FBI intern down in a cubicle with the phone, and a day or so later, it'd be unlocked. That'd be a really boring shift for them, but you could still do it. If the phone has a 6-digit lock code, that becomes substantially less-convenient, and you're into the range of a full-time job for a year or more.

But you might not be able to do that either, depending on the phone's settings. One of the security settings you can set on the iPhone is for it to erase the data on the phone after 10 incorrect password attempts. The FBI seems to think that this option is enabled for Farook's iPhone.

Here's what the FBI says that they want Apple to do

The FBI wants Apple to produce a custom version of iOS (the iPhone software), and load it onto Farook's iPhone, to enable them to quickly try all of the possible pass-codes.

This custom software would:

  1. Disable the "erase after 10 incorrect codes are entered" feature (of course)
  2. Allow the FBI to feed possible pass-codes to the iPhone from a connected computer, rather than requiring some poor intern to enter each one by hand.
  3. Reduce the amount of time required between entering each code, so they can check them faster. That wouldn't matter if there was a 4-digit code set, so maybe Farook used a longer code.


Can Apple do it?

Apparently so, or at least Apple CEO Tim Cook hasn't made the claim that they can't comply with the court order, just that they shouldn't be required to. It probably would not be that much work, actually. Items 1 and 3 up there should be trivially-easy to change, and #2 is probably not a huge amount of work for someone who's familiar with interfacing the iPhone to a PC. Somewhere between "one guy working over the weekend" and "two guys working on it for a week" is probably a reasonable guess.

Here's why Apple says that they shouldn't be forced to do this


It's a violation of their customers' privacy

Tim Cook says in his open letter that the FBI's request amounts to:
The government is asking Apple to hack our own users and undermine decades of security advancements that protect our customers — including tens of millions of American citizens — from sophisticated hackers and cybercriminals. 
Earlier models of the iPhone were much simpler for Apple to bypass the pass-code on, and they've expended substantial effort over the last few revisions to make it much harder for people to break into iPhones (and newer ones are even more-secure than the phone in this case). This is valuable protection for the individual customers' data, and has contributed in large part to reducing the number of phones stolen, since they can be locked in such a way that they can't be easily re-sold. This same cryptographic technology is also what keeps trade secret information that's stored on businesspeople's phones from being copied as a matter of course overtime they travel to any foreign country.

This is not a normal subpoena, it's a special court order

Normally, law enforcement agencies will get a court order to compel a company or individual to turn over information or physical evidence that is relevant to a particular investigation. Apple has cooperated in previous investigations (and even in this specific case) with those sorts of orders. This is something else entirely.

Using the All Writs Act, an obscure 18th-century law, the FBI is trying to force Apple to engage in an activity that they wouldn't otherwise do (and which will have a negative impact on their business and customers). The All Writs act has some significant restrictions in terms of when it can be invoked, but there's remarkably-little restriction on what a court can use it to order.

Once the FBI successfully uses the All Writs Act to force Apple to produce a custom version of iOS, they will have established a precedent where they can use it to compel Apple (or any other technology company) to take whatever actions they think might be helpful to aid any investigation they might launch. Lest you think I'm veering into conspiracy-theory territory here, consider the following:

Several statements that the FBI has made to the court and in the news are either extremely naive or deliberately misleading.

The FBI has made statements both in their court filings and in the press which are simply untrue. If it weren't for the fact that the people making these claims are actual forensics experts (or work with such experts), I'd be inclined to say that they just don't know what they're talking about. Given that they do work for the FBI, I think it's reasonable to hold them to a much higher standard of clueful-ness.

It's just for this one phone for this one investigation

I can't believe that anybody would think they could get this argument past a judge. Of course if this tool exists, the FBI (and every other police/security agency in the US and every other country in the world) will require that a this custom firmware version be loaded on whatever iPhones they might have picked up in the course of an investigation. And it'd be so much easier if they could just hold on to the firmware themselves, and apply it themselves to iPhones where they have a warrant. This isn't even a "slippery slope" argument, it's just what will obviously happen.

Several news articles have mentioned China, but really any country that has a poor human rights record would obviously misuse this tool, if it was available. In particular, the Gulf states have an atrocious record on human rights, and a track record of forcing technology companies to compromise customer security to make things easier on their state security agencies (See: Saudi Arabia and Blackberry).

There may be critical information on this phone that leads to other terrorists that Farook was in contact with.

It's very unlikely that there's actually any information on this phone that'd be useful to the FBI investigation. First off, this isn't even Farook's personal phone. It's the work phone that was issued to him by his employer, the County of San Bernardino. I mean, you can never underestimate the intelligence of criminals, but what kind of idiot would plan their attack on a county facility using their county-supplied phone?

In any case, Farook destroyed his own personal phone, as well as a laptop and several other devices, before carrying out the attack. If he went to all that trouble to destroy evidence, it seems unlikely that he just plain forgot to destroy his work phone. It's much more-likely that there was never anything remotely-incriminating on it to begin with.

Secondly, the FBI already has access to backups of that phone all the way up to 1 month before the attack. So they'd only be potentially getting information that was added to the phone in the last couple of weeks before the attack.

And finally, almost all of the relevant data you might get from that phone is already in the FBI's hands through other channels. They've already got access to the call records, emails, and other communications from that phone and Farook's other devices.

Apple can make this hack so that it only works on this one iPhone, eliminating any risk to Apple's other customers.

Well, sure, in a trivial sense. In a much more-significant sense, this is a content-free statement. In the trivial sense, Apple cannot course add extra code to this custom version of iOS so that it only works on Farook's phone. But really, they can't do that - they have to test it first, of course, so that means it has to be installable on at least two phones. And it'd obviously be trivial to change which phones it works on later, which brings us back to the original "it's only for this one phone" nonsense above.

Additionally, this runs into conflict with the requirements of the "All Writs Act", which is the justification for this order. They're not allowed to create an "undue burden" on Apple, and having Apple set up a whole new internal process for creating thousands of custom versions of iOS for every investigation in which it might be useful is not a trivial thing.

Right now, Apple needs to be very careful about which OS updates it digitally "signs", which is the process that's needed to allow the software to be installed on customers' phones. There are hundreds or maybe thousands of Apple employees who have access to the tools and the source code to make changes in iOS. But that final step of signing an update is necessarily restricted, because the key for that process allows you to say to the world "this software is approved by Apple". They're presumably quite careful with that key. You can make the argument (and people have) that digitally-signing a file is essentially the same as a physical signature, and you shouldn't be able to compel someone to sign something digitally any more than you can legally compel them to sign a physical piece of paper.

I don't know about Apple, but at one of my former employers, we kept our code-signing key, and the laptop with the software for signing our updates, physically locked up in a safe. The key was actually split into multiple parts, which were only accessible to certain people. Because if you can sign software, you can make it do anything you want. You can remove the DRM which is used to secure purchased content, steal all of a customer's personal data, anything.

There's a larger issue at stake here - the very idea of privacy is under attack

Ever since the ratification of the Bill Of Rights, there has been a back-and-forth argument in this country over the right balance between the citizen's right to privacy, and the state's need for security. Since the development of effective commercial cryptography in the late 20th century, the debate has gotten significantly more-heated.

Privacy is a basic right, guaranteed by the Bill of Rights here in the US

The 4th Amendment to the US Constitution says:
The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no Warrants shall issue, but upon probable cause, supported by Oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized.

This controls the sorts of searches that the police (FBI, etc) can perform. In particular, they need probable cause, and a court-issued warrant. Over the last few centuries, that's been dialed back a bit, and US citizens are routinely searched without a warrant, and without probable cause. But there are still limits, and if you, your home, or your stuff is unreasonably-searched, you can contest that in court (and you might even win).

When the constitution was written, the founding fathers could not have imagined the sort of surveillance technology we have today.

In 1789, if you wanted to have a private conversation with a friend or family member, you could take them aside into a room, or go for a walk in the woods, and if you couldn't see anybody else, chances are nobody would overhear what you had to say. With a wax seal on your mail, you could see whether it had been tampered with (or read by someone else) in transit.

Modern communication systems (email, telephone, chat) are much easier to listen in on, and when new technology comes along, it has typically taken a while for the Supreme Court to come to the conclusion that whatever new-fangled communication system you use, it's essentially the same as a letter, for legal purposes. Tapping phone lines without a warrant used to be totally legal. Same with intercepting email and other electronic communications.

The question of whether or not you can be compelled to unlock your own phone, even if it contains potentially-incriminating evidence, is possibly still open, despite the fact that that seems like an obvious violation of the 5th Amendment.

Strong encryption flips the balance of privacy back to the way things were in the 18th century

When you have access to strong encryption, you have privacy by default. This is as it should be. Until the early 1990s, most encryption that was available commercially was just terrible. Since the development of the World Wide Web, the level of sophistication of the cryptography available to individuals and commercial users has vastly improved.

The US government has fought the availability of effective encryption for decades

After World War II, a war which the Allies won in part due to their ability to decrypt German secret messages, the US government set up the NSA to ensure that they had a lead in cryptographic technology. And until the growth of academic cryptographic research in the 1980s and 1990s, their expertise was unmatched. The NSA has a weird double mission. On the one hand, they're supposed to protect US military and civilian communications from foreign spies. On the other side, they're supposed to develop ways to break encryption used by other organizations, to support US intelligence-gathering. When it comes to commercial encryption, these goals are directly in conflict.

When the first truly effective encryption systems began to become commercially available, the NSA tried to keep their ability to listen in on communications by restricting the length of keys that could be used in software that was being exported. Eventually, it became obvious that that was only going to disadvantage US software makers, and the restriction was lifted.

During the Clinton administration, the NSA proposed Clipper, a cryptography system that would make it easy for law enforcement to listen in on communications (with a warrant, at least in principle), but would be very difficult for foreign governments, hackers, and others to break. It turned out to have a number of fundamental flaws, and was pretty quickly killed.

More-recently, the NSA has been possibly caught inserting a flaw into a security standard that they helped develop.

Law enforcement and security agencies now have much greater ability to collect data that's not specifically protected with encryption

Despite better security of communications overall, the security apparatus has continued to press the boundaries of what information they can gather without a proper warrant. Here are a few recent(wish) examples.

The FISA court

In order to allow allow Federal law enforcement and intelligence agencies to obtain search warrants, without having to publicly disclose what they're searching for, and who they're searching, Congress created a parallel court system, the Federal Intelligence Surveillance Court. This court provides search warrants, and has been involved in issuing court orders to compel commercial companies to cooperate with the NSA in collecting data, including information on US citizens, which the NSA is explicitly barred from collecting.

Telephone metadata collection

The NSA has been, for many years, collecting telephone meta-data (who's calling whom) for essentially all telephone call placed inside the United States (and several other countries). This only came to light because of Edward Snowden's whistle-blowing, because of course they got the authority for that from the secret FISA court.

StingRay

The StingRay system is basically a "fake" cell tower that broadcasts a signal that causes every mobile phone within range to report its location. They can be used to track the location of mobile-phone users in bulk, and can also apparently be used to intercept calls. These systems have been provided to local police forces via grants from the Department of Homeland Security, and they're used in a variety of ways that are at best quasi-legal (in that they haven't been specifically declared illegal yet).

Automated number plate readers

These machines are just about everywhere. They're used to automatically collect tolls, the police use them to search for cars that are associated with wanted criminals, repo men use them to look for cars that the owners have stopped making payments on, etc, etc. My local city has them mounted on the parking enforcement golf-carts, so they can just cruise down the street and collect the location and license plate numbers of every single car parked anywhere in the city.

And again, there's no law telling either the police or the private companies what they can or can't do with this information, so it gets used (and mis-used) for all sorts of things. The police have no need and no right to know where my car is at all times, as long as I'm actually following the parking rules.

What happens now?

I think there's a good chance that the court will make the "right" decision here, and side with Apple after considering their response. Either way, you should expect that Apple (and other manufacturers) will make additional efforts to ensure that they themselves cannot circumvent their own security systems. If the court makes the "wrong" decision, then there will be a whole lot more of these court orders issued in the near future, and that's bad news for privacy.