I recently built Schedgy, a lightweight calendaring application, for scheduling support shifts at FreshBooks. Schedgy allows our support scheduler to drag and drop employees onto the days of a month, indicating the shifts they will be working.
I am going to use Schedgy to frame the conversation.
For Schedgy, I built the following model:
The actual Calendar object — contains Day instances, and encapsulates the logic for flipping between months.
The days of the month. A calendar maintains a reference to many of these. A day maintains a list of many Users, representing people assigned to a support shift on a given day.
Represents an employee at FreshBooks — it has their email, their first name, their last name, and various other instance variables. There is one underlying user object for a given employee, which can be referenced by multiple days.
How many people do we need on support on a given day? Do we need at least one developer? This object encapsulates this logic. DayRequirements objects are attached to days.
Here’s what the code ended up looking like:
2. Use MVC
This is fragile.
People accustomed to frameworks like Rails are familiar with using an MVC design pattern to avoid this on the server-side, similar methodologies should be applied on the client-side.
I have two hammers that I like to use for this:
1) For large, dynamically generated, chunks of HTML, I use JSON Template to abstract rendering away from my core models. In Schedgy I use JSON Template for dynamically generated elements, such as the HTML snippet for a user being assigned to a day.
Here’s an example:
2) I use jQuery’s $.data() method to attach references on UI elements back to the underlying domain models. Here’s an example of this in action, from Schedgy:
I find applying this approach helps create much cleaner code than, for instance, relying on attributes on a DOM Element to drive behaviour.
3. Unit Test
I have two tools which I use on a regular basis:
1) QUnit is a great unit testing framework, and is tailored towards usage with jQuery. Use QUnit — it runs in any web-browser, and works awesome.
2) Those familiar with RSpec might find JSSpec interesting. Under the hood, it’s a bit hacky (relying on eval() and regex to drive its DSL), but, having said this, I love using it. It makes clean readable tests.
Here’s a good example of an JSSpec specification from Endtable, a Couch ORM I have been working on:
Schedgy is open-source if you want to check it out — it works nicely for our use-case, but keep in mind it was build during a FreshBooks HackOff and the code could certainly use some love.
Let me know in the comments if you find this post useful. I wouldn’t mind writing a few more along the same line.