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
- If classB.属性1 = "Something1" then call soap service,get some integer value, perfome some arithmatical calculation
使用常量,并将结果分配给 classA.Property2
- Else If classB.属性1 = "Something2" then call soap service,get some integer value, and assign the result to
classA.Property2
- 否则将 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。基本上,逻辑将从 ClassA
和 ClassB
中抽象出来。相反,领域事件会处理它。事件对象将收到一条消息,其中包含对 ClassA
和 ClassB
的引用,处理它,分配它需要的任何值(或者更好的是,将它们传递给 类 通过受控方法),然后完成。这使得计算行为更易于测试,并允许您在多个地方重复使用该组件。
我会创建一个 DDD 类型 'domain service',它通过接口依赖于 SOAP 服务,并以这种方式进行。很好,可测试,我不明白为什么它不符合 OCP。
应避免使域模型依赖于外部服务。
我有一个名为 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
- If classB.属性1 = "Something1" then call soap service,get some integer value, perfome some arithmatical calculation 使用常量,并将结果分配给 classA.Property2
- Else If classB.属性1 = "Something2" then call soap service,get some integer value, and assign the result to classA.Property2
- 否则将 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。基本上,逻辑将从 ClassA
和 ClassB
中抽象出来。相反,领域事件会处理它。事件对象将收到一条消息,其中包含对 ClassA
和 ClassB
的引用,处理它,分配它需要的任何值(或者更好的是,将它们传递给 类 通过受控方法),然后完成。这使得计算行为更易于测试,并允许您在多个地方重复使用该组件。
我会创建一个 DDD 类型 'domain service',它通过接口依赖于 SOAP 服务,并以这种方式进行。很好,可测试,我不明白为什么它不符合 OCP。
应避免使域模型依赖于外部服务。