我想创建一个在线测验应用程序。我想到了几种类型的练习,包括填空练习:
练习可能要求用户输入文本:
Chemical energy produced by the ____ is stored in a small molecule called ____
或者从给定列表中选择一个选项:
Mitochondria contain their own small (genes/cells/chromosomes)
我一直想知道在 SQL 模式中表示它的最佳方式。空格可以出现在句子的任何部分,并且可以有任意数量的空格。
所以我想这样表示:
class BlankExercise {
@ManyToOne
private List<Part> parts;
}
其中
Part
可以是普通文本,也可以是空白。因此,每个练习都是其各部分的总和:
Chemical energy produced by the ____ is stored in a small molecule called ____
有 4 个部分:
1. Chemical energy produced by the
2. (Mitochondria)
3. is stored in a small molecule called
4. (adenosine)
但这需要使用某种形式的继承策略 -
Part
将是一个公共父类,它将由 NormalPart
和 BlankEmptyPart
和 BlankOptionsPart
进行扩展。但我读到,如果可能的话,应该避免对数据库实体使用继承,但我很难看到一种不涉及继承的解决方案。
我能想到的唯一其他解决方案是使用多个表格,一个单独的表格用于“正常”文本,另一个表格用于每种类型的空白:
exercise_texts
exercise_id text
对于用户必须输入整个单词的空白:
exerice_blanks_empty
exercise_id solution_text blank_index
对于用户选择现有选项的空白:
exerice_blanks_options blank_index
exercise_id blank_id
与
exercise_blanks_options_list
blank_id option_text is_correct
每个空白表都有
blank_index
列,该列对应于其在句子中的位置:例如,Mitochondria
的索引为 1
,adenosine
的索引为 3
。
我想知道哪种设计更好,或者两者都不可行,有更好的吗?
从数据库的角度来看,您所勾画的两种模式看起来都很合理。我使用稍微不同的命名约定充实了对此的解释,我认为这将是一个小小的改进。请参阅sqlfiddle。
请注意,不要以组织应用程序代码的名义以不自然的方式扭曲数据库模式;设计不当的数据库可能会成为你的眼中钉。
当孩子确实是父母的子类型时,继承是最好的。在这种情况下,我不会将空白选项解释为练习题的子类型,它更多的是它的一个属性。所以它们是相关的,但不是以集合子集的方式。
在这种情况下,您可以考虑使用组合,而不是继承。例如。使用建议的模式,您可以在实例化类时将
List<QuestionBlank>
传递给 Question
类。您正在将属性 Question.QuestionBlanks
设置到该列表。
如果您想使用继承来反映
Question
、QuestionPart
和 QuestionPartBlankOption
之间的相似性,您可以考虑创建一个基类,让它们各自继承。他们各自共享一些属性,例如主文本字段,可能需要某种显示顺序等。如果您认为可以通过此实现的代码重用证明了此附加抽象的合理性,那么所有三个对象都可以从我们可以称为“的单个父对象继承” QuestionText”或其他什么。这可能是应用程序代码中的一个方便的抽象,不耦合到特定的数据库表。