Thinking about the problem domain, Trevor, Sebastian, and I decided to abstract away the complexity. The problem (as I understood it then) can be explained thusly:
Students need a way to follow a list of scheduled tasks throughout the day, to assist them in performing daily activities. These tasks can be broken into more detailed tasks with steps or choices. A choice, such as what to have for lunch, is non-linear. A choice helps a student develop his sense of independence. Each choice and task may have accompanying text and audio.
Day to day within a week, the schedule of tasks may be different. Weeks can also differ from each other.
Given these simple business requirements, we decided that a step, a task, and a choice were all the same in that they had a name, audio content, text content, and that they had a parent-child relationship with each other. We decided that all of these would be “tasks” and that there would be a “task type” field to differentiate between these. The “task” paradigm yields the following definitions:
- A task is a task with linear/sequential sub-tasks
- A step is a task with no sub-tasks
- A choice is a task with non-linear, non-sequential sub-tasks
We also decided, after further discussion to make certain other things tasks. We thought that days and weeks were similar enough to a task in the parent-child relationship. We decided that
- A day is a task with linear/sequential sub-tasks whose name is a weekday
- A week is a task with day sub-tasks (days as defined above)
This allowed us to have a single Task model, and a Task Parent model, which greatly simplified the API. Instead of making REST calls to create a step, create a week, or create a choice, there would be just one create call, with a task type defining the behavior of the task. This would also make copying tasks and task trees easier, since we would only have to work with one model when doing a deep copy of a task tree.
Although this made the API really quick to build, when I started writing the builder code, interacting with the API, I found the API to be a bit low level. For example, I would have to make two calls to bind a new task to a user. First, I would have to create the task via the API, and then create the user-task relationship via the API. As I was writing nested callbacks with the jQuery ajax functions, I questioned our decision to make the API so simple. Still, I think the API is a thing of beauty, and I am still proud of what we did that weekend.