OOP - 责任在哪里

时间:2015-06-30 03:59:16

标签: oop design-patterns domain-driven-design solid-principles ooad

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

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

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;}
}
  

伪代码中的逻辑

  1. 如果classB.property1 =" Something1"然后调用soap服务,获取一些整数值,进行一些算术计算 使用常量,并将结果分配给classA.Property2
  2. 否则如果classB.property1 =" Something2"然后调用soap服务,获取一些整数值,并将结果分配给 classA.Property2
  3. 然后将classA.Property2设置为默认值。
  4. 我不喜欢If else,它不遵循OCP。我想与装饰师这样做。第二个选项是使用构建器模式并封装if else逻辑,但它仍会破坏OCP。或者是一个可以执行此操作的全新域服务?但是,如果其他人选择采用域服务方式,那么OCP仍然会被破坏。

    上述逻辑正在业务逻辑类中执行。

    那么上述计算逻辑的责任在哪里呢? 如果还有其他如何避免呢?

3 个答案:

答案 0 :(得分:1)

DDD中,ClassA是此方案中的聚合根,应该是处理此逻辑的根。 ClassB 可以引用ClassA;我个人更喜欢让我的关系成为一种严格的,单向的关系。含义ClassB 不会知道ClassA存在。有一些边缘情况我违反了这个规则;虽然不是很多。

相反,我会使用Domain events来促进这一点。 There are good examples在线look at Form Elements here。基本上,逻辑将从ClassAClassB中抽象出来。相反,域事件会处理它。事件对象将被赋予一条消息,其中包含对ClassAClassB的引用,处理它,分配它需要的值(或者更好的是,通过受控方法将它们传递给类),并完成。这使计算的行为更加可测试,并允许您在多个位置重用此组件。

答案 1 :(得分:1)

我会创建一个DDD类型的“域服务”,它通过接口依赖SOAP服务并以这种方式执行。很好,可测试,我不明白为什么它不符合OCP标准。

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

答案 2 :(得分:0)

我们真的需要更多关于这些价值的详细信息"并且"它们现在或将来会以任何其他方式使用"能干净利落地告诉他们应该去哪里。

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

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

如果没有其他人从B类调用此值,并且没有其他调用从您的代码到SOAP服务,则此功能应该在B类中,以隐藏外部逻辑呼叫者。