Try, Catch, Fail

Wednesday, September 24, 2014

Recently, I've been doing a lot of performance work on a real-time data visualization app at Netflix. This app in particular is getting event streams (via web sockets) from the Netflix cloud. These event streams are aggregated in various ways so I don't get a firehose of events via some brilliant work by my colleagues, but nonetheless, it's a lot for single-threaded browser app to process, especially when that browser app also has a rich, interactive UI.

This means that what I really need to do is spin up another thread to separate the work load between UI related concerns and I/O or data map/reduce concerns. The idea is to free the UI thread up as much as possible, so it doesn't "jank" when I'm doing things like parsing JSON that arrived on the web socket. Generally, a snapshot of this concept looks a *little* like this:

Behold: An overly simplified, off-center, and crappy diagram of two event loop threads mating in their natural habitat!

There are other things I'm doing in this area, for example using RxJS to buffer incoming pushes on the socket, setting up back-pressure handling, etc. But I'm not going to get into that stuff in this post. What I want to talk about here is web workers. Just the basics really.

How can you make a multi-threaded JavaScript app?

The first question someone might have is simple: "You're gonna to what?"

It's actually easier that it sounds. You just create a new Worker:

Then your script file will be something like this:

Pretty darn simple. If your browser supports it, you just create a new worker, and point it at a script you'd like to run in that thread. Both the worker object in the window, and the worker script's global scope have access to an `onmessage` event, and a `postMessage` method. The `postMessage` method will send a message event to the other side, which is handled by the `onmessage` event. Really, really basic.

How can I build one of these dynamically?

So then there's problem developers face for a variety of reasons. Maybe you need to create some worker on the fly because of variable conditions in your app. Maybe your JavaScript build environment makes unit testing separate, standalone scripts a PITA. Who knows? So what do you do? Well, Blob URLs to the rescue:

Easy peasy. You can take any string containing JavaScript and use it to create a worker. Just make sure you also teardown the URL when you're done:

"But dynamic workers seem less testable, Ben, you dork."

Yeah. The above example is probably going to be even harder to test, I suppose. You have this string, that's a script. Evaling that string and then testing does not at all sound appealing. At least to me. So there are a few other approaches. Here are two that I like the best:

1. Behavioral testing of the live worker

Actually spin up the worker in your test, send messages to it and check the responses. This could get sloppy because maybe your worker doesn't always send responses to things you post to it. Also async gets nutty in tests sometimes.

2. Build your worker from functions and test those

For his approach, we create functions on some testable object or in some testable space we already have access to in our tests. So in Angular it might be a service or controller, and in Ember it could be any Ember Object (Controller, a Route, Model, etc). The idea is we just add a function to it, that we're going to use to create the worker.

The idea is that you can create a function that takes a global context as an argument. The reason I'm choosing to pass it as an argument, and not as `this` via binding is simply because a lot of frameworks (JQuery and Ember for example) make a lot of use of the `this` keyword, and I want to limit confusion about what this is. It's a global scope that doesn't belong to the current class.

Once you do that, you'll be able to call the worker function, or even bits and pieces of it, depending on how you use this trick and unit test those parts along with the rest of your framework code.

For my example, I'll use a plain JS class:

To use this Muppet class it might look a little like this:

And now some tests (in a Pseudo-Jasmine style, but this will work in any testing framework):

As a side note, I've "DRY-ed" up the tests above for the terseness of this blog entry. I'm actually against DRY tests, but that's a whole other blog post I suppose. This StackOverflow answer sums up some of my feelings on that, I suppose.

Also, one goofy thing about Jasmine is the need to reset spies after they've been called once, so the code above might not exactly just "work" if you copy-pasta, because I've taken out the bits that will reset the spy. Again, for terseness.

Additional things to know about Workers

importScripts() - is a globally available function for loading other scripts into your worker. For example you could load RxJS in like so: `importScripts('http://example.com/rxjs.min.js', 'http://example.com/scripts/rxjs.async.js');`. Be aware if you're using Blob URLs you might run into issue with relative URLs in import scripts.

