Saturday, January 31, 2009

The Drupal Quiz module

One of my key interests in Drupal these days is the Quiz module. As often as I can find time, I've been working on improving the module. So far, since I have inherited code maintainership, I have upgraded it to Drupal 6, released the 2.x branch, begun development on the 3.x branch, and added support for a new question type (long answer).

Right now I'm working on this crazy (in the Drupal world) idea: I'm architecting a generic object-oriented framework that should make it easy to add question types. Historically, the quiz module has only supported one type -- the so-called "multichoice" type. This one type is supposed to function as:
  • Multiple choice, single answer
  • Multiple choice, multi-answer
  • True/false
  • Personality-style multiple choice (no right/wrong answer)
The concept is interesting. Much of the logic between these four is shared. And the theory behind initial development was, apparently, that if they were so similar, they could simply all be covered by one set of functions.

This idea seemed to hold true... to a point. But as more and more feature requests come in (many of them not only reasonible requests, but features that really ought to have been in there for a long time -- like being able to skip a question), a choice has to be made:

Create a UI that is so complex that it will require training to use, or break out question types again.

I'm obviously not a fan of the first. I think the current (2.x) branch has a horribly complex process for creating tests, and the issue queue is too full of questions that shouldn't have to be asked.

I started down the second path by first implementing a new question type (rather than beginning by breaking down the multichoice module into several smaller pieces). I started by creating a long-answer question type.

What I discovered was this: Huge portions of the code were just copy-n-paste jobs from the multichoice module. (Actually, they were copy, paste, delete lots of conditionals jobs.) This got me thinking. The obvious solution for a situation like this (when you are working in an OO language) is to abstract and extend. That has long been looked at as un-drupalish, so I initially put the idea out of my mind.

But when I started attempting to add some other new features (in the afformentioned class of things that really ought to be there), I discovered that I was constantly running into roadblocks imposed by the lumping together of multiple choice types that should really be separate. And, really, the only way to separate them without cloning hundreds and hundreds of lines of code is to employ a decent OO architecture.

I've got the class model just about done. When I finish implementing it, I am estimating that it will take about two hours to create a True/False question type -- the simplest type. Other types will not take much longer. Reporting should be much easier, too. And perhaps even Views integration will take less time. That would be nice.