业务逻辑发生变化时如何尊重开闭原则?

Posted

技术标签:

【中文标题】业务逻辑发生变化时如何尊重开闭原则?【英文标题】:How to respect Open closed principle when you have business logic change? 【发布时间】:2010-08-24 15:24:29 【问题描述】:

我们正在对我们的系统进行一些重大更改,我想知道在尊重 SOLID 原则的情况下实施这些新业务逻辑规则的最佳方式:

Open / Closed 原则说“打开以进行扩展,但关闭以进行修改”好的,但是我该如何进行修改?我的意思是,我不想保留旧的业务逻辑,而在我看来“扩展”主要是指“添加代码”而不是“更改代码”,那我理解错了什么?

【问题讨论】:

【参考方案1】:

Open/Closed 背后的理念是,如果您需要不同的业务逻辑,则需要创建一个新的业务逻辑类。

但是,这样做的主要动机是您不想影响现有的代码、重新测试、再次签核等。如果您使用的业务逻辑发生了根本性的变化,那么您将会改变所有对新对象的引用并废弃旧对象,在这种情况下重新打开对象进行修改是可以接受的。关键是 (1) 无论如何您都需要重新测试所有代码,并且 (2) 旧对象不会在任何地方使用。

HTH, 詹姆斯

【讨论】:

【参考方案2】:

两个大问题:

我们在这里谈论什么样的变化?

你有什么样的现有代码?是否已经符合任何 SOLID 原则?

假设我们需要对设计良好的现有应用程序进行一些更改。考虑一下工资单应用程序。我们可能有一个Interafce(这只是一个人为的例子)

 public Interface EmployeeContract          
      public int computeSalaryForMonth(int month);
 

我们有实现:

 public class SalesContract implements EmployeeContract 
      public int computeSalaryForMonth(int month)
               // computation involving sales figures and base salary
      
 

  public class HourlyContract implements EmployeeContract 
      public int computeSalaryForMonth(int month)
               // computation involving hours worked and overtime payments
      
 

现在应用程序的所有其他部分都根据接口进行编码。

我们现在可以在不更改任何现有代码的情况下添加新类型的合约,我们可以扩展并添加可能相当复杂的新业务逻辑。

但是这是因为最初的设计师预见到了这种变化,增加了新的月度合同类型。如果我们想招收每周领薪的员工,那不是很好吗?现在我们的界面不合适了,需要改一下,效果会波及其他代码。

实际上,软件不会对任意业务逻辑的无痛更改开放,并且确实尝试预先灵活可以花费大量精力。但是请注意,即使在我的示例中,接口并不像我们现在需要的那样灵活,因为接口是耦合点,因此很容易识别需要更改的代码部分。

总结:在你的情况下:

    了解现有代码的结构以及它的灵活性点。接受某些代码需要更改的事实,并且业务中的重大更改可能需要对代码进行重大更改也就不足为奇了。 结构通常有助于可维护性,因此在添加新代码时请注意结构。通过对接口进行编码在代码中提供“防火墙”,在完成工作和对扩展开放之间取得平衡。

【讨论】:

你说的那种变化是这样的(旅游业):过去老板会说“六月的一周是20欧元”,现在他可以说“六月的一周”是 20 欧元,但如果您想停留 8 天,则每个奖励日为 5 欧元”。感谢您的启发,我认为将这些原则视为指导原则而不是必须做的事情很好。 我们可以对上面的示例代码应用桥接或适配器模式来解耦两个变量概念 - 1.不同的计算(销售额,每小时) 2.不同的支付方案(每月,每周)。我的观点是我们可以应用反思来改进您的设计,并且您可以进行正面设计。 @Thurein - 是的,我们可以增加额外的灵活性,但要付出额外的努力和复杂性。如果我们设计得好,那么重构就很容易,我们可以决定是现在还是以后做。在我设计的示例中,很明显会有更多种类的员工,因此您的桥梁可能会从一开始就进入。一般来说,我建议在灵活性和简单性之间取得平衡。 “你不需要它”是一个很好的提醒。【参考方案3】:

开放-封闭原则意味着您不必更改现有代码,因此它对修改是封闭的,但为了满足新的要求,您需要使用子类、实现接口、设计模式来扩展代码,以便您的代码对开放这个活动。在重构时,您将面临需要更改代码的原因,但您必须以一种方式来满足 OSP。

例如,您可以创建工厂方法,而不是创建散布在代码周围的类似对象的新实例。当新的 requiremet 来添加一个新对象时,您的代码将关闭以进行修改(代码中没有新实例)但打开以进行修改(扩展工厂方法)。

【讨论】:

以上是关于业务逻辑发生变化时如何尊重开闭原则?的主要内容,如果未能解决你的问题,请参考以下文章

开闭原则

6大设计原则之开闭原则

设计模式 开闭原则

面向对象设计原则二:开闭原则(OCP)

由于开闭原则处理继承层次结构

设计模式六大原则:开闭原则