Workers have no document! This means any script you might want to load that requires the DOM (Ember, Angular, or D3 for example) will not load properly in your worker.

Workers, therefore have no DOM-related stuffs. You won't be able to build HTML via DOM objects and send them back to your UI thread.

You can only "postMessage" objects that can be "structured cloned": This is complicated to explain, I guess, but to keep it simple: you can send POJOs back and forth or simple struct-type class objects.

Workers can be a PITA to debug. For example: breakpoints aren't always hit, and console.log behaves differently. Therefor, I think it's a *really really* good idea to unit test your worker directly.

Go forth and enthreadify all the things!

I kid, I kid. You probably shouldn't use Workers unless you have to. But in the end, there are a LOT of ways to skin this cat. Now with the tools to convert any string containing JavaScript into a URL that can be spun up in a different thread, developers should be able to use threading in a variety of interesting, and testable(!!) ways.

There are still a lot of other things to talk about: MessageChannels, for example. But that, again would be a different blog entry. I just want to mention them so anyone reading this hopefully does some Googling.

Thursday, September 18, 2014

Recently I posted about how to handle SVG in Ember. Angular has some issues itself with SVG, and it's worth discussing here, partially because I recently contributed a lot to the effort to get SVG working in Angular.

For the most part, Angular won't have too many problems with SVG, as long as you're using attribute-style directives, and you're not creating new directives. The issues Angular has with SVG will become more apparent when you're dealing with custom directives, particularly those using custom-elements, transclusion or template strings.

Angular 1.3.0-beta.19 has first class SVG support

The short story is, if you want to use SVG with Angular, it's a good idea to use 1.3.0 beta 19. I submitted and issue, then did a late-night hack-session with Igor Minar get SVG working in Angular. The approach was basically to track namespace while Angular was traversing the DOM looking for directives during $compile. The code in that area is a little tangled because of how it uses closures to pass around transclusions, found directives, and other important pieces of information. After we had it mostly working, Tobias Bosch and Igor (and probably others on the team) went back through the code and cleaned it up, fixing a few issues we didn't find the first time.

So what about 1.2?

The current stable version is 1.2. It is my personal opinion that if you want SVG support, at this point you're better off upgrading to 1.3.0-beta.19. This is because the hacks you'd have to perform to get SVG 100% working with Angular 1.2 would be much more than the work it would take to upgrade your app, and any subsequent beta-related code breakage.

Angular's issues with SVG

The problems with SVG in Angular are the same problems found in almost any framework, with one interesting exception, cloning custom elements.

1. Parsing HTML

This happened in cases where template strings were being converted into DOM elements so they could be compiled. Parsing HTML strings was done with a wrap map that didn't support SVG elements. I went through what a wrap map is in my previous post about Ember and SVG, but as a refresher: Basically, you create a div object, then you set it's innerHTML to your HTML string, which is sandwiched between the proper tags. So if you had a string like '<td>whatever</td>', you'd create an HTMLDivElement with document.createElement, then you'd concat '<table><tbody><tr>', your string and the closing tags, then assign it to div.innerHTML. After than you'd grab the nodes from the appropriate place in the DOM tree of div.

2. Cloning custom elements

The reason this one is interesting is because Angular leverages the existing DOM as it's view, where other frameworks process templates and output DOM. This means that Angular can do efficient things like clone existing elements to create new elements. The also means that Angular is going to try to clone everything, even custom tags, exactly as they exist in the DOM. SVG 1 doesn't know what to do with custom tags. SVG 2 will treat them like <g> tags, but no browser supports SVG 2 yet, AFAIK. So what happens when you clone <my-tag><circle /></my-tag>? It clones successfully, but <my-tag> has no layout, so everything underneath it will not render. This means that all directives that are custom elements for SVG need to have `replace:true`. This is something that is true even in Angular 1.3.0 beta 19 and higher.

3. SVG validation error messages

