Search code examples
classdesign-patternsobjectpropertiesclass-design

What is the best way to model multi-part questions


I am trying to design a subclass that will contain responses to multipart questions and some logic to evaluate/act on them. For example, FoodSurvey would be a subclass of BaseSurvey

BaseSurvey
  Name
  Date
  Submit()

FoodSurvey <- BaseSurvey
  DoYouLikeIcecream
  IfSoWhatFlavour
  WouldYouLikeAFreeSample
  SendSample(flavour)
  ...

FoodSurvey could have several dozen or more questions, and I would need to valdate each answer based on others, as well as run some other processes specific to FoodSurvey (as opposed to CarSurvey) that may depend on multiple answers (ex: SendSample(rockyRoad)).

I have toyed with the idea of a Question class with a Questions collection in each Survey but this quickly started to look like a Survey 'engine' which seemed like it 1.) was overkill, 2.) was error prone and 3.) limited the logic I could use to validate answers.

Are there any accepted best practices regarding designing this type of class?

If it matters, the classes will eventually be used in an ASP.NET website or web application.


Solution

  • I like your approach of having a 'Question' class. In more detail, this model could use a type/object patter - sort of like the relationship between a type and an object. The code could look like this:

    class Question
    {
        public string Text { get; set; }
    }
    
    class QuestionAnswer
    {
        public Question Question { get; set; }
        public string Answer { get; set; }
    }
    
    interface ISurveyValidator
    {
        bool Validate(SurveyType type, IEnumerable<QuestionAnswer> answers);
    }
    
    class SurveyType
    {
        public string Name { get; set; }
    
        public IList<Question> Questions { get; set; }
    
        public ISurveyValidator Validator { get; set; }
    
        public Survey CreateSurvey(IEnumerable<QuestionAnswer> answers)
        {
            if (!this.Validator.Validate(this, answers))
                throw new Exception();
            return new Survey
            {
                Type = this,
                Date = DateTime.Now,
                Answers = answers.ToList()
            };
        }
    }
    
    class Survey
    {
        public SurveyType Type { get; set; }
        public DateTime Date { get; set; }
        public IList<QuestionAnswer> Answers { get; set; }
    }
    

    This would allow you to provide custom validation for each survey type.