Following up Jonathan's post on the
design decisions that went into
Verify, here is some of the thinking on the engineering decisions we made. Think of it as tips on going from *zero* to *one point oh* taken from our experience building Verify:
Never let engineering drive design
Don't get me wrong, engineering gets a hell of a lot of say in what gets implemented, but it should
never be driving what gets created. It's a conflict of interest really; as an engineer your primary objective is to maximize the efficiency, readability, and speed at which your code is developed. This is always at odds with the best interests of the people using your application. They want features that are easy to use, through a simple interface, that often requires complex logic behind the scenes.
As Jonathan said, we didn't write a single line of back end or JavaScript code until the entire front end interface was coded up with static HTML/CSS. Now the interface you see on Verify today has changed considerably since the first iteration, but the point was not to lock in a perfect design. The point was to think through the functionality of the entire application from the perspective of the people using it, before considering how it was going to be structured.
There is, however, one very important caveat. The design team needs to be savvy enough to know what can actually be done, and what is crazy talk. If you're designing for a medium you don't understand the limitations of, slap yourself, right now. You don't need to know how to write
object oriented JavaScript using
prototypical inheritance, but you damn well need to know that yes, JavaScript can add interactivity to websites, but no, it cannot detect if the user is currently drinking coffee.
ZURB has some pretty savvy designers. They may be
a little crazy, but they are certainty knowledgable as to what you can do on the web, and what's just
bat shit crazy. I can't stress how critical this is to a good engineer-designer relationship.
Alright, enough touchy-feely stuff, it's about to
get real.
Inheritance is your friend
Using inheritance and polymorphism isn't just for
uber-geeks. Sure, there are a lot of letters in those two words, but really it's just about code reuse. If you're using a framework that does not provide support for inheritance or some equivalent form of code reuse, you may have chosen poorly.
Verify has a lot of different tests, that all share a lot of similar functionality. So it was pretty much a slam dunk that all the tests would inherit from a generic test that includes all the shared functionality. This way when you want to create a new test, you just inherit from the generic test and already have most of what you will need. Simple right?
If you are using
Ruby on Rails (or a similar MVC framework), then you can also use inheritance in your views and controllers. For Rails specifically, the inheritance support in controllers and views is a very powerful, but seldom discussed. The details are beyond the scope of this post, but one thing we make extensive use of in Verify is removing the
helper :all line from application_controller.rb. This loads the view helpers in the same order as your inheritance tree, as opposed to just loading everything in alphabetical order.
You know, backend code is not the only place you can use inheritance.
Keep your JavaScript under control
We knew from the beginning that Verify was going to have a lot of JavaScript components, from the tests themselves to the interactive reports for viewing the test results.
jQuery is our JavaScript library of choice, for pretty much one reason:
It's readable by non-engineers. Sure, it has great doc, huge adoption, and solid performance, but mostly it's the CSS selector based selection and traversal that makes it accessible to everyone on the team.
That said, jQuery doesn't come with all the built in structure and organization that you get from Dojo or YUI. It's left up to you to determine how you are going to organize everything, and we're OK with that. We keep it pretty simple in Verify, relying on the basic
JavaScript module pattern, and a lot of message passing using custom events.
Now we could get all crazy and build the entire application with JavaScript, but we didn't, here's why.
Don't event your entire app if you don't have to
When I say
event I mean building your entire application front-end using JavaScript with the single page load (think Gmail).
SproutCore does this and can deliver some very cool interactions, however it's a very heavy framework to learn that may be overkill for what you are trying to accomplish.
For Verify we took a hybrid approach. Rather than eventing the entire application, we evented a few key portions of the site, the test taking pages, and the test report page. The technical advantage is that it take a lot less JavaScript to implement some light weight transitions between divs on the page, rather then building an entire app in the browser. You still get the advantage of super snappy response times when moving between the evented elements, but don't need to completely leave the safety of good old fashion links and page loads.
While our eventing was light, we still made sure that evented pages were linkable when applicable. For example on the report page there is a summary, demographics and raw tab. Switching between tabs is done with JavaScript, but the current tab is reflected using the
url fragment (#raw) so that the back and forward buttons, bookmarking, and copy pasting still works as they would with a regular url.
Let's review
- Don't think about implementation until you know what you are building
- Learn how to properly use inheritance on your platform of choice
- Know something about organizing your JavaScript
- Only event what you need to
Like what we did here? Think you can do better?
We're hiring a full time Rails Engineer and looking for engineering interns, hit us with your best shot.