为了简单起见:假设您有一个包含下表的实体关系图 (ERD):
Survey
:ID、姓名、问题 Question
:ID、文本、调查在这种情况下,
Survey
有一个或多个Questions
,而Question
仅属于一个Survey
。我的问题是,我可以仅使用类重新创建此架构,而不使用任何持久层(如领域或核心数据)吗?这是我的意思的简单演示:
struct Survey {
var id: Int
var name: String
var questions: [Question] // 1 or more questions
}
struct Question {
var id: Int
var text: String
var survey: Survey // belongs to only one survey
}
我尝试了这种方法,但显然由于一对多关系,以下代码将无法工作:
let survey = Survey(id: 0, name: "First survey", questions: [
Question(id: survey.id, text: "Whats your name", survey: survey) // This is not possible.
])
更多背景:我想创建一个调查应用程序。该应用程序的架构很难设计,因为调查将支持多种类型的问题(多项选择、开放式问题、是/否问题等)。通过在线搜索,我发现有一些针对像
this这样的调查的 ERD 设计。问题是这个 ERD 设计是针对数据库的..但我现在不想创建数据库。然而,我认为在架构上设计可以使用类来表示。那么问题是如何?
这是解决这个问题的一种明显方法,
struct Survey {
var id: Int
var name: String
var questions: [Question]! // 1 or more questions
init(id: Int, name: String) {
self.id = id
self.name = name
}
}
struct Question {
var id: Int
var text: String
var survey: Survey // belongs to only one survey
}
因此,您可以创建一个对象,而不需要创建其他结构并只需使用赋值,而不是在初始值设定项内传递对象。
var survey = Survey(id: 0, name: "First survey")
survey.questions = [
Question(id: survey.id, text: "Whats your name", survey:survey) // This is not possible.
]
但是 ERD 是在 OOP 还很陌生的时代发明的。存在多种扩展 ERD 变体 (EERD),每种变体都试图以自己的方式解决继承和专业化问题,但语义较弱且没有权威标准。
修改架构
事实上,支持“
多种类型的问题”的意图强烈建议使用Question
的某些专业化(子类型),因为多项选择的内容和行为与开放式问题非常不同。然后,继承将允许应用开放封闭原则,即轻松添加新类型的问题,而无需更改其余代码。
对代码的影响:Question
不应该是
struct
而是class
或协议。
问题需要了解其调查吗?Question
需要了解
Survey
。我不确定,因此我使用了单向导航箭头。事实上,人们很容易想象在多项调查中都使用同一问题。如果您需要它,您的设计就有问题,因为很难像您的代码那样初始化带有问题的调查,而且,没有什么可以阻止
不一致,问题引用的是另一项调查而不是它所包含的调查.
要解决此问题,请考虑采用没有引用回溯的设计,或者至少分两步创建调查并添加问题:一种不直接修改数组的方法可以强制一致性。或者,您可以考虑创造性地使用