Since Angular is using real DOM to set up it's views, that means you're liable to run into situations where you're trying to bind to an attribute in svg like `<rect x="{{x}}"/>` The problem here is you'll get error messages all over your console saying that {{x}} is an invalid value for rect (or something like that). Fortunately, there is already a fix in angular for this in the form of the `ng-attr-` binding style. That means you can do `<rect ng-attr-x="{{x}}"/>` and everything will will be fine.

Custom SVG elements in Angular 1.3.0-beta.19 and higher

There is a new `templateNamespace` property in the directive configuration object that you'll need to set, and you'll want to set `replace` to true. But other than that, it's now pretty straight forward.

Wednesday, September 17, 2014

At the time of this post, working with SVG in Ember can be a PITA to say the least. At Netflix, I'm working on an Ember application that is at least 90% SVG, and I've hit a lot, if not all, of the pain points you might have before finding this post. Hopefully someone else finds this helpful.
The issues faced in Ember with SVG are the same issues faced by most frameworks. In fact, as of right now (now meaning while I'm typing this), there are no stable versions of JavaScript "frameworks" that fully support SVG properly. Angular, Ember, React and Polymer all have some pain around handling SVG. Some of them attempt to handle it, React for example, but there are certain cases where it will still break.

First Problem - Partials getting parsed incorrectly

This happens when the root of a template is an SVG element. Ember, like JQuery, React, and in some cases Angular, use a "wrap map" technique to parse HTML strings. This essentially creates a div tag, puts your string wrapped in some other tags into the div's innerHTML, then pulls out the child nodes you required. That's a simplified version of the technique, and I can go over that in another post. The "map" comes in when trying to determine what to "wrap" the string you provided with. For example wrapping a <td> with <table><tbody><tr>.

The problem with this technique is that SVG elements, being in a different namespace than HTML elements, will not be created properly if they're not inside of an <svg> tag. And all 50 or so SVG tags are simply not in the wrap map.

Second Problem - CSS Classes not being applied properly

Under the hood Ember uses JQuery to add and remove classes from elements. The problem here is that JQuery doesn't support SVG. I could go on a rant here about how I don't like JQuery, but meh. The reason JQuery doesn't work to add and remove classes from SVG elements is that JQuery tries to do so by setting element.className to a string. In SVG, element.className is an SVGAnimatedString, and you must set baseVal to the string instead. But better still, if you're in IE8 and newer the "modern browsers" JQuery 2.x and higher purports to target, you can just use classList to add and remove classes. Alternatively, setting class via setAttribute('class', 'whatever') will also work with SVG.

The Solution (for now): 1.7.0 beta.5 with a script

Thanks to Stefan Penner, I was able to push through a PR to Ember that exposes the wrap map used in Handlebars via Ember._metamorphWrapMap. This allowed me to create a patch script that updates the wrap map with the appropriate elements for SVG. That same patch also updates JQuery's addClass and removeClass to use classList internally, which might break for really old browsers. (Also, as of right now I'm not supporting passing functions to those methods but feel free to submit a PR if you need that feature).

ember-handlebars-svg is a script I made to update the wrap map and fix class manipulation. (via bower: bower install ember-handlebars-svg)

After that everything should "just work". No other JQuery patches or anything are required unless you're trying to use JQuery for animation or something, in which case, I'd recommend ditching that and using D3. There are still a few places you could have a problem, specifically if you try to use an svg <a> tag as a root element to a template, and that's unavoidable because of the wrap map approach, but other than that, you *should* be okay. (should, haha).

The FUTURE!!!!

In short, the future of SVG in Ember looks 100% awesome. And the answer is "HTMLBars".

I've talked about this issue at length with Stefan Penner, Kris Seldan, Erik Bryn and Matthew Beale and how it's going to be solved in the future of Ember. Currently SVG in 1.8.0 with metal-views is broken again. But not to worry: HTMLBars and metal-views will allow for a more complete solution to this problem that will use namespace tracking instead of clumsy wrap maps to provide functionality to properly create elements in each namespace. This means it will work 100% of the time, where a wrap map will still have some issues (for example both HTML and SVG have an <a> tag).

