Thursday, May 29, 2014

JavaScript's Final Frontier - MIDI

JavaScript has had an amazing last few years. Node.JS has taken server-side development by storm. First person shooter games are being built using HTML and JavaScript in the browser. Natural language processing and machine learning are being implemented in minimalist JavaScript libraries. It would seem like there's no area in which JavaScript isn't set blow away preconceptions about what it can't do and become a major player.

There is, however, one area in which JavaScript - or more accurately the web stack and the engines that implement it - has only made a few tentative forays.  For me this represents a final frontier; the one area where JavaScript has yet to show that it can compete with native applications. That frontier is MIDI.

I know what you're probably thinking. Cheesy video game soundtracks on your SoundBlaster sound card. Web pages with blink tags and bad music tracks on autoplay. They represent one use case where MIDI was applied outside of its original intent. MIDI was made for connecting electronic musical instruments, and it is still very much alive and well. From lighting control systems to professional recording studios to GarageBand, MIDI is a key component of arts performance and production. MIDI connects sequencers, hardware, software synthesizers and drum machines to create the music many people listen to everyday. The specification, though aging, shows no signs of going away anytime soon. It's simple and effective and well crafted.

It had to be. Of all applications, music could be the most demanding. That's because in most applications, even realtime ones, the exact timing of event processing is flexible within certain limits. Interactive web applications can tolerate latency on their network connections. 3D video games can scale down their frames per second and still provide a decent user experience. At 30 frames per second, the illusion of continuous motion is approximated. The human ear, on the other hand, is capable of detecting delays as small as 6 milliseconds. For a musican, latency of 20ms between striking a key and hearing a sound, would be a show-stopper. Accurate timing is essential for music performance and production.

There's been a lot of interest and some amazing demos of Web Audio API functionality.  The Web MIDI API, on the other hand, hasn't gotten much support.  Support for Web MIDI has landed in Chrome Canary, but that's it for now.  A few people have begun to look at the possibility of adding support for it in Firefox.  Until the Web MIDI API is widely supported, interested people will have to make due with the JazzSoft midi plugin and Chris Wilson's Web MIDI API shim.

I remain hopeful that support for this API will grow, because it will open up doors for some truly great new creative and artistic initiatives.

Wednesday, May 7, 2014

REST API Best Practices 3: Partial Updates - PATCH vs PUT

This post is a continuation of REST API Best Practices 2: HTTP and CRUD, and deals with the question of partial updates.

REST purists insist that PATCH is the only "correct" way to perform partial updates [1], but it hasn't reached "best-practice" status just yet, for a number of reasons.

Pragmatists, on the other hand, are concerned with building mobile back-ends and APIs that simply work and are easy to use, even if that means using PUT to perform partial updates [2].

The problems with using PATCH for partial updates are manifold:
  1. Support for PATCH in browsers, servers and web application frameworks is not universal. IE8, PHP, Tomcat, django, and lots of other software has missing or flaky support for it. So depending on your technology stack and users, it might not even be a valid option for you.
  2. Using the PATCH method correctly requires clients to submit a document describing the differences between the new and original documents, like a diff file, rather than a straightforward list of modified properties. This means the client has to do a lot of extra work - keep a copy of the original resource, compare it to the modified resource, create a "diff" between the two, compose some type of document showing the differences, and send it to the server. The server also has more work to apply the diff file. 
  3. There's no specification that says how the changes in the diff file should be formatted or what it should contain, exactly. The RFC simply says:
    "With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version."
    One early recommendation for using PATCH is the JSON Patch RFC [3]. Unfortunately, the spec overly complicates updating. I describe a much simpler alternative below, which works with either PATCH or PUT.

Pragmatic partial updates with PUT

Using PUT for partial updates is pretty simple, even if it doesn't conform strictly to the concept of Representational State Transfer.  So a fair number of programmers happily use it to implement partial updates on back-end mobile API servers. It's fair to say that when developing an API, a pragmatic approach that focuses on the needs of mobile client applications is completely reasonable.

Current "best practices" when using PUT for partial updates, as I see it, is this: When you PUT the update:
  1. Include the properties to be updated, with their new values
  2. Don't include properties that are not to be updated
  3. Set properties to be 'deleted' to null
The reality is that most data is going to be stored in a database that has an implicit or explicit schema that describes what sort of data your application is expecting. If you're using a relational database, this will end up being columns in your database tables, some of whose values may be null. In this scenario it makes perfect sense to "delete" properties by setting them null, since the database columns are not going to disappear in any case. And for those who use a NoSQL database, its not a stretch to delete nullified properties.

Update: This pragmatic approach to updates is used by a number of exemplary SaaS companies, including Github. It can also be used with the HTTP PATCH method, and it has now been formalized in RFC 7386 JSON Merge Patch [4].

Further reading