【问题标题】:What versioning design pattern would you recommend你会推荐什么版本控制设计模式
【发布时间】:2009-02-17 16:12:58
【问题描述】:

我需要将“版本控制”构建到应用程序中,并且想知道如何最好地处理它。

我有这个一般模式:

模型 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。只是想知道这是否可以做得更好。

【问题讨论】:

    标签: mysql ruby-on-rails design-patterns


    【解决方案1】:

    Martin Fowler 有一些关于基于时间/版本控制的设计模式的好文章 - 绝对值得一看:

    http://martinfowler.com/eaaDev/timeNarrative.html

    【讨论】:

    • 这个链接很好地证实了我的想法,因为他将时间用作我建议使用版本号的维度。
    【解决方案2】:

    我不认为版本控制本身没有特定的 GoF 设计模式,因为它存在许多实现。

    版本控制最简单的实现是对象的链表。列表中的每个节点都是可版本化对象的新版本。为了节省空间,您还实现了某种diff,它显示了修订之间的区别。这样您就可以将差异存储在数据库中,还可以存储可版本控制对象的最终版本,因为版本控制系统应该能够派生介于两者之间的版本。

    数据库架构可能大致如下所示(您可以在大多数 wiki 系统中看到这种模式):

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

    如果您想在分支和其他方面进行硬核,您可能需要考虑查看DAG,这是现代分布式版本控制系统使用的。

    现在,如果我们谈论您的示例,则需要将大量对象保存在配置中。 IE。我们必须为模型挑选出我们想要的对象的修订版本。这意味着我们有一个多对多关系(通过中间表解决),有点像这样:

    +---+ 1   * +---------------+ 1   * +-----------------+ *   1 +-------+
    | B |-------| Diff          |-------| ModelSelection  |-------| Model |
    +---+       +---------------+       +-----------------+       +-------+
                | revisionNo    |       | {PK} configId   |
                | {FK} configId |       | {FK} modelId    |
                +---------------+       +-----------------+
    

    我希望这会有所帮助。

    【讨论】:

    • 这个实现不会解决维护版本及其关联对象之间关系的问题
    • deimos1986:当然可以,使用 dbschema 示例进行了更新。您可以在 wiki 实现中看到此弹出窗口。我建议你看看 MediaWiki 或其他开源 wiki 系统,看看他们的数据库模型以获得一些灵感
    • 哦,你的意思是你有一个完整的对象配置需要版本控制......
    • 是的,一个对象及其所有关联对象都需要版本化
    • 在这个 wiki 示例中,如果每个 wiki 页面也有与某个版本相关联的 cmets,并且当您返回旧版本时,您可以为该版本选择适当的 cmets,这将是相似的
    【解决方案3】:

    我通过使用acts_as_versioned 插件在rails 中解决了这个问题。当您将其应用于模型时,它假定除了model_name 表之外还有一个model_name_version。每次保存模型时,旧版本和时间戳都会复制到model_name_version 表中。

    这种方法使模型表的大小保持可管理,同时仍允许搜索以前的版本。我不确定该插件是否能处理您想要开箱即用的链接,但添加起来并不难。

    【讨论】:

    • 我查看了acts_as_versioned 和其他现有插件,似乎没有一个可以处理版本控制关联的问题。 AAV wiki 页面有这个悬而未决的问题:有人对外键关系进行版本控制吗...
    • 对 - 我希望它不会。然而,插件非常容易修改,而且这种特殊的改变并不难。
    • 我已经为 Sequel 编写了一个插件,它按照问题中描述的方式实现了这一点。我想在 AR 中再次尝试一下,并以最好的方式做到这一点。如果查看 AAV 插件代码,将其扩展为处理 n..n 关联并非易事。
    • 也许acts_as_versioned_associations 会是一个更好的起点? github.com/rlivsey/acts_as_versioned_association/tree
    • 来自 aava 的作者(以防其他人尝试使用它):注意 - 自 Rails 1.2 以来没有被触及,也没有在 Rails 2 中测试,需要一些我目前没有的 TLC时间
    【解决方案4】:

    Memento patternObserver pattern 的组合应该满足您的需求。还请查看Visitor pattern 以了解您的情况可能的应用......

    【讨论】:

    • 听起来它可以帮助我猜我的问题与数据库级别的设计有关。当 Memento 有多个关联对象时,你如何去持久化它们,它们也需要被持久化。
    • 每个对象负责将其状态存储到相应的数据库表中。当每个对象还拥有一个属性“版本”时,该属性通过观察者在每次更改时同步,存储一致且可重现的状态应该是可能的。
    【解决方案5】:

    如何保存您想要版本化的数据库 shema 的 XML 快照?然后能不能改变数据库的状态?

    【讨论】:

    • 老实说,回顾过去,我通过获取我需要的所有数据并将其合并到一个大的 json 文档中并在我需要获取一个版本时将其转储到 couchdb 中(表的集合)。问题不在于架构,而在于跨越多个表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 2020-10-27
    • 1970-01-01
    相关资源
    最近更新 更多