CQRS 与旧系统



我希望将一个相对较新的基于 Web 的应用程序转换为更像 CQRS 风格的系统,具有清晰的域模型。 我的新应用程序本质上是对旧现有系统的增强替换。

我组织中的现有系统共享一组通用数据库,这些数据库由整个公司孤岛中存在的无数应用程序(通过混沌方法开发)进行更新。 (就目前而言,我相信公司中没有一个人可以识别所有这些人。

因此,我的

问题是关于我的应用程序的读取模型。 由于各种状态更改、一般用户数据等都是由我无法控制的其他应用程序更新的,因此以我可以处理外部更新但仍然保持相对简单的方式处理构建读取模型的最佳方法是什么?

到目前为止,我已经考虑了以下内容:

  1. 在数据库中为读取模型创建视图,这些模型读取所有表,旧表和新表。
  2. 向现有表添加触发器以更新新的读取模型表
  3. 向数据库(CLR Stored proc/etc [sql server])添加一些代码以更新读取模型的外部数据存储
  4. 放弃希望

关于如何处理这个问题的普遍共识是什么? 认为我可以在不完全从头开始重写所有内容的情况下为遗留系统带来秩序是愚蠢的吗?

我已经成功地使用了选项 #1。 创建视图以降低数据士气以创建读取模型是一个可行的选项,具体取决于写入数据库的复杂性。 这意味着,如果它是大多数开发人员可以理解的相对简单的连接,那么我会仔细研究它是否适合您。 我会小心这些观点过于复杂。

要考虑的另一件事是定期轮询以构建和更新类似于传统报告数据库。尽管与通知相比不是最佳的,但根据读取模型的陈旧程度,这也可能是要查看的选项。

我曾经遇到过类似的情况,以下步骤是我是如何做到的:

为了改进遗留系统并实现更清晰的代码库,关键是接管编写责任。但不要太雄心勃勃,因为这可能会引入接口/合约更改,从而使最终部署存在风险。

  1. 如果所有写入都是通过除直接 sql 更新之外的任何内容触发的,请尽可能使它们向后兼容。将它们作为新开发的命令处理程序的适配器/客户端。

  2. 有些写入是直接的sql更新,但不受您的控制
    询问负责团队是否可以更改为您的新界面/合同?
    如果没有,请参阅步骤 3。

  3. 询问他们是否可以容忍最终一致性,并愿意用数据库过程替换SQL更新?
    如果是,请将所有 sql 更新放在过程中并计划部署并查看步骤 4。
    如果没有,也许你应该将它们包含在重构中。

  4. 修改过程,将 sql 更新替换为插入事件。并开发一个后端作业来滚动事件并发布它们。使订阅这些事件的新应用程序向命令处理程序触发命令。

  5. 从命令处理程序发出事件,并使用它们更新其他应用程序过去使用的表。

  6. 移至旧系统的下一部分。

如果我们有一个无限强大的服务器,我们就不会为视图模型而烦恼,而只会从基本实体表中读取数据。 视图模型旨在通过准备和维护适当的数据集进行显示来提高性能。 如果使用数据库视图作为视图模型,则实际上并没有比即席查询获得太大的性能提升(如果忽略 sql 解析器可以为视图执行的预先规划)。

我使用的解决方案取得了成功,该

解决方案比@Hippoom的解决方案侵入性更小,但比@Derek的解决方案响应更快。 如果您有权访问旧系统并且可以进行较小的代码更改,则可以添加异步队列写入,以在旧系统存储库或持久保存数据的队列系统(RabbitMQ、Kafka 等)中生成事件。 使这些写入异步不会带来任何显著的性能成本,如果队列写入失败,也不会影响旧系统。 通过 QA 进行此更改也相当容易。

然后编写一个事件驱动的部分来更新您的读取模型。 在旧系统更新阶段(可能需要一段时间),或者如果您只能访问写入这些数据库的某些旧系统,则可以使用一个小实用程序,每隔几分钟在队列中放置一个新的"UpdateViewModel"事件。 然后,当旧系统保存重要内容时,您将获得及时的事件,但对于您无法更新的系统,也会涵盖这些事件。

最新更新