Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing a questiion-and-answer system that is flexible and efficient

I've been working on a dynamic question-and-answers system, but I'm having trouble creating a efficient AND flexible design for this system. I'd love to know if there's an established design pattern or any recommendations for designing this system.

What I'm trying to do

I have a set of questions. After answering them, another set of questions are shown, depending on the answers to the previous set. This repeats, until no more questions are needed.

The question answers are all boolean, multiple-choice, or numeric.

The important part is that most questions are only shown when a specific set of criteria is met, based on the previous answers.
I need the criteria to support mainly boolean logic, such as And, Or, Not, Equals, Greater Than, and Less Than.

For example, let's say I have already received answers to questions such as Age, Gender, and State.
One of the next questions is In School?, but it should ONLY be displayed if: Age < 30 AND Gender=Male AND (State = CA OR State = NY)

Has anyone heard of a similar design pattern? How would you approach this design?


Background Information

I tried Database columns

At first, we only had 3 initial questions, so we just used 3 columns to filter the second set of questions.

However, our business needs grew and we started needing more initial questions, added more columns, and put more logic within those filters.

This quickly became too rigid and cumbersome.

I tried a Logic Interpreter

Our second attempt to make the system more flexible: store the filtering logic as JavaScript, and run a JavaScript interpreter to filter the results.

This worked pretty well for flexibility, but retrieving thousands of rows from the database and interpreting the scripts was extremely inefficient and performed too poorly for production.

I tried a Hybrid

We finally combined the two approaches, and came up with something feasable.
We first filtered our list based on several hard-coded database columns, and further filtered the list with the JavaScript interpreter.

This hybrid system still has many drawbacks:

  • The logic is in 2 different systems (SQL database logic and JavaScript interpreter)
  • Interpreting the JavaScript is slow, and is probably overkill for the simple boolean logic needed
  • The system is very difficult to maintain, especially because the JavaScript logic must always be written by a developer.

I'd really like to hear suggestions on how to improve this design.

Other Info

My database is MS SQL Server, the backend is .NET C#, and the JavaScript interpreter is JINT. The UI implementation is not important, but is a AJAX enabled website used to ask and answer these questions.

like image 740
Scott Rippey Avatar asked Feb 12 '12 08:02

Scott Rippey


2 Answers

We had to do something similar in the past for a medical system and due to its complexity, we resorted to reuse the rule engine that support multi-classification decision tree. I remember that I came across a nice simple design about this and managed to dig out the link.

http://www.javaworld.com/javaworld/javatips/jw-javatip139.html?page=1

The design is loosely coupled from the data storage, so making it easy to fit into your existing solution design.

like image 84
Fadrian Sudaman Avatar answered Sep 20 '22 11:09

Fadrian Sudaman


If I understand your question correctly, it sounds like you are building a finite state machine.

Each state corresponds to a question, and based on the answer you move on to a new question. The same question might occur in several separate states.

In your example the begin state would be the question "State?", and if it the answer is "CA" we move to the next state with the question "Rent or Own?". For any answer to that question the next state will be the question "Age?" since there is no further sub-questions for the "State?"->"Rent or Own?" path.

For you db model you need a state table and a relation table between states, ie:

table states:

  • id (int)
  • question (varchar)
  • type (set[text, boolean, int])

table state_state:

  • fromState (int)
  • toState(int)
  • answerType (set[any, equals, greater, ...])
  • answer (varchar)

In your code you only need to know the current state, ask the question, make a query to state_state and compare the results to the answer given to know what the id of the next state will be and thus the next question.

If you have a lot of states with the same question you can create a questions table and relate it to state.

If you have several 'begin questions' you can either have one state machine and tie the end questions to the next 'begin question', or you could have several state machines.

like image 22
Jacob Midtgaard-Olesen Avatar answered Sep 20 '22 11:09

Jacob Midtgaard-Olesen