Herd Hound Rewrite and App Rebirth

When i started coding on Herd Hound, working 15 to 17 hours a day on average (including the day job), under a lot of pressure, and very tired all the time (no shit, right?), I’ve started with a very vague notion of what the app would look like. What I knew was that the backend would be a very simple web service providing data in JSON form, with a single URL that would return the actual user interface. The user interface would actually contain tons of business logic, and it would, in essence, be a RIA. That’s how it all started.

The next idea down the road was the tabbed UI. Each tab would be a mix of HTML, JavaScript, and CSS. I needed something that would help with switching between tabs, so I wrote the App object, which had the loadView method. It took care of loading tab contents. Next I wanted to have a method to switch between tabs, so I wrote the switchTo method. And so on and so forth.

One of the decisions that came to haunt me was the decision to go with jQuery. While it may serve as a quick start, it turns your code into spaghetti of DOM selectors and callbacks quicker than you can say ‘DOM’.

Another silly design decision was that I allowed some of the views to lock up the app. I called this ‘unsafe operations’, and the purpose was to allow these operations to be suspended and resumed in some scenarios. The idea was simple. In view code, you call App.markUnsafe(viewname), and the app would then save the view state before switching to another view, and tell all other views to come back to that view when finished. Of course, in a world where you allow views to switch to other views, instead of delegating this responsibility to the application core, this is a very bad idea. And it’s also a bad idea in general. The reason it’s such a bad idea is that this is not what you want your app to do.

Instead of asking you app to do this, then that, then something else, you should ask your app to ensure something. Instead of asking it to suspend-resume, I should have just asked it to ‘ensure that user is logged in’ for example. The latter way of thinking is much closer to writing a sane solution, than the former way, which eventually leads to weird bugs that you can’t track down.

At any rate, I’ve started the complete rewrite of the App framework. After doing a fair deal of reading, I’ve decided to go with a pattern that mimicks the way YUI works, and borrows some ideas from backbone.js (namely, context-sensitive jQuery selector), and some of my own.

The new app is divided into three layers:

  1. jQuery + plugins
  2. App code + plugins
  3. Sandboxes + modules

The App core is a single object called App. This object interfaces with jQuery to provide lower-level functionality. It takes care of stuff like logging, view switching, event handling, AJAX, DOM manipulation, creating and running sandboxes. The architecture of App is now completely pluggable. By default, App comes with nothing but event handling system and a rudimentary logger. Everything else is in plugins, including the plugin system itself. The plugin system is attached later mainly because it’s a piece of code that I wanted in a separate file for maintainability.

The plugin system is the heart of App. It loads code, manages loaded code, and dependency resolution. While it’s not a terribly complex system (by design), it does have some shortcomings. It doesn’t do combos (doesn’t know how to request combined payloads to save HTTP requests). It doesn’t need to do this for any other reasons, though. Well-behaved plugins can be loaded in any order, and even executed in any order, because they don’t do anything on their own except modify and augment the App object. The dependency system simply ensures that certain plugins are loaded when you want to load a plugin that relies on them. It doesn’t actually care about the order in which these plugins are loaded, just that they are all loaded in the end.

The sandbox is basically an object that takes care of setting up a working environment for the modules. Modules are the HTML/JavaScript/CSS mix that you will see on your screen. They are the workhorse of the app. Sandbox ensures that modules can feel right at home. It attaches itself to the sandbox root node (HTML element which belongs to the sandbox) and provides modules with tools to do its job. It also provides modules with tools for AJAX communication (interface to the App’s tools), and DOM manipulation. It also makes a central in-memory storage for different modules to exchange data in an event-driven way, and provides broadcast facilities so modules can send out messages that echo throughout the application.

The sandbox isn’t a real sandbox, in that it’s not sealing the module off. That’d be quite a feat, if i knew how to do it, but unfortunately, I don’t. So I’m just saying “this is a sandbox and you should stay in it”. Btw, sandbox itself is quite simple out of the box. It only provides with hooks for initializing and terminating modules that run in them, but nothing else. Everything else is added using the same plugin system that is used to extend the App itself. This works because sandbox is extended using the sandbox template. The template is exposed to the plugins so they can add stuff to it.

So some of you may be asking why jQuery. Well, the reason is that the JavaScript library in level 0 is supposed to take care of only 2 things: AJAX and DOM manipulation. And jQuery does this well, as admitted by most frontend programmers. I don’t have doubts about that. Everything else is pure JavaScript in my case, with maybe a few custom enhancements collected from around the Internet (and yes, I’ve heard of Underscore.js, but I prefer to modify the prototypes as it was meant to do rather than use awkward containers). Another reason is that our application is not a big one, so it certainly doesn’t need all the shiny tools provided by large frameworks. Writing my own smallish toolkit is, in my opinion, completely justified in this case.