我正在开发我的第一个Core Data项目(在iPhone上),我真的很喜欢它。核心数据很酷。
但是,我遇到了一个设计难题,我不确定如何解决,尽管我认为这是一个相当常见的情况。它涉及数据模型。为了清楚起见,我将以假想的足球游戏应用程序为例来说明我的问题。假设有NSMO称为唐斯和戏剧。播放功能类似于Downs使用的模板。用户创建Plays(例如,Bootleg,Button Hook,Slant Route,Sweep等)并填写各种属性。戏剧与唐斯有很多关系。对于每个Down,用户决定使用哪个Play。执行Down时,它使用Play作为其模板。每次运行后,它都会存储在历史记录中。该节目记得有史以来所有的唐斯。
到目前为止,这么好。这一切都很好。
我遇到的问题是当用户想要更改Play的详细信息时会发生什么。假设它最初涉及向左传递,但是用户现在希望它是向右传递。但是,进行此更改不仅会影响该Play的所有未来执行,还会更改存储在历史记录中的播放的详细信息。由于Play模板已被更改,Downs的记录实际上已被“污染”。
我一直在解决这种情况的几种可能的修复,但我想SO的天才知道如何处理这个比我更多。不过,我提出的潜在修复方法是:
播放的“版本控制”。对Play模板的每次更改实际上都会创建一个具有相同名称的新的单独Play对象(就用户而言)。然而,在引擎盖下,它实际上是一个不同的游戏。这可行,AFAICT,但似乎它可能会导致Play对象的疯狂扩散,尤其是。如果用户在同一个Play的多个版本之间来回切换(每次用户切换时在对象之后创建对象)。是的,该应用程序可以检查预先存在的,相同的播放,但......它只是看起来像一团糟。
让Downs在保存时记录他们使用的Play的详细信息,但不记录Play对象。这看起来很荒谬,因为Play对象是那里来保存那些细节。
认识到Play对象实际上正在实现两个功能:一个是Down的模板,另一个是记录使用的模板。这两个函数与Down有不同的关系。第一个(模板)具有多对多关系。但第二个(记录)有一对一的关系。这意味着要创建第二个对象,例如“Play-Template”,它将保留与Downs的多对多关系。播放对象将被重新配置为与Downs具有一对一关系。 Down将使用Play-Template对象执行,但使用新类型的Play对象来存储使用的模板。正是这种从一对多的关系变为一对一的关系,代表了问题的关键。
即使写出这个问题,也能让我更清楚。我觉得像解决方案3这样的东西就是答案。但是,如果有人有更好的想法,或者甚至只是确认我正在走上正轨,那将会有所帮助。 (记住,我不是在制作足球比赛,只是更快/更容易使用每个人都能理解的比喻。)
答案 0 :(得分:1)
我认为你需要重新开始设计。
(1)为什么使用PlayEntity作为DownEntity的模板?实体实际上是(在引擎盖下)类,因此类定义本身就是每个实例的“模板”。
(2)托管对象应代表真实对象或真实信息关系的数据模型。因此,您需要认真思考您尝试建模的真实对象或信息。一个好的开始就是问问自己如何用笔和纸记录这些信息。
在你的例子中,Plays and Downs模型完全不同。
Down是及时订购的事件。在任何特定的游戏中只有一个特定的Down。这意味着足球历史上每场比赛中的每一场比赛都是完全独一无二的。因此,向下数据模型实体主要感兴趣的是将Down的关系及时建模到其他向下和整个游戏。
相比之下,Play是一个空间事件。比赛不是独一无二的,经常在比赛中以及从比赛到比赛中重复。 Play实体应关注球员,球和场地之间的空间关系。
你最终会得到这样的东西:
DownEntity{
game;
half;
quarter;
turnover;
gameClockTime;
yardLine;
penalties;
play --(required,Cascade)->PlayEntity.down
previousDown --(optional, nullify)-->Down.nextDown;
nextDown --(optional, nullify)-->Down.previousDown
}
PlayEntity {
playName;
//whatever other detail you want to model
down --(optional,nullify)-->>DownEnity.play;
}
请注意,两个实体都不会复制另一个实体的属性中保存的信息。他们也没有共享继承,因为他们没有模仿游戏的相同方面。 Down模拟时间序列,Play模拟空间序列。它要求两者完全描述每次下来发生的事情。
您首先要创建所需的标准化PlayEntities来构建数据库。如果您有一个新颖的游戏,您将创建一个新的PlayEntity并根据需要填充它。每次你失败都会创建一个DownEntity并创建一个与现有或新创建的PlayEntity的关系。
答案 1 :(得分:0)
我会选择你的#3作为最明智,最明智的选择。它很好地涵盖了您(隐喻)应用程序的预期用途。
我在一段时间内遇到了类似的情况,其应用程序跟踪了对人们进行的测试;测试包含多个问题,可以在多个日期进行更改和重新管理。拥有测试模板以及各个测试对象,使整个模型更容易处理。