oop - 告诉,不要问和单一职责——在类里面用数据做新的事情

标签 oop single-responsibility-principle tell-dont-ask

我有一个案例,“告诉,不要问”似乎与“单一责任”原则相冲突。我已经查看了有关该主题的其他讨论,但尚未能够为这种情况制定最合适的面向对象方法。

我有一个程序可以读取和操作来自各种来源的数据集合。我创建了一个类来保存和操作数据(“DataSet”类)。它包括对数据集执行各种操作的方法,例如比较两个数据集以生成包含差异的新数据集,以及将数据集写入文件。

我现在想对数据集执行一些分析并将结果输出到报告中。我第一次尝试对此进行编码询问数据集以从中提取信息,然后构建报告,但这似乎违背了“告诉,不要问”的原则。那么:我是否应该将分析方法放在 DataSet 类中并告诉数据集进行自我分析并生成报告?这是否违反了单一职责原则?如果我想在 future 执行其他类型的分析怎么办 - DataSet 类可能会变得非常臃肿,其中包含许多与其核心目的无关的不同分析例程。

谁能在这里建议最好的方法?是否有解决此问题的特定设计模式?

最佳答案

每当您设计软件时,您总是必须平衡不同的原则,因为其中许多是相互冲突的。例如,DRY(不要重复自己)原则经常与单一职责原则相冲突,特别是当两件事做类似但不完全相同的事情时。

很多时候,你必须决定哪个原则更重要,并强调那个原则而不是另一个原则(尽管你应该尽可能多地坚持)。很多时候,原则是一起工作的,有时它们会相互矛盾。

在这种情况下,Tell Don't Ask 与其他原则一起使用,例如 Law of Demeter (尽管它的名字仍然是一个原则,就软件而言,最好将其描述为最少知识原则)。

LoD 告诉我们的是一个对象的方法应该只调用其他方法

  • 本身
  • 在作为参数传入它的对象上
  • 使用由参数
  • 传递的对象创建/实例化的任何对象
  • 对象直接组件对象
  • 或全局变量

  • 没有具体说,但我觉得选择调用方法的优先顺序也应该是这个顺序,全局变量是最后的手段。但是,这既不是这里也不是那里。

    因此,如果我们将 Tell, Don't Ask 与 LoD 结合使用,那么将对象传递给另一个对象进行“询问”是完全可以的。意思是,您有一个 Analysis 对象,您“告诉”它做某事,将 DataSet 对象作为参数传递。这就是遵守 TDA。在 Analysis 对象的方法中,您仅通过访问“亲密 friend ”数据来遵守 LoD。

    这也符合 SRP,因为您的 DataSet 仍然只是一个 DataSet 而您的 Analysis 对象是一个 Analysis 对象。

    这里的关键是这些原则通常是“相对论的”。这意味着,从获取数据并想要执行分析的父对象的角度来看,您是在“告诉”分析对象做某事。

    TDA 的目的是您的父代码不应查询您的 DataSet 的状态,然后根据它做出决定。相反,它应该将对象传递给其他对象并让这些对象执行它们的职责,这可能包括查询这些对象的状态,但这没关系,因为这是在它们的职责范围内。

    此处进一步引用:

    http://pragprog.com/articles/tell-dont-ask

    编辑:

    如果您想要更权威的来源,没有人比 Martin Fowler 本人更好(阅读到最后,您会找到此评论)

    http://martinfowler.com/bliki/TellDontAsk.html

    But personally, I don't use tell-dont-ask. I do look to co-locate data and behavior, which often leads to similar results. One thing I find troubling about tell-dont-ask is that I've seen it encourage people to become GetterEradicators, seeking to get rid of all query methods. But there are times when objects collaborate effectively by providing information. A good example are objects that take input information and transform it to simplify their clients, such as using EmbeddedDocument. I've seen code get into convolutions of only telling where suitably responsible query methods would simplify matters 1. For me, tell-don't-ask is a stepping stone towards co-locating behavior and data, but I don't find it a point worth highlighting

    关于oop - 告诉,不要问和单一职责——在类里面用数据做新的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10709763/

    相关文章:

    java - 代号一 SQLite 数据问题

    python - 在 __init__ 处设置对象的父类(super class)?

    java - 在哪里捕获和处理空参数?

    java - 单一职责原则和服务/存储库设计

    principles - SRP & "axis of change"?

    c# - 告诉,不要问原则和密码过期

    oop - 单一职责 (SRP) 与告诉不要问 (TDA)?

    c++ - 覆盖继承的函数