【问题标题】:Single Responsibility(SRP) vs Tell Don't Ask(TDA)?单一职责(SRP)与告诉不要问(TDA)?
【发布时间】:2016-11-05 12:29:16
【问题描述】:

我了解许多设计原则在某些情况下会相互冲突。所以,我们必须权衡它们,看看哪一个更有益。 直到现在我才知道 SRP 原则,并且完全基于它做了很多设计,但在内部,我在遵循时有时会感觉错了 这个原则。现在我了解了 TDA,我的感觉得到了更多的支持:)

SRP :- 对象应该担心自己的问题,而不是其他人

TDA :- 行为(仅取决于其对象状态)应保留在对象本身内部

示例:-我有不同的形状,如矩形、正方形、圆形等。现在我必须计算面积。

到目前为止我的设计:- 我一直在关注 SRP,在那里我有 AreaCalculatorService 类,它会询问形状状态并计算面积。这种设计背后的原因 形状不应该担心面积计算,因为它不是形状的责任。但理想情况下,我曾经认为面积计算代码应该驻留在每个形状下 好像如果出现新形状,我必须修改 AreaCalculatorService 类(这违反了扩展开放和修改关闭原则(OECM))。 但总是优先考虑 SRP。这似乎是错误的

神话被打破(至少我的):- 使用 TDA,看起来我的感觉是正确的,我不应该询问对象的状态,而是告诉形状来计算它的面积。尽管 它会违反 SRP 原则,但会支持 OECM 原则。正如我所说,设计原则有时会相互冲突,但我相信行为在哪里 完全依赖于它的对象状态,行为和状态应该是在一起的。

另一个例子:- 假设我要计算一个组织中所有员工的所有部门的薪水,那么我们应该遵循 SalaryCalculatorService 所在的 SRP 将取决于部门和员工。

它会询问每个员工的工资,然后对所有工资进行求和。所以我在这里询问员工的状态,但是 仍然没有违反 TDA calcSalary 不仅仅取决于每个员工的薪水。

让我知道我对这两个原则的解释是否正确

【问题讨论】:

  • 形状的职责是什么?很难在真空中谈论这些事情。你的例子太小了。
  • 它可以是任何与形状合乎逻辑的东西,例如getName(),保持状态等
  • 该区域显然是形状界面的一部分。您甚至如何以一般方式在外部实现它?用线条还是曲线?这里没有违反 SRP,这绝对是 TDA。
  • 我想分析另一个示例,但没有充分说明。我真的不明白正在分析的问题。你为什么不为一个真正的问题创建一个真正的库,在某个地方发布它,然后讨论它的设计呢?或者选择一个现有的库。
  • There's no SRP violation here and it's definitely TDA.. 我认为这里违反了 SRP。真正意义上的单一职责意味着改变应该有单一的理由。形状的唯一职责是保持对象的状态(如面积计算)

标签: oop single-responsibility-principle design-principles tell-dont-ask


【解决方案1】:

我认为您对 TDA 的理解是正确的。 问题在于 SRP,以我的经验,这是最容易被误解的 SOLID 原则。 SRP 说一个班级应该只有一个改变的理由。 “改变的原因”部分经常与“它应该只有一项责任”因此“它必须只做一件事”相混淆。不,不是那样的。
“改变的原因”完全取决于类所在的应用程序的上下文。特别是它取决于与软件交互的参与者,以及将来可能要求更改的参与者。
参与者可能是:为软件付费的客户、普通用户和一些超级用户。管理应用程序数据库的 DBA 或处理运行应用程序的硬件的 IT 部门。一旦你枚举了你的软件周围的所有参与者,为了遵循 SRP 所说的,你必须以一种只有一个单一职责的方式编写你的类,因此只有一个参与者的请求可能需要对你的类进行一些更改.
所以,我认为你应该按照 TDA 将数据和使用这些数据的行为放在同一个对象中。通过这种方式,您可以管理对象之间的关系,告诉它们做什么而不是询问数据,减少耦合并达到更好的封装。
如上所述的 SRP 将指导您决定将哪些行为放入一个对象而不是另一个对象中。

【讨论】:

  • 除了作为人的演员之外,您还可以考虑目标应用程序。例如,您不希望在形状中直接使用 Draw 函数,因为如果您转向另一种技术(例如 Windows、控制台、Web、Open GL、Direct X.. .).
猜你喜欢
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
  • 2011-06-18
相关资源
最近更新 更多