The Different Stacks series covers the different software and library stacks I have experimented with, and how it goes together
While we were getting ready to launch Treehouse, I was given the opportunity to build a brand new component, Code Challenges. We had already decided to incorporate badges via multiple choice quizzes in Treehouse, but then it became clear that we really needed a way to demonstrate your knowledge by actually coding. Since Alan had more than enough on his plate, and I was in search of a project, Code Challenges became my baby.
- CoffeeScript (everywhere)
- Dojo / Dijit
Now I want to explain how these components worked together in a real application.
Require.JS + Dojo + Ace Editor
The code challenge interface is a fairly complex interface with many components including tabs, a rich code editor with multiple instances , and challenge interface. All of these components need to be able to communicate effectively. There are a lot of moving parts in th application, so organizing all this code is important. One huge js file isn’t going to cut it. I decided to give require.js a try. This provided me the ability to split my code into multiple modules, with all of the dependency management handled for me.
Require.js was a great choice, particularly because my two main external libraries (Ace and Dojo) follow the same Asynchronous Module Definition pattern that require.js follows. This means instead of loading a large compiled file that includes all of the library into my app, I can require components from ace and dojo just like I would require any of my own modules.
Getting ace and dojo into my project was a bit tricky. The require.js website has a guide to using dojo with require. It really just came down to checking out the correct tag of the libraries.
This combination was nice because I don’t have any global objects to rely on from my modules, so the dependency graph is fairly easy to reason about.
CoffeeScript + Dojo
I decided to commit to using CoffeeScript throughout this project. I had experimented with CoffeeScript before, but I wanted to see how well it held up in a larger project. It’s awesome, and it changes the way you program and think about problems. One of the biggest shifts is how CoffeeScript comprehensions make map and select/filter operations easy without another library like underscore.
My favorite sugar in CoffeeScript comes from its class syntax. It is
nice because it provides a pretty familiar syntax for creating classes
implementation be pretty much the standard for prototypal inheritance.
It even implements a
super keyword that works very well.
One of the surprise benefits of the class sugar is how it easily replaced dojo’s subclassing mechanism. Most of my classes are subclasses of the various dojo widgets that override certain callbacks in the lifecycle to serve my application needs. The suggested way of subclassing in dojo is the following.
This pattern is by no means the worst implementation I’ve seen, but one
thing I don’t care for is the provide/define that will place my class
into the global repository of classes. With require, I want all my
classes to be local to the module, then specifically exported. The other
complaint is that dojo can’t name the constructor function after your
class, so when debugging, the default “class” name for an object won’t
be MyButton, but something more cryptic. CoffeeScript classes actually
produce the correctly named constructor function, so the representation
in the console or
.toString() will match the name of you class.
The CoffeeScript that would create a class is this, and it not only looks cleaner, but also addresses the scope and naming problems.
Bam! The extend keyword works without issue. Without a constructor
defined, it will automatically call the parent’s constructor when
MyButton is executed. If I want to override any methods, including the
constructor, I can do it very easily. Again the
super keyword works as
Node + Express + CouchDB
The one awesome component that I do want to talk about is CouchDB. Couch turns out to be an ideal datastore for the editor because all my queries are key/value lookups. There isn’t any real searching or complex queries. The data I need to store is pretty varied, as any given challenge template or editing session may have any number of “files” associated with it. Converting it to JSON and throwing it into the couch is about as easy as it gets.
Here’s the cool part: the server doesn’t have (almost) anything to do with the server. Couch uses HTTP to work with it, and the browser speaks HTTP, so my frontend talks directly to the database.
Due to the same domain policy of the browser, the frontend can’t talk directly to the database, but it can if the server acts as a dumb proxy to the database. The http-proxy library made this trivial to do in Node. There is a little bit of middleware that runs some basic authorization checks on the queries, but that’s it. There’s no real “API” on my server, just the API of the database exposed through a proxy.
Jade + Stylus + Handlebars
Overall I am pretty satisfied with this stack. It has been one of the most organized front-end project I have had the chance to work on. Jumping back in after several weeks away from the code has been pretty painless. It’s easy to get (re)oriented in the code.
The require.js compiler did have a few quirks that I had to work through when I was getting the app ready for launch. Most of these problems were easy to resolve, and the cost was worth the benefit to me.
What do you think? Have you used any of these technologies in your projects? What are your experiences?