Gàidheil is Gàidhealtachdan air an eadar-lìon

Why I left Angular for Knockout

Or, how Steve Sanderson outdid the Google geniuses

(and I’m not one given to praising anything out of Microsoft)

I’ve been working in the Digital Innovation Lab at the University of North Carolina, Chapel Hill, for over four months now, developing tools to that enable humanities scholars to produce and engage with digital resources. Our main focus is on a sophisticated WordPress plug-in called DH Press.

Our plug-in enables the administration-user to configure projects so that all kinds of information can be utilized and visualized. The main kind of visualization supported to date is geographical (base maps and overlays), although we also support transcriptions synchronized with SoundCloud recordings. I’ve worked up a “Topic Card” visualization and several others are planned.

But in order to support these new features of DH Press, I have been rewriting the “backend” of our tool, which is inserted in the WordPress administrative dashboard as a complex bundle of HTML and JavaScript. It was the first code that Joe Hope (the original programmer) wrote for DH Press, and it relies upon jQuery to manage and modify the GUI dynamically. As can be expected of beasts of this nature, it is extremely convoluted (trying to coordinate variables and HTML document elements through JavaScript and jQuery alone) and has become practically unmanageable, let alone easily extended for the kinds of new features we are planning.

It became clear to me that I needed to completely rewrite the backend using one of the new JavaScript frameworks that support data binding and the kind of Model-View-Controller separation of concerns that I’d been used to since the 1980s. After an initial bit of research I decided to go with Angular. In principle, Angular seems like a fairly ideal solution for dealing with complexity, testing, and deployment.

After three weeks of banging my head on unexpectedly reappearing walls (often recruiting another experienced programmer with some Angular experience to make sure I’d not made obvious mistakes), I decided I had no choice but to abandon Angular for some other framework. I spent an hour or so researching alternatives and decided to try Knockout.js. I’ve been delighted and productively engaged since doing so, and this blog post will explain some of the reasons why, and the contrasts I found between them for my own application.

Capacity and Compatibility

As anyone who’s used Angular knows, you have to abandon all previous experience with other frameworks if you go with Angular. That’s fine, as long as Angular does what you want, or if someone else has created a specific solution within the Angular framework. That’s not always the case, however. There is a steep learning curve for Angular, and a large number of mechanisms and terms to learn when using the framework. If you want to create something new or incorporate components of another JavaScript library within an Angular application, you need to wrap it up within an Angular package, like a directive, in a very specific way.

In contrast, the Knockout framework is lightweight and plays well with others. In fact, the very effective tutorials on the Knockout website walk you through the process of incorporating jQueryUI widgets. You can exploit jQuery when you want, and it doesn’t (necessarily) have any negative repercussions on your use of Knockout.

Learning Curves and Cleanliness

As I’ve hinted at above, Angular is a large and demanding framework. Working with some mechanisms is pretty complicated — not least directives. I spent a huge amount of time experimenting with different settings to make my directives work, not always with the best success (figuring out the various stages of compiling, linking, etc, is non-trivial). Angular effectively allows you to create new HTML tags which you can define and sprinkle through your DOM, but in order to make it work, Angular has to rewrite your DOM considerably, and I find the results very messy (lots of insertions of Angular-encoded comments), further confusing what is going on if you want to look at the DOM.

In contrast, Knockout is very easy to learn and the online tutorial walks you through the concepts in a matter of a couple of hours. Interfacing with Knockout is done with arguments passed via the data-bind attribute, which limits the invasion and obfuscation of your HTML and DOM. In contrast to Angular’s directives (as one example), creating a new bidingHandler in Knockout (to create new kinds of GUI components or styles) is extremely straightforward and easy, allowing you to integrate jQueryUI or any other library painlessly. I have found Knockout’s template feature very useful and simple, implementing most of the functionality that Angular’s directives promised but without the unnecessary complexity.

Complexity and Interdependencies

One of the justifications for using both Angular and Knockout is the promise of automatically maintaining dependencies between variables and the GUI representation of the values in those variables: data-binding. A considerable amount of the complexity of the conventional jQuery-oriented JavaScript application is due to the difficulty of synchronizing the GUI with the data models which the user interface is meant to represent. The application which I’m writing is a particularly good example of these challenges, as there are complex interdependencies between different parts of the (user-defined) data structure.

As far as I could ever make out, Angular assumes that it can figure out a lot of the interdependencies on its own, but at some point it failed to maintain those co-dependent relationships. I could not get under the hood or inform the system about those networks of relations well enough to keep it working, after a great deal of effort. That’s what finally put me off the framework, which might have been fine in other circumstances. Although I contemplated creating an example to put on JSFiddle of the problem I was having, it was impractical because unscalable complexity itself was the problem (as far as I can make out). And there were many nuances about Angular that caused me problems that were poorly documented, but I eventually tracked down on stackoverflow help pages.

Knockout, by contrast, allows me to declare my “observable” variables and arrays (those that I need to have synchronized between the data model and GUI) or even values that are computed as a function of other variables. This system, while it required a little more specificity on my part, has accurately maintained the complex web of relationships in my system. And I did very minimal head-banging as a result.

Conclusions

I’ve been able to do everything I need to do in a quite complex application with a hairy set of interdependencies, and quite rapidly, using Knockout. Knockout is easy to learn and doesn’t clutter up my webpage. Knockout allows me to be explicit about my variable interdependencies and work with me as an informed ally, rather than assuming it knows more than I do about my own application, not hiding its assumptions under the hood like Angular. It plays well with others, and allows me to easily incorporate and wrap components of other JavaScript libraries. Sorry, Google, I’m sticking with Knockout.

Not sure what you liked in Knockout but after having working with angular + typescript. I’m working with Knockout + Javascript. I want to say that I want to cry, but the good thing is that 2 weeks till the end of the contract.
What readability are you talking about?
In Knockout it is very pure. Lots of usages KO, lots of models converting to observables & back. I just opened a file which has 12Kb and it has 312 usages of “ko.”. To say that the app is coupled to that framework is to say nothing. It is VERY VERY VERY VERY COUPLED!!!
Debugging is a nightmare, if I want to have a look into a model I see observable functions with lots of crap which I don’t want to see because I want to see my model.