单一职责 (SRP) vs 告诉不要问 (TDA)?
Single Responsibility(SRP) vs Tell Don't Ask(TDA)?
我了解在某些情况下许多设计原则会相互冲突。因此,我们必须权衡它们,看看哪个更有利。
直到现在我都知道 SRP 原则并且完全基于它做了我的很多设计但是在内部我在遵循时有时会感到错误
这个原则。现在我开始了解 TDA ,我的感觉得到了更多的支持:)
SRP :-对象应该担心自己而不是其他人
TDA :- 行为(仅取决于其对象状态)应保留在对象本身内部
示例:- 我有不同的形状,如矩形、正方形、圆形等。现在我必须计算面积。
到目前为止我的设计:- 我一直在关注 SRP,其中我有 AreaCalculatorService class,它会询问形状状态并计算面积。这种设计背后的原因
形状不应该担心面积计算,因为它不是形状责任。但理想情况下,我曾经认为面积计算代码应该位于每个形状下
就好像如果出现新的形状,我必须修改 AreaCalculatorService class(这违反了开放扩展和修改关闭原则(OECM))。
但总是优先考虑SRP。好像错了
神话被打破(至少我的):- 使用 TDA,看起来我的感觉是正确的,我不应该询问对象的状态,而是告诉形状计算它的面积。尽管
它会违反 SRP 原则,但会支持 OECM 原则。正如我所说,设计原则有时会相互冲突,但我相信行为在哪里
完全依赖于它的对象状态,行为和状态应该在一起。
另一个例子:-说我要计算一个组织中所有员工的所有部门的工资,那么我们应该遵循SRP where SalaryCalculatorService
将取决于部门和员工。
它会询问每个员工的薪水,然后对所有薪水进行求和。所以在这里我要求员工的状态但是
仍然没有违反 TDA calcSalary 不仅仅取决于每个员工的薪水。
让我知道我对这两个原则的解释是否正确,在第一种情况下我应该遵循 TDA 而在第二种情况下应该遵循 SRP?
我认为你对TDA的理解是正确的。
问题在于 SRP,根据我的经验,这是最容易被误解的 SOLID 原则。
SRP 说一个 class 应该只有一个改变的理由。 "reason to change" 部分经常与 "it should have only one responsibility" 混淆,因此 "it must do only one thing"。不,不是那样的。
"reason to change" 完全取决于 class 所在的应用程序的上下文。特别是它取决于与软件交互的参与者,并且将来可以要求更改。
参与者可以是:为软件付费的客户、普通用户和一些超级用户。将管理应用程序数据库的 DBA 或处理运行应用程序的硬件的 IT 部门。一旦你枚举了软件周围的所有参与者,为了遵循 SRP 所说的,你必须以一种只有一个单一责任的方式编写你的 class,因此只有来自一个参与者的请求可能需要一些class.
的变化
所以,我认为您应该遵循 TDA,将数据和使用这些数据的行为放在同一个对象中。通过这种方式,您可以管理对象之间的关系,告诉它们做什么而不是询问数据,减少耦合并达到更好的封装。
如上所述的 SRP 将指导您决定将哪些行为放在一个对象而不是另一个对象中。
我了解在某些情况下许多设计原则会相互冲突。因此,我们必须权衡它们,看看哪个更有利。 直到现在我都知道 SRP 原则并且完全基于它做了我的很多设计但是在内部我在遵循时有时会感到错误 这个原则。现在我开始了解 TDA ,我的感觉得到了更多的支持:)
SRP :-对象应该担心自己而不是其他人
TDA :- 行为(仅取决于其对象状态)应保留在对象本身内部
示例:- 我有不同的形状,如矩形、正方形、圆形等。现在我必须计算面积。
到目前为止我的设计:- 我一直在关注 SRP,其中我有 AreaCalculatorService class,它会询问形状状态并计算面积。这种设计背后的原因 形状不应该担心面积计算,因为它不是形状责任。但理想情况下,我曾经认为面积计算代码应该位于每个形状下 就好像如果出现新的形状,我必须修改 AreaCalculatorService class(这违反了开放扩展和修改关闭原则(OECM))。 但总是优先考虑SRP。好像错了
神话被打破(至少我的):- 使用 TDA,看起来我的感觉是正确的,我不应该询问对象的状态,而是告诉形状计算它的面积。尽管 它会违反 SRP 原则,但会支持 OECM 原则。正如我所说,设计原则有时会相互冲突,但我相信行为在哪里 完全依赖于它的对象状态,行为和状态应该在一起。
另一个例子:-说我要计算一个组织中所有员工的所有部门的工资,那么我们应该遵循SRP where SalaryCalculatorService 将取决于部门和员工。
它会询问每个员工的薪水,然后对所有薪水进行求和。所以在这里我要求员工的状态但是 仍然没有违反 TDA calcSalary 不仅仅取决于每个员工的薪水。
让我知道我对这两个原则的解释是否正确,在第一种情况下我应该遵循 TDA 而在第二种情况下应该遵循 SRP?
我认为你对TDA的理解是正确的。
问题在于 SRP,根据我的经验,这是最容易被误解的 SOLID 原则。
SRP 说一个 class 应该只有一个改变的理由。 "reason to change" 部分经常与 "it should have only one responsibility" 混淆,因此 "it must do only one thing"。不,不是那样的。
"reason to change" 完全取决于 class 所在的应用程序的上下文。特别是它取决于与软件交互的参与者,并且将来可以要求更改。
参与者可以是:为软件付费的客户、普通用户和一些超级用户。将管理应用程序数据库的 DBA 或处理运行应用程序的硬件的 IT 部门。一旦你枚举了软件周围的所有参与者,为了遵循 SRP 所说的,你必须以一种只有一个单一责任的方式编写你的 class,因此只有来自一个参与者的请求可能需要一些class.
的变化
所以,我认为您应该遵循 TDA,将数据和使用这些数据的行为放在同一个对象中。通过这种方式,您可以管理对象之间的关系,告诉它们做什么而不是询问数据,减少耦合并达到更好的封装。
如上所述的 SRP 将指导您决定将哪些行为放在一个对象而不是另一个对象中。