Stay up to date

When it comes to the status of HTMLBars and SVG support, I'd recommend following these folks on Twitter:

Generally, when there's a new release or a big, new feature added to Ember, Tom tweets it immediately. Stef's mostly good for information regarding Ember-CLI, but the others are all involved in the development of HTMLBars and SVG support, so they're important to follow. Also, when HTMLBars is released with SVG support, I'm liable to sing it from the rooftops. ;)

Wednesday, April 30, 2014

Years ago when I was learning kung fu, my Shifu would talk about kung fu and tai chi as "two paths up the same mountain". One path was external and physical. The other path was internal and introspective. That was to say that in both kung fu and tai chi you were starting from two difference places, but you were on a journey to the same point. When you reached that point, the only logical choice was to continue down the other path.

I feel that Angular and Ember are nearing this point. And I think they're reaching it at pretty much the same time. Simply cresting the mountain isn't enough; Now it's time for both frameworks to take a trip down the other side.

It seems to me that Angular's path has been primarily driven by a desire to create a highly extensible, clean, simple, concise API, to allow developers the power and freedom to accomplish their goals. They've certainly done that. In spades. But not without some pain to those developers. With freedom comes the ability to shoot yourself in the foot and enough rope to hang yourself with.

Ember, on the other hand, chose a path of guiding developers to create software easily and safely by providing a broad set of tools, structure and rules to follow. And they have definitely succeeded. But again, not without some pain for the developers. That broad set of tools, the expected structure and all of the rules that go with them must be learned in order to master the framework, and it’s perhaps too much for some to digest.

The Angular and Ember communities are the ones pushing the web forward

All of the new features available to us in modern browsers are powerful and amazing, but it’s these two frameworks that truly enable developers to create content that leverages that power in a way that’s pushing the web forward.

It is my hope that there will be increased cooperation between these two core teams, so that they can create something more perfect than they each already have. It certainly seems possible. There are a lot of future developments in this space that both frameworks have overlapping concerns with: Web Components, Shadow DOM, ECMAScript 6 (and beyond), even the future of HTML standards.

More importantly, I hope to see more interaction between the Angular and Ember communities (meaning you, dear reader) in general. Sharing techniques and strategies across frameworks only serves to give everyone a better understanding of web development and help these two frameworks evolve.

Maybe one day they will be one framework… Maybe one day we’ll all be Embular developers.

Constructor-based dependency injection as an obvious feature. Angular forces a constructor-based DI style that uses constructor functions with parameters. The style is carried throughout the framework and is plainly obvious to any developer that is writing code against Angular. In essence, it forces dependency injection. As an added bonus, this style of dependency declaration and injection enables Angular to detect circular dependencies at run-time.

Ember on the other hand, does not have this exact same mechanism. While you can inject your dependencies at time of creation with Ember via EmberObject.create({ deps: here }), the actual injection of those dependencies is optional. Meaning if one of those dependencies doesn't exist, it will still create the object. There also currently isn't a mechanism for circular dependency checking. The final issue related to how Ember handles the injection of dependencies is that it's not really apparent to the developer where dependencies are being "injection". The short answer: Anywhere you see this.get('something") is an entry point for a dependency. So there are multiple points where dependencies can be injected into your classes, whereas in Angular, there's one obvious point they are injected from, and it helps guide the developer towards dealing with dependencies in that manner.

Angular has a cleaner, neater API. Angular’s api revolves around a small set of primitives: controllers, service providers, directives, and filters. Along with a uniform DI syntax, these primitives allow Angular to be learned quickly and easily by new developers. Angular gives you a powerful set of tools, and then gets out of your way.

