【问题标题】:Good design to track changes in domain model跟踪领域模型变化的良好设计
【发布时间】:2015-12-08 19:05:59
【问题描述】:

我们有 2 个单独的现有应用程序,它们只能通过总线消息传递系统和数据库进行通信。现在我们想通知第二个应用程序在数据库更新之前或之后在第一个应用程序中对我们的域模型所做的任何更改:一旦我们知道有真正的更改要保存在存储中或刚刚保存,我们想要发送特定消息到一个单独的应用程序。消息未指明进行了何种更改。

一些注意事项:

  • 我们希望保持我们的域模型精简,我的意思是内部没有特定的业务逻辑,同时我们不想将服务引用添加到我们的数据层(存储库类列表)
  • 理想情况下,即使调用了存储库的 Update 方法,如果数据库没有真正的更改,我们也不希望发送消息。
  • 如果消息在数据提交到数据库之前发送也没关系,即使它们最终被拒绝
  • 我们的领域模型由几十个对象和几十个属性组成,因此向每个属性添加 OnPropertyChanged 会花费大量时间
  • 我们绝对不想在存储级别实现通知系统
  • 我们希望以任何开发人员都无法绕过此通知机制的方式构建我们的应用程序设计

您会建议我们在应用程序设计方面使用哪些方法?数据层通过总线系统提交此类通知是一种好习惯吗?我们如何知道数据实际上发生了变化:我们可以通过 NIBerate 会话知道它还是我们必须跟踪领域模型内部的变化?

【问题讨论】:

    标签: c# design-patterns nhibernate


    【解决方案1】:

    Data Layer 通过总线系统提交此类通知是一种好习惯吗?

    不,不是。尽管一些框架开箱即用地支持这一点,但自己拥有或编写通常是错误的。这里的问题有两个 -

    1. YAGNI - 当您预先设计一个系统时,您往往会用高估的机制来压倒它,这反过来会影响系统的效率和简单性。
    2. 上下文是关键!拥有一个在没有上下文的情况下通知它所做的一切的存储库太笼统了。考虑在向表中插入行以更改 UI 时通知,现在考虑从云同步数据的角度。向 DB 中的大量数据与 UI 刷新率之间存在强耦合,这显然是两件不同的事情。解决这个问题并保持连贯性变得很麻烦。

    我们如何知道数据实际发生了变化:我们可以通过 NIBerate 会话知道它还是我们必须跟踪域模型内部的变化?

    您对要求和这个问题的表述存在一些不一致之处。您这样介绍它 - “如果消息在数据提交到 db 之前发送也没关系,即使它们最终被拒绝” 然后你说知道数据实际上已更改是相关的与否。

    无论如何,如果您将数据直接保存到 DB,它通常会返回一些指示,例如修改的行数。当使用像 NHibernate 这样的 ORM 框架时,您通常可以立即提交事务并获得相同的指示。

    在这两种方式中,如果其他应用程序正在从同一个数据库中检索数据,您应该只让其他应用程序知道数据库中的数据实际更改的时间。

    您会建议我们在应用程序设计方面使用哪些方法?

    我们通过将事件发布为逻辑过程的一部分而不是持久性的一部分来解决此问题,因为您可能有一些不需要通知的操作。如果您仍想在数据方面执行此操作,我不建议在您的存储库中对其进行硬编码,而是使用 Martin fowler 的 Unit of workTransaction script 模式。它们将允许您决定哪些数据事务应该发布事件,哪些不是,以及何时发布。

    【讨论】:

      【解决方案2】:

      数据层通过以下方式提交此类通知是一种好习惯吗? 公交系统?

      不,但是如果您需要为每次更改都发出此类通知,并且如果您可以将这些事件绑定到系统的管道中而无需更改所有存储库,则可以。

      我们如何知道数据实际上发生了变化:我们可以通过 NIBerate 会话知道它还是我们必须跟踪域内的变化 型号?

      解决此问题的最简单方法是使用interceptor or an event。 这样的事情应该可以解决您的问题,

      事件

      (完整示例请参考this

          public class ChangeEventListener : IFlushEntityEventListener
          {
              public SetModificationTimeFlushEntityEventListener()
              {
                  CurrentDateTimeProvider = () => DateTime.Now;
              }
      
              public void OnFlushEntity(FlushEntityEvent @event)
              {
                  var entity = @event.Entity;
                  var entityEntry = @event.EntityEntry;
      
                  if (entityEntry.Status == Status.Deleted)
                  {
                      //raise event
                  }
                  var trackable = entity as ITrackModificationDate;
                  if (trackable == null)
                  {
                      return;
                  }
                  if (HasDirtyProperties(@event))
                  {
                      //raise event
                  }
              }
      
          }
      

      拦截器

      public class NotificationInterceptor : EmptyInterceptor 
      {
      
               public override bool OnFlushDirty(object entity, 
                                                object id, 
                                object[] currentState,
                                object[] previousState, 
                                string[] propertyNames,
                                IType[] types) 
              {
              //do check for changed states by comparing current and previous values, and raise event if changed
                  return true
              }
       }
      

      【讨论】:

      • 为什么不用 Nhb 听众呢?侦听器似乎是较新的机制
      猜你喜欢
      • 1970-01-01
      • 2013-05-15
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      相关资源
      最近更新 更多