你会推荐哪种版本控制设计模式?

23
我需要在一个应用程序中建立“版本控制”的功能,想知道如何最好地处理它。
通常情况是:
模型A有许多B
当更新模型A的属性时,需要对其进行版本控制,并且还需要对其关联对象(B)进行版本控制。因此,应用程序将显示模型A的当前版本,但也必须能够查看先前版本的A及其关联对象。
我想使用文档存储,但这只是应用程序的一部分,使用文档存储和关系数据库会增加更多的复杂性。
我已经考虑使用星型模式,但在继续之前,我想知道是否有一种设计模式可以解决这个问题?
这个问题主要是解决在关系数据库中存储相关对象的版本的问题。需要能够有效地查询数据(例如,序列化对象不足以满足需求)。
更新:我正在思考/已经实现了某些方法,但希望知道是否有“更好的方法”。
,---------. 1      * ,--------.
| Model A |----------| Model B|
`---------'          `--------'
|PK       |          | a_id   |
|b_version|          |version |
|version  |          `--------'
`---------'

我会复制模型A以及所有相关的B,并递增版本属性。然后通过b_version和b.version连接B进行选择查询。只是想知道是否有更好的方法。

5个回答

10

这个链接对于确认我的想法非常有帮助,因为他使用时间作为一个维度,而我则建议使用版本号。 - MatthewFord

9

我认为并没有特定的GoF设计模式来处理版本控制,因为有许多实现方式。

最简单的版本控制实现是一个对象的链表。其中列表中的每个节点都是可版本化对象的新版本。为了节省空间,您还可以实现某种diff,显示修订版之间的区别。这样,您可以将差异存储在数据库中,但版本控制系统也应该能够推导出中间版本的最终版本的版本化对象。

数据库模式可能主要如下所示(您可以在大多数Wiki系统中看到此模式):

+--------------------+ 1     * +-----------------------------+
| VersionableObject  |---------| Diff                        |
+--------------------+         +-----------------------------+
| lastStateContent   |         | difference                  |
| originalAuthor     |         | revision                    |
| #dates and whatnot |         | # userId, dates and whatnot |      
+--------------------+         +-----------------------------+

如果您想在分支和其他方面变得更加强大,您可能需要考虑查看DAG,这是现代分布式版本控制系统使用的内容。
现在,如果我们谈论您的示例,就需要保存许多对象的配置。也就是说,我们必须挑选出我们想要模型的对象的修订版。这意味着我们有一个多对多的关系(可以通过中介表解决),就像这样:
+---+ 1   * +---------------+ 1   * +-----------------+ *   1 +-------+
| B |-------| Diff          |-------| ModelSelection  |-------| Model |
+---+       +---------------+       +-----------------+       +-------+
            | revisionNo    |       | {PK} configId   |
            | {FK} configId |       | {FK} modelId    |
            +---------------+       +-----------------+

我希望这有所帮助。


这种实现方式不能解决版本之间及其相关对象之间的关系维护问题。 - MatthewFord
1
deimos1986:当然会,已经更新了一个数据库模式的例子。你可以在维基实现中看到这个弹出窗口。我建议你查看MediaWiki或其他开源维基系统,并查看它们的数据库模型以获得一些灵感。 - Spoike
哦,你的意思是你有一个需要进行版本控制的整个对象配置... - Spoike
在这个维基例子中,如果每个维基页面也有与版本相关联的评论,当您返回旧版本时,您可以看到该版本的适当评论。 - MatthewFord
@deimos1986:在数据库中更新了一些配置处理方面的内容。将Model视为您的A,将ModelSelection视为您与B对象的关联(但选择这些对象的特定修订版本)。 - Spoike
显示剩余2条评论

2
我曾在Rails中通过使用acts_as_versioned插件来解决这个问题。当将其应用于一个模型时,它假定除了model_name表之外还有一个model_name_version表。每次保存模型时,旧版本以及时间戳都会被复制到model_name_version表中。
这种方法使模型表的大小可管理,同时仍然允许搜索以前的版本。我不确定该插件是否可以直接处理您想要的链接,但是添加功能不难。

我已经查看了acts_as_versioned和其他现有的插件,似乎没有处理版本关联的问题。AAV维基页面有这个开放性的问题:是否有人对外键关系进行版本控制方面的工作? - MatthewFord
正确 - 我不认为会这样。然而,插件非常容易修改,这个特定的更改并不困难。 - Sarah Mei
我已经为Sequel编写了一个插件,按照问题描述的方式实现了它。我想再次尝试在AR中完成它,并以最佳方式完成。如果查看AAV插件代码,将其扩展以处理n..n关联是非常困难的。 - MatthewFord
也许acts_as_versioned_associations会是一个更好的起点?http://github.com/rlivsey/acts_as_versioned_association/tree/ - Sarah Mei
来自aava的作者(以防其他人尝试使用它):注意-自Rails 1.2以来就没有被修改过,也没有在Rails 2中进行过测试,需要一些关爱,但我目前没有时间。 - MatthewFord

1

听起来可能有帮助,我想我的问题涉及到数据库层面的设计。当Memento有多个关联对象需要持久化时,您如何进行持久化处理? - MatthewFord
每个对象都负责将其状态存储到相应的数据库表中。当每个对象还持有一个名为“version”的属性时,该属性通过Observer在每次更改时同步,因此应该可以存储一致且可重现的状态。 - Kosi2801

0

保存您想要版本控制的数据库架构的XML快照,然后能够更改数据库的状态怎么样?


说实话,回头看,我有点绕过问题,只是获取了所有需要的数据,并将其组合成一个大的JSON文档,然后在需要获取(一组表的)版本时将其转储到CouchDB中。问题不在于模式,而在于跨多个表的情况。 - MatthewFord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接