设计模式对许多实体的历史有益吗?

时间:2011-08-23 10:43:41

标签: design-patterns

我的应用程序中有一些实体类。我想保存对此实体的所有更改以及历史表中发生的一些事件。问题是实体类是不同的,用不同的原语构建,它们之间有不同的关系。

例如,在购物应用程序中,可以有:User,Item,Transaction,Watch。我希望能够像这样向用户显示一些活动日志:

  • 16:00你在2468交易中买了“指环王”,
  • 15:30您已将“Hobbit”添加到您的监视列表中,
  • 15:00看过项目的“Silmarillion”已将价格从15降至12,50欧元,
  • 14:30你已经把你的名字从“Tomasz”改为“Tom”。

此日志涉及许多内容:

  • 新交易实体2468,项目为“LotR”,
  • 与项目“Hobbit”及我的帐户
  • 关联的新Watch实体
  • 更新了商品价格(但存储了旧价格和新价格),
  • 更新了用户名(旧存储和新存储)。

我的主要问题是如何跟踪这些数据?

  1. 我是否应该拥有与实体表一样多的表来保留其更改? UserVersions,ItemVersions等?
  2. 我应该查询所有版本表,加入并排序结果以生成此日志吗?
  3. 或者也许应该有一个表版本,其中包含“Entity”,“OldValue”,“NewValue”列 - 那么约束和外键呢?是不是太脏了解决方案?
  4. 这有设计模式吗?
  5. 最后如果你知道 - Facebook如何做到这一点? :)

3 个答案:

答案 0 :(得分:6)

您可能对名为Event Sourcing的设计模式感兴趣。

  

Event Sourcing确保对应用程序状态的所有更改都是   存储为一系列事件。我们不仅可以查询这些事件   也可以使用事件日志来重建过去的状态,并作为一个   基础自动调整状态以应对追溯   变化。

至于如何存储此类事件,实际上取决于要求。有时只需将其序列化为JSON就足够了。

事件采购包含在大多数CQRS实施中,因此您几乎可以在任何与之相关的资源中找到其他信息。

答案 1 :(得分:2)

您可以使用commandpattern。如果将它们添加到堆栈中,则可以获得历史记录。

每个命令都包含执行任务所需的所有信息。 这个过程意味着每个命令都是分解的,并且很难为特定用户视图存储和查询它们(因为用户需要查看其他人调用的命令的信息(例如15:00观看项目的“Silmarillion”已降价)从15到12,50欧元)。

您可以在数据库中按如下方式表示命令:

Command
-------
id
name
timestamp
user

CommandParameters
-----------------
commandId
name
value

现在,您可以构建一个查询,显示用户或用户在其监视列表中的特定项目的所有相关命令(您可以添加包含与用户和项目相关的所有命令的表格)

HistoryBuilder
--------------
viewName
commandName
filterField

对于用户,您可以获得最终用户可以执行的所有命令,对于项目,您可以获得与价格更新库存更改等项目相关的所有命令。

现在,您可以提供适配器,以便从这些命令中生成更多用户友好的消息。通过这种方式,您可以在其他上下文中使用相同的命令,并在其上使用另一个适配器。

我希望这能让你更进一步。

答案 2 :(得分:0)

也许您可以使用Drupal和其他CMS的方法,即将相同数据的当前版本和旧版本保存在单个表中。这里举例说明更详细:CMS versioning strategies for content

不知道这个模式的名称是什么,但我确信它自己就是一个。

这有一个明显的速度优势。在跟踪引入每个更改的操作方面,您可以使用单独的表,可能在更改之前和之后有一些指向记录的链接。