OOP——责任去哪里

OOP - Where does the responsibility go

我有一个名为 A 的 class 和另一个名为 B 的 Class。Class A 包含 Class B 作为 属性。

我有一个业务逻辑。根据 Class B 中 a 属性 的值,我必须计算 Class A 中另一个 属性 的值。要进行此计算,我必须调用 a SOAP 服务,获取一个值,然后根据 Class B 中的 属性 的值,我必须对 SOAP 服务返回的值进行数学计算,然后设置 属性 在 Class A.

public Class A{
  public string Property1{get;set;}
  public int Property2{get;set;}
  public B Property3{get;set;}
}

public class B{
 public string Property1{get;set;}
 public string Property2{get;set;}
}

The logic in pseudocode

  1. If classB.属性1 = "Something1" then call soap service,get some integer value, perfome some arithmatical calculation 使用常量,并将结果分配给 classA.Property2
  2. Else If classB.属性1 = "Something2" then call soap service,get some integer value, and assign the result to classA.Property2
  3. 否则将 classA.Property2 设置为默认值。

我不喜欢 If else,它不遵循 OCP。我正在考虑与装饰师一起做这件事。第二种选择是使用构建器模式并封装 if else 逻辑,但它仍然会破坏 OCP。还是可以执行此操作的全新域服务?但是即使我选择了域服务方式,如果否则,OCP 仍然会被破坏。

以上逻辑正在业务逻辑中执行class。

那么上面的计算逻辑责任到哪里去了呢? 还有如何避免这种情况?

我们确实需要 "what these values are" 和 "will they be used in any other ways now or in the future" 的更多详细信息,以便能够清楚地说明它们应该去哪里。

也就是说,首先,我们可以将您的伪代码清理为:

Get a value from Class B.
If that value is equal to "foo":
   call SOAP service
   do math
   assign value to property2
Else if it's equal to "bar":
   call SOAP service
   assign value to property2
Else
   assign default value to property2

如果没有其他方法可以让任何人从 class B 调用此值,并且您的代码也没有其他调用 SOAP 服务,则此功能可能应该在 class B 中,对外部调用者隐藏逻辑。

DDD中,ClassA是这个场景下的聚合根,应该是处理这个逻辑的。 ClassB 可以 引用 ClassA;我个人更喜欢让我的关系成为一种严格的、单向的关系。意思是 ClassB 没有 知道 ClassA 存在。在某些极端情况下我违反了这条规则;虽然不多。

相反,我会使用 Domain events to facilitate this. There are a few good examples of this online to look at。基本上,逻辑将从 ClassAClassB 中抽象出来。相反,领域事件会处理它。事件对象将收到一条消息,其中包含对 ClassAClassB 的引用,处理它,分配它需要的任何值(或者更好的是,将它们传递给 类 通过受控方法),然后完成。这使得计算行为更易于测试,并允许您在多个地方重复使用该组件。

我会创建一个 DDD 类型 'domain service',它通过接口依赖于 SOAP 服务,并以这种方式进行。很好,可测试,我不明白为什么它不符合 OCP。

应避免使域模型依赖于外部服务。