Master Template Model: Inherit or Not?

I have a scenario that is not easy to explain, but I'm sure it's a very common problem. I will try my best to illustrate the problem.

Let's say we have a Survey app that allows us to create surveys. Each survey has its own structure (contains questions, questions are grouped and ordered, etc.). These polls are managed by the administrator and are considered the main survey templates. The user can now select one of these master surveys, make some settings, and interview some individuals.

So basically we have polls that have a common structure (collections, properties, etc.), but the data can be different.

How do you model the database?

My idea would be to keep everything in one table and create a column that separates templates from executed ones.

tbl_Survey (id, name, conducted_on)

      

How do you model your classes?

My idea:

Survey {
  Name
  Questions
}

ConductedSurvey : Survey {
  //gets the master according to the name
  GetMaster()
}

      

Important: There are many relationships with other classes in the Overview. If we decide to subclass. Do they all have to be subclasses (because we will be copying data from master for each object)?

+1


source to share


1 answer


So basically we have polls that have a common structure (collections, properties, etc.), but the data might be different ... My idea would be to store everything in one table and create a column that separates templates from held ones.

Okay what you say is a prototype. Polling "templates" is a prototype. Obviously, if a prototype has the same structure as an instance based on a prototype, if it would be foolish and wasteful to create completely different tables for the same structure - even more so when you realize that this means any change in this structure should be reflected in both sets.

Is it possible to add a column to differentiate the prototype / template from the completed survey? No, probably not. Instead, I would add another one-to-one table to the survey root table. In this table, I would add some metadata that distinguishes prototype from non-prototype.

For three reasons: 1) In any sane system, prototypes will be a little less general survey. 2) I would often like to list all prototypes, eg. "create a new survey wizard", which lists the prototype options on which the new survey is based. And 3) hold this for a little extra data:

create table survey_prototype (
    id int not null primary key,
    survey_id references survey(id) -- the regular survey table
    wizard_description varchar(80)
    . . . .
);

      

Now I suppose there is a description in the review as well, but this is for a prototype, this description is something like "REPLACE ME WHAT USER DESCRIPTION WILL SEE", but this wizard_description is something like "Political Poll Prototype".

Now, since any search for a prototype / template has no chance of returning a survey completed (since no survey completed is attached to survey_prototype), your getMaster looks (conceptually, presumably you are using an ORM) like this:



ConductedSurvey : Survey {
  //gets the master according to the name
  GetMaster() { "select * from survey_prototype join survey..."
}

      

Important: There are many relationships with other classes in the Overview. If we decide to subclass. Do they all have to be subclasses (so that we copy the data from the master for each object)?

You are correct: for any prototype you get through your ORM, you will have to deep copy it in order to save the new poll and not overwrite the prototype. Since you need to make a deep copy anyway, in deep copy you can instead of using the base class that uses the prototype, make a copy of the subclass.

Of course, you will need to make this decision at every level of the hierarchy; it would be nice to encapsulate each transform policy to deeply transform the copy into one class. Template visitor would do it, because it has one overloaded function visit

for each (base) class of your types as (at least) visitSurvey

, visitQuestion

, visitAnswer

.

Since you will be dealing with a tree (taking into account the survey, with the questions about children and the answers of the grandchildren, i.e. the composite template), I suggest you use the visitor template in your copy / transformer. Since your classes are relatively stable, the visitor will perform well. And it allows you to have several different specific visitors, one for each type of transformation (and when it comes time to show or grade a survey, you can also write a visitor for that - so you get this functionality for almost "free" after you install the visitors template ).

Any of the common nhibernate patterns can be used to handle subclasses in the database; This way, after you have visited and transformed, you will have a new non-prototype tree that can be automatically saved to the nhibernate database.

So to summarize: survey_prototype table, get prototype, nhibernate will fetch the whole tree when querying root in survey_prototype, visit that tree with deep copy transformer which returns copied root, allows user to write on this, save copied root and let nhibernate recursively will save every node of the tree. When the user should see a non-prototype survey, pull the root of the survey with nhibernate, use a screen visitor to display it, etc.

+4


source







All Articles