0

I'm facing some object relationship problems in an application that, among other things, handles multiple choices exercises.

Thinking of those exercises, I can that:

1- I have several exercises, that have several questions that have several alternatives. 2- A specific question can be part of several exercises. 3- A specific alternative can NOT be part of several questions.

In terms of relationship:

Exercise < n-n > Question
Question < 1-n > Alternative

I coded the classes the way bellow:

class Exercise {
    private $id;
    private $name;
    private $questions = []; //array of ExerciseQuestion
    //...
}

class ExerciseQuestion {
    private $id;
    private $exercise = new Exercise();
    private $question = new Question();
    private $order; //handles question's order of appearance
    //...
}

class Question {
    private $id;
    private $wording;
    //...
}

class Alternative {
    private $id;
    private $question = new Question();
    private $text;
    //...
}

I don't know if I did it wright, but, instead of storing relationships ID's in classes attributes, I'm storing an instance of the related class. It seemed to be right approach when I started.

The problem I foresee is that, in the relation Exercise-ExerciseQuestion-Question, I will be thrown in a hell of circular references. I will have an Exercise that has several ExerciseQuestion that holds an instance of Exercise with a lot of ExerciseQuestion inside it. Am I right in this assumption?

Is there a better - or correct - way to express that kind of relationship? Should I change to store ID's instead of instances or can can make use of some design pattern?

yivi
  • 42,438
  • 18
  • 116
  • 138

3 Answers3

2

If I'm reading you correctly, you don't actually have a problem. If your domain includes circular or self-referencing relationships, then your models should too.

Since your objects are entities (they have identities), you'll want to take care that only one instance exists for each id. But as long as you enforce that, they can refer to each other however you need them to.

Now, circular references can be tricky to deal with if you need to traverse the object graph in some exhaustive way. In that case, you'll need to take care to not get yourself into an endless loop. But if your domain actually has these relationships, then you need to model them, and you'll have to implement some way to detect cycles and deal with them. The details will be informed by your particular needs.

timdev
  • 61,857
  • 6
  • 82
  • 92
  • Thanks for your help @timdev . I believe in this case I shouldn't have circular references, because the flow always seems to go top-down: Exercise >> ExerciseQuestions >> Question >> Alternatives. Do you have any tips on how I can improve the design, please? – Roberto Dias Dec 22 '18 at 14:47
  • If you don't need to go the other direction, you can remove ExerciseQuestion entirely. Exercises can just have an ordered array of Questions. You don't need an entity for every table in your database. – timdev Dec 24 '18 at 19:14
  • 1
    Thanks @timdev! The code looks cleaner after refactored the way you suggested. – Roberto Dias Jan 06 '19 at 21:14
0

I am not sure if i understand what you're saying but if you're asking : is that a circular reference problematic? the answer is yes an no, it's depends of what's you're going to do and how you're handling your issue. But if you are talking about your implementation the answer is definitly no it's not problematic because the class attribute does not store "an objet" but "a reference to an object" hence there is no circular construction wich lead to an infinite recursive iteration in your case Good luck

0

You have a problem in your model. A relation object should store only the ids of the parts involved in the relation, an exercise_id and a question_id, and any additional attributes that apply to the relation of both entities, such as the order. You don't instantiate involved entities in the relation object.

To be precise, your ER model is like this

Exercise (id, name)
Question (id, wording)
ExerciseQuestion (exercise_id, question_id, order) // both ids
                                                   // form primary key
Alternative (id, text, question_id)

And your classes should follow that.

progmatico
  • 4,714
  • 1
  • 16
  • 27