Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm designing a flexible Wizard system that presents a number of screens to complete a task. Some screens may need to be skipped based on answers to prompts on one or more previous screens.

The conditions to skip a given screen need to be editable by a non-technical user via a UI. Multiple conditions need only be combined with and.

I have an initial design in mind, but it feels inelegant. I wonder if there's a better way to approach this class of problem.

Initial Design

UI

UI Mockup

where

The first column allows the user to select a question from a previous screen.

The second column allows the user to select an operator applicable to the type of question asked.

The third column allows the user to enter one or more values depending on the selected operator.

Object Model

public enum Operations { ... }
public class Condition
{
    int QuestionId { get; set; }
    Operations Operation { get; set; }
    List<object> Parameters { get; private set; }
}

List<Condition> pageSkipConditions;

Controller Logic

bool allConditionsTrue = pageSkipConditions.Count > 0;
foreach (Condition c in pageSkipConditions)
{
    allConditionsTrue &= Evaluate(previousAnswers, c);
} 

// ...

private bool Evaluate(List<Answers> previousAnswers, Condition c)
{
    switch (c.Operation)
    {
        case Operations.StartsWith:
            // logic for this operation
        // etc.
    }
}
share|improve this question

2 Answers 2

up vote 3 down vote accepted

Well, there's a formal pattern from Fowler that describes what you're doing right here. I've used it to design wizards that had branches as well (though I remember his decsription/documentation of that pattern being much better).

That said, if you take a step back and really look at what you're describing... it looks remarkably like a state machine. Those are well documented in many many places but they come in different flavours through implementation details. Most notable of those:

  • central control ie. some class manages the state transition logic (this looks similar to what you've designed already)
  • distributed control ie. each state knows of the transitions that leave it, and calls a state change on the parent whose state they implement
share|improve this answer
    
Calling this problem a state machine is overly general. IMO - if the OP simply wants the functionality described, he doesn't need a full featured state machine, what he has is simple enough. Sure, a state machine can be fitted to this, but so can a rules engine, neither of which may be necessary based on this simple logic. –  spinning_plate Jul 12 '12 at 6:28

One improvement:

Simply have a method in Condition.evaluate(List<Answers> previous) and implement the logic there, since it should be invariant. Scratches the switch statement.

Another comment: You might want to consider allowing multiple conditions per question ID. in the current model you'll have trouble jumping to different questions based on criteria (i.e., jump to 34 if I enter <4, jump to 92 otherwise, etc). You might also want to consider having conditions be part of Question or some mediating object (QuestionConditions or what have you)

Otherwise looks good to me, writing wizards sucks, keep it at simple as possible.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.