In contrast, Ember’s API has a broad surface area. There are many different types of controllers and other Ember primitives and it’s really hard to tell what you should and shouldn’t worry about using when you’re first starting out. Combine this with an API that isn’t always easy to read and it can be difficult for a developer new to Ember to figure out what’s really happening. For example: App.FooController = Ember.Controller.extend({ foo: 'bar' }) to create a controller, while fairly terse, doesn't make any sense to someone from outside Ember. It reads like "set App.FooController equal to Ember.Controller, and extend Ember.Controller with this object literal I'm giving you were foo is set to 'bar'".... When I first saw this format I was thinking, "What am I extending? Is this like $.extend? If so, why am I extending this Controller object over and over again?" By that token, angular.controller('FooCtrl', function($scope) { $scope.foo = 'bar'; }); just reads more fluently. "Angular, create a controller, named FooCtrl, it needs $scope, and it should put 'bar' on foo on scope".

Even computed properties, one of Ember's better features, don't read easy on the eyes to new developers. excitedFoo: function() { return this.get('foo') + '!!!'; }.property('foo') ... Anyone new is going to be like "What the hell is this property method on this anonymous function? Where did that come from? How do I call this new function?"

Handlebars is ugly. There I said it. It's ugly. <div {{bind-attr thing="this" blah="that"}}></div> Is just plain ugly compared to dealing with Angular's templating... which is just plain HTML. That said, however, HTMLBars is coming, and it will completely change all of that and *should* level that part of the playing field.

Angular can stand alone. Angular doesn't require any additional libraries to to function. Ember on the other hand, requires JQuery and Handlebars to function. Which only adds to Ember's already fairly immense download size. Generally speaking though, this is not a big deal. Once it's downloaded, it's downloaded. But it's worth mentioning because some people do care about this, for whatever reason.

Angular is a lot more lightweight. Let's compare the two current production versions: Angular 1.2.16 (104K min / 37K gzip) vs Ember 1.5.1 (277K min / 75K gzip) is almost half the size gzipped, and almost a third the size if your server admin forgets to enable gzip compression on your web server. And to be clear, that doesn't include the other two files that Ember requires: JQuery 2.0.1 (81K min / 28K gzip) and Handlebars 1.3.0 (43K min / 13K gzip). Those bring the required download to spin up an Ember app to around (401K gzip / 116K gzip) versus (104K / 37K) for Angular. For added fairness we'll include Angular's routing module (4K min / 2K gzip), but that's hardly going to make a difference. But this probably isn't a big deal. This particular concern is really only a concern the first time a user hits a page, because all of these files should be cached after that. Still, some people look at file size and might not like what they find.

Angular has a lot to learn from Ember. I think the ease of use in Angular and it's wide spread popularity may have gotten the idea into the community's head that it's "the best", but that's simply not the case.

Ember's use of convention over configuration. Angular allows developers to follow whatever convention they choose, which sounds like freedom to some, but on a large team it's more chaos than anything. Inconsistent names are a pet peeve at best, and a debugging nightmare at worst. For example a developer could name a controller "FooCtrl", "FooController", or "fooControllerer" or "fooServiceThing"... all legal names, none of them consistent. In fairness, Angular does provide a style guide, but in my experience getting people to follow a convention is a lot easier when a framework enforces and rewards the behavior.

Ember doesn't allow logic in templates. Angular, on the other hand does, via "expressions". These expressions are not quite "Turing-Complete" on their own, but they are very, very close. Expressions in templates are dangerous because they're harder to test. They also move what should have been a concern of your controller into your view. Angular's expression parsing engine is extremely impressive. It really is. Anyone that loves JavaScript should just go look at it, it's lexing pseudo-JS into tokens and parsing into a function that can be called against any JS object, usually scope. The problem with expressions is that they've allowed developers to put way, way too much logic into the templates, which makes that logic harder to test, and impossible to test in isolation. For example ng-bind="someVar + 'some string' + dangerZone('!!!')" or maybe something like: ng-click="foo = 'bar'; blah(foo + bar + '!!!); shazbot = nanoo && nanoo" ... that's totally legal in Angular, and completely insane. Ember does not allow this, you can bind to properties, calculated properties, or in the case of events, actions on the controller; All of which are easily tested in isolation.

