I have a requirement to build 'versioning' into an application and was wondering how best to approach it.
我需要在应用程序中构建“版本控制”,并且想知道如何最好地处理它。
I have this general pattern:
我有这个一般模式:
Model A has many B's
模型A有很多B
Where on update the attributes of A need to be versioned and its associated objects (B's) also need to be versioned. So the application will display the current version of A, but it must also be possible to view previous versions of A and its associated objects.
在更新时,A的属性需要进行版本化,并且其关联对象(B)也需要进行版本控制。因此,应用程序将显示A的当前版本,但也必须能够查看A的早期版本及其关联对象。
I would like to use a document store however this is only a portion of the application and having a doc store and a relation database would introduce more complexity.
我想使用文档存储,但这只是应用程序的一部分,并且拥有doc存储和关系数据库会带来更多复杂性。
I have considered using a star schema, but before I progress I was wondering if there is a design pattern floating around tackling this problem?
我考虑过使用星型模式,但在我进步之前,我想知道是否有一个设计模式可以解决这个问题?
This question is slanted towards resolving the issue of storing the versions of an associated object in a relational database. Where there is an inherent need to be able to effectively query the data (ie serializing object won't suffice).
这个问题倾向于解决在关系数据库中存储关联对象的版本的问题。哪里有固有的需要能够有效地查询数据(即序列化对象是不够的)。
Update: What I was thinking/have implemented but want to see if the is "a better way"
更新:我在想什么/已实施但想看看它是“更好的方式”
,---------. 1 * ,--------.
| Model A |----------| Model B|
`---------' `--------'
|PK | | a_id |
|b_version| |version |
|version | `--------'
`---------'
Where I would be duplicating model A and all the associated B's and incrementing the version attribute. Then doing a select to join the B's via b_version and b.version. Just wondering if this can be done better.
我将复制模型A和所有相关的B并增加版本属性。然后通过b_version和b.version进行选择以加入B'。只是想知道这是否可以做得更好。
5 个解决方案
#1
7
I don't think there is no specific GoF design pattern per se for versioning because there exists many implementations of it.
我不认为没有特定的GoF设计模式本身用于版本控制,因为它存在许多实现。
The most simple implementation of versioning is a linked list of objects. Where each node in the list is a new revision of whatever the versionable object is. To save space you also implement some kind of a diff that shows what the difference is between the revisions. That way you can store diffs in the database, but also the final version of the versionable object since the version control system should be able to derive the versions in between.
版本控制的最简单实现是对象的链接列表。其中列表中的每个节点都是可版本化对象的新版本。为了节省空间,您还可以实现某种差异,以显示修订版本之间的差异。这样,您可以在数据库中存储差异,但也可以存储可版本化对象的最终版本,因为版本控制系统应该能够在其间导出版本。
The database schema could principally look something like this (you can see this pattern in most wiki systems):
数据库模式主要看起来像这样(你可以在大多数wiki系统中看到这种模式):
+--------------------+ 1 * +-----------------------------+
| VersionableObject |---------| Diff |
+--------------------+ +-----------------------------+
| lastStateContent | | difference |
| originalAuthor | | revision |
| #dates and whatnot | | # userId, dates and whatnot |
+--------------------+ +-----------------------------+
If you want to go hardcore with branching and stuff you might want to consider have a look at DAG which is what modern distributed version control systems use.
如果你想用分支和东西去硬核,你可能要考虑看一下现代分布式版本控制系统使用的DAG。
Now if we talk about your example a whole slew of objects that needs to be saved in configurations. I.e. we have to pick out the revisions of objects that we want for the model. It means we have a many to many relationship (which is solved with an intermediary table), sort of like this:
现在,如果我们谈论您的示例,需要在配置中保存一大堆对象。即我们必须挑选出我们想要的模型对象的修订版。这意味着我们有多对多关系(用中间表解决),有点像这样:
+---+ 1 * +---------------+ 1 * +-----------------+ * 1 +-------+
| B |-------| Diff |-------| ModelSelection |-------| Model |
+---+ +---------------+ +-----------------+ +-------+
| revisionNo | | {PK} configId |
| {FK} configId | | {FK} modelId |
+---------------+ +-----------------+
I hope this helps.
我希望这有帮助。
#2
8
Martin Fowler has some good articles on time/versioning-based design patterns - definitely worth a look:
Martin Fowler有一些关于基于时间/版本设计模式的好文章 - 绝对值得一看:
http://martinfowler.com/eaaDev/timeNarrative.html
http://martinfowler.com/eaaDev/timeNarrative.html
#3
2
I've solved this problem in rails by using the acts_as_versioned
plugin. When you apply it to a model, it assumes there is a model_name_version
in addition to the model_name
table. Every time a model is saved, the old version along with a timestamp is copied into the model_name_version
table.
我已经使用acts_as_versioned插件在rails中解决了这个问题。将其应用于模型时,它假定除了model_name表之外还有model_name_version。每次保存模型时,旧版本和时间戳都会复制到model_name_version表中。
This approach keeps the size of the model table manageable while still allowing search on previous versions. I'm not sure the plugin handles the chaining you want out of the box, but it wouldn't be hard to add.
此方法可以保持模型表的大小可管理,同时仍允许搜索以前的版本。我不确定插件是否可以处理您想要的链接,但是添加并不难。
#4
1
A combination of the Memento pattern with the Observer pattern should fit your needs. Also have a look at the Visitor pattern for possible application in your case...
Memento模式与Observer模式的组合应该符合您的需求。还可以查看访问者模式以了解您的案例中可能的应用...
#5
0
What about saving a XML snapshot of the database shema you want to version? And then be able to change the state of the database?
如何保存您想要版本的数据库的XML快照?然后能够改变数据库的状态?
#1
7
I don't think there is no specific GoF design pattern per se for versioning because there exists many implementations of it.
我不认为没有特定的GoF设计模式本身用于版本控制,因为它存在许多实现。
The most simple implementation of versioning is a linked list of objects. Where each node in the list is a new revision of whatever the versionable object is. To save space you also implement some kind of a diff that shows what the difference is between the revisions. That way you can store diffs in the database, but also the final version of the versionable object since the version control system should be able to derive the versions in between.
版本控制的最简单实现是对象的链接列表。其中列表中的每个节点都是可版本化对象的新版本。为了节省空间,您还可以实现某种差异,以显示修订版本之间的差异。这样,您可以在数据库中存储差异,但也可以存储可版本化对象的最终版本,因为版本控制系统应该能够在其间导出版本。
The database schema could principally look something like this (you can see this pattern in most wiki systems):
数据库模式主要看起来像这样(你可以在大多数wiki系统中看到这种模式):
+--------------------+ 1 * +-----------------------------+
| VersionableObject |---------| Diff |
+--------------------+ +-----------------------------+
| lastStateContent | | difference |
| originalAuthor | | revision |
| #dates and whatnot | | # userId, dates and whatnot |
+--------------------+ +-----------------------------+
If you want to go hardcore with branching and stuff you might want to consider have a look at DAG which is what modern distributed version control systems use.
如果你想用分支和东西去硬核,你可能要考虑看一下现代分布式版本控制系统使用的DAG。
Now if we talk about your example a whole slew of objects that needs to be saved in configurations. I.e. we have to pick out the revisions of objects that we want for the model. It means we have a many to many relationship (which is solved with an intermediary table), sort of like this:
现在,如果我们谈论您的示例,需要在配置中保存一大堆对象。即我们必须挑选出我们想要的模型对象的修订版。这意味着我们有多对多关系(用中间表解决),有点像这样:
+---+ 1 * +---------------+ 1 * +-----------------+ * 1 +-------+
| B |-------| Diff |-------| ModelSelection |-------| Model |
+---+ +---------------+ +-----------------+ +-------+
| revisionNo | | {PK} configId |
| {FK} configId | | {FK} modelId |
+---------------+ +-----------------+
I hope this helps.
我希望这有帮助。
#2
8
Martin Fowler has some good articles on time/versioning-based design patterns - definitely worth a look:
Martin Fowler有一些关于基于时间/版本设计模式的好文章 - 绝对值得一看:
http://martinfowler.com/eaaDev/timeNarrative.html
http://martinfowler.com/eaaDev/timeNarrative.html
#3
2
I've solved this problem in rails by using the acts_as_versioned
plugin. When you apply it to a model, it assumes there is a model_name_version
in addition to the model_name
table. Every time a model is saved, the old version along with a timestamp is copied into the model_name_version
table.
我已经使用acts_as_versioned插件在rails中解决了这个问题。将其应用于模型时,它假定除了model_name表之外还有model_name_version。每次保存模型时,旧版本和时间戳都会复制到model_name_version表中。
This approach keeps the size of the model table manageable while still allowing search on previous versions. I'm not sure the plugin handles the chaining you want out of the box, but it wouldn't be hard to add.
此方法可以保持模型表的大小可管理,同时仍允许搜索以前的版本。我不确定插件是否可以处理您想要的链接,但是添加并不难。
#4
1
A combination of the Memento pattern with the Observer pattern should fit your needs. Also have a look at the Visitor pattern for possible application in your case...
Memento模式与Observer模式的组合应该符合您的需求。还可以查看访问者模式以了解您的案例中可能的应用...
#5
0
What about saving a XML snapshot of the database shema you want to version? And then be able to change the state of the database?
如何保存您想要版本的数据库的XML快照?然后能够改变数据库的状态?