Question

Sorry if something similar has been asked before. I'll try and be specific as possible.

I'm working on a quiz/study flash card application in c#. That would allow a user to create a number of study cards for self assessment. I would like the user to have the ability to create different types of card i.e. one where there is just a question and the answer, say both held as strings, one where there is a question and then multiple choices of answer and one where these is a phrase with words missing. Ideally I'd like to leave this open to extension later e.g. I might want to add a question that consists of a diagram or image where the missing words were labels that needed to be supplied.

Designing each of these things individually is probably do-able. Where I'm stuck is knowing how to design this in such a way that the user can attempt to take the test and the system can loop through the cards in such a way that the next card the user is presented with is any random one from the set and can be any one of the types I've mentioned below. I could define some sort of common interface say ICard and iterate through a collection of that type but am I always going to have to actually know what type I have so I can display what's needed for that particular card to the user e.g. display the multiple choices if it's a multiple choice type of card. Something about that kind of design doesn't seem quite right but I'm not sure of what other approach to take.

Thanks

Was it helpful?

Solution

Use ICard for the general card and some other interface for each type of card.

class MyCard: IMyCard, ICard 
{ ... }

Loop through using ICard and when you get to the rendering part use

if(object is IMyCard)
    renderIMyCard();

To determine which specific type of card you are working with. Strictly speaking, you don't really need to use an interface for each of the types but using an interface will make the code easier to Unit test if you do.

The other way you might go about this is to just embed the type of card in ICard as an enum property. But I think the interface method will serve you better in the long run.

OTHER TIPS

Define model classes for each type of card, with a common base interface. Then, define corresponding View classes which handle rendering for those model classes. Here's an example:

Models:

interface IFlashCard { ... }

class MultipleOptionFlashCard : IFlashCard
{
    String question;
    List<String> answerOptions;
    // etc.
}

Views

interface IFlashCardView
{
    render();
}

class MultipleOptionFlashCardView : IFlashCardView
{
    public void render()
    {
        // show textbox for question
        // show radio buttons for answer options
    }
}

Finally in the render phase,

IFlashCard flashCard = getNextFlashCard();
IFlashCardView flashCardView = mapModelToView(flashCard);
flashCardView.render();

where you map the model to the view in any number of ways, such as:

IFlashCardView mapModelToView(IFlashCard card)
{
    if (card is MultipleOptionFlashCard)
    {
        return new MultipleOptionFlashCardView(card);
    }
    else ...
}

If you are using WPF, you can define a DataTemplate to directly map a model class to a set of controls, so this process becomes simpler and DRYer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top