Robust routing. As I've stated above, Ember's routing is flat out the best I've seen. The third-party ui-router for Angular comes close, but in the end, it's just a pale replica of what Ember has done, as best I can tell. That's not to belittle ui-router at all, it's a fine piece of code craftsmanship, but Ember has spent more time so far refining routing, and it shows. ngRoute, which is the Angular core offering doesn't even compare, and if it has a "best feature" it's simply that it's not included with Angular by default any longer.

Wire up more for the developer. I realize this might not be a goal the Angular team has, but in the end, Ember has solved the problem of "how can we help the developer" much better when it comes to wiring things up. In the case of routing, as mentioned in my previous article, when you setup a route in Ember and you simply give it a name, it will automatically know where to look for that route’s controller, model and template, as well set up the path it’s looking for.

That’s not really the end of it though, Ember also has a {{link-to}} helper that allows the developer to create a link to a page, by route name, and also pass a model to that route via the link {{link-to “foobar” shazbot}} will take whatever value (object or otherwise) is in the current controller’s `shazbot` property, as pass it as a parameter to the route, which carries over into the controller as a property.

Ember also has a feature which enables very simple two-way binding to query parameters. Basically, this means when a query parameter such as `#/routePath?foo=bar` becomes `#/routePath?foo=wee` then a property `foo` on the current controller will update from `”bar”` to `”wee”. Likewise, if you update the controller property `foo` to be something else, it will reflect it in the query param in the url bar.

Inheritance and mixins. Ember allows the developer to create a controller, or a component, or a route, or anything really, and then create subclasses of any of those things through basic inheritance. This is a very powerful tool. Combine that with Ember's mixins, and you've got a powerful toolset at your disposal that simply doesn't exist in Angular, at least not without some finagling

Ember also has a long list of what's great about it. It's a list that should be well known, but I feel at times that Ember fans just stink at explaining Ember's merits. Particularly to Angular fans. As I've stated above, my experience with Ember isn't as comprehensive as it is with Angular, but there are a few things about Ember that I absolutely revere and I'm excited to tell anyone who will listen:

Two way binding that doesn't allow you to write untestable code. Yeah, we've got this "two-way binding" thing in every framework these days. But where Ember shines is it forces you to write testable code. By this I mean it doesn't allow for logic in your views the way some other frameworks like Angular do. That means that everything you bind to in your view is exposed as a single, unit-testable property somewhere.

Convention over configuration. Ember uses convention to help the developer organize their code. In Ember 1.5+ this means using ES6 modules so you even know where your files are and what they're named. For example, a route named "test" would automatically look for a "test.js" file under the controllers directory, and a "test.hbs" Handlebars template under the templates directory. Likewise with files for models and the route itself. Convention over configuration means that the one stupid developer, on that other team that you hate dealing with, that always names things in stupid ways, is forced not to be a big, stupid, dumbface.

Adherence to standards. Ember developers have gone to great lengths to try to make sure Ember is moving itself, and your application's codebase towards web standards. For example, custom components are named in a convention that complies with the W3C's web components draft. Having worked with an Ember core team developer, I can tell you that their concern with future-proofing your application by trying to adhere to standards is obvious.

Ember polyfills ES5 (and ES6) functionality where it can. So if you're in a crappy browser, Array.prototype.forEach, map, reduce and filter now all work! This is in contrast to doing things like using angular.forEach, underscore/lo-dash's _.each or JQuery's $.each functions. Frankly, it's just better practice.

Extremely robust routing OOTB. Ember's routing is just flat out better than anything else I've seen out there. Better than Angular's ngRoute, better than Sammy.js, better than ui-router. It's really, really good. I've even heard rumblings that Angular might use Ember's router in the future, but that could just be gossip.

Ember solves problems and wires things up for you. What I mean by this is that in other frameworks, like Angular, you're going to have to wire quite a few things up by hand. In Ember when you add a route named ‘smith’, it’s automatically going to look for a controller either named SmithController or in the appropriate file (if you’re using Ember 1.5’s ES6 modules). This goes the same for a smith template, or a SmithRoute, etc. But none of those things are required, they’re also stubbed in for you automatically. It’s also going to look for a client-side route path “/smith”.