类版本控制以支持向后兼容性

时间:2009-12-29 20:33:17

标签: .net class versioning document

在我工作的项目中,我们处理医疗账单。

每次状态对官方表单(我们的数据类表示)进行更改时,为了保持与以前表单的向后兼容性,我们添加新属性但保留原有表单,并具有文档版本属性用于确定完成哪些验证以及用于显示验证的UI操作。

这导致项目生命周期内的课程膨胀(近5年的国家强制修改),而且根本不支持旧的文档格式不是一种选择。

我想尝试为每个文档版本创建一个新类,但即使这样,我们也会有几个非常相似(虽然稍有改动)代码的副本。并且ProgressNoteV16,ProgressNoteV17等类名看起来很可怕。

不能使用继承,因为这仍然会导致相同的问题(具有不再需要的属性的类)。接口会使接口变得臃肿,这无法解决问题。

用于解决此问题的解决方案和最佳做法是什么?

4 个答案:

答案 0 :(得分:7)

对于任何以任何身份与公众合作的机构来说,这是一个相当经典的问题,特别是如果它是政府或政府监督的机构。解决方案非常重要,它可能需要一些重要的工作来创建,以及之后的维护。

过去在为客户处理类似问题时,这对我有用,但它可能不适合你,你需要草拟你想要完成的事情以及是否有意义这样做。

有几种模式需要熟悉(如果你还没有):

  1. Factory已经提到过
  2. Composition希望能让你摆脱一些丑陋的继承问题
  3. Template用于从版​​本
  4. 中分离出表单的逻辑

    有两本书非常适合解释这些(以及其他一些有用的书):

    1. 首先设计模式(不记得我的头脑)
    2. 企业应用程序架构模式(Fowler)
    3. 现在我过去使用的过程:

      1. 首先获取所有当前版本的表单,将它们分成不同的类并查找常见的重叠。您可以在草稿模式下执行此操作,也可以作为当前计划为每个版本创建不同的类
      2. 从此类结构中派生出许多“基础”对象,您可以将这些对象用作表单的每个重要版本集的继承根。您可能有其中的几个,但它们应该比您拥有的总表单对象少。
      3. 现在,在每个基础对象中,将常用功能(即名称和地址结构等)组合在一起,并将其抽象到自己的类层次结构中,通过构造函数注入将此hieararchy注入到基类中。
      4. 现在将合成模式应用于基类层次结构,并尽可能多地获取通用类结构。理想情况下,此时您的表单只是每个表单中已更改的最小功能,并且具有一个构造函数,该构造函数具有所有常见(可能稍微变化)的功能。
      5. 现在应用模板模式来抽象出类中的所有常用“功能”,例如常见验证和持久性逻辑,再次使用构造函数注入将此功能恢复到基类中。
      6. 从基类中提取接口适配器定义,并将这些定义用作应用程序使用表单的基础
      7. 建立你的工厂类来处理设置它的所有蹩脚工作。
      8. 希望能为您提供一些想法。

答案 1 :(得分:2)

如果无法使用继承“因为文档中的字段可以删除”,那么您目前如何处理?

根据您的设计细节,您应该能够覆盖当前版本文档未使用的字段(即在该文档的子类中覆盖),并在该方法的实现中抛出NotSupportedException或类似内容表单尝试分配值。通过类似的逻辑,您可以(并且可能应该)使用接口...只知道具体实现可能会为它实现的属性抛出异常,但是没有为该UI版本定义。

您可以使用Factory Pattern返回给定表单版本的对象的适当实例。

如果稍微改变但大部分相同的代码之间存在某些共性,您可能能够将某些共性重构为多个公共方法使用的私有/受保护方法。

对于类命名,如果使用工厂模式,则可以使用该接口在大多数代码中引用该类。只有工厂本身才需要处理“奇怪”的类名。

答案 2 :(得分:0)

我会以更松散耦合的方式实现它 - 一个包含两个字段的类:一个版本和一个字典。当数据发生这种变化时,尝试跟踪丢失和添加的属性变得非常繁琐。使用字典,您只需测试以查看密钥是否存在。

答案 3 :(得分:0)

如果没有代码的任何进一步细节,我想你可能会尝试装饰设计模式的想法......看一下这篇文章:Avoid Excessive Subclassing with the Decorator Design Pattern

Martin Fowler检查Patterns for things that change with time也值得一读,以便为这种设计方案提供有用的建议。