1

请告诉我,如果我在这个例子中以正确的方式应用Tell, don't ask原则。

我有两个类,CalculationResults有一个函数calculateMe(),用于Data进行一些计算。重要的是它存储结果。

class Data {
private:
  int dataForCalculations;
public:
  void calculate(CalculationResults& calculationResults) {
    calculationResults.calculateMe(dataForCalculations);
  }
};

class CalculationResults {
private:
  int calculatedData;
public:
  void calculateMe(int dataForCalculations) {
    calculatedData = someCalculations(dataForCalculations);
  }
};

// somewhere else:
Data data;
CalculationResults calculationResults;
data.calculate(calculationResults);

这段代码的第一个版本(在应用Tell 之前,不要问)没有使用Data::calculate函数,但它有一个getterfor dataForCalculations,所以我在某个地方调用了calculationResults.calculateMe(data.getDataForCalculations()).

新版本更好吗?

4

1 回答 1

5

新版本更好吗?

这取决于你问谁。但可以肯定的是,新版本是 100% 告诉,不要问。这很容易分辨,因为您的方法返回 void。

就个人而言,我一直在尝试纯粹地遵循告诉,不要问原则,并且出于几个原因放弃了它。

一方面,告诉,不问原则会导致概念上令人困惑的对象交互。以您的代码为例。我不希望一个Data对象能够自行计算。我希望Data成为其他东西的输入。

作为另一个例子。如果我正在编写一个模拟呼叫某人的程序,我可能有一个Phone, 和PhoneNumber, 和一个Person对象。现在,根据tell,don't ask,你应该用数据询问对象来完成某个动作。所以,在这种情况下PhoneNumber可能有一个 dial() 方法:phoneNumber.dial(). 但这在概念上有意义吗?真的, a 将 aPerson拨入PhoneNumbera Phone

所以,这是我的第一个问题。我发现它更难理解,而且我发现更难想出对象之间的自然交互与告诉,不要问,这让我放慢了速度。

其次,当两个对象需要共享数据时,通常不清楚应该首先调用哪个对象。以 aBook和 aPen为例。你说book.writeWith(pen)还是pen.writeOn(book)?也许可以用那个例子来争论,但很多时候你会发现差异是任意的,我讨厌这样。

第三,告诉,不要问,一个对象会慢慢建立越来越多的责任。你告诉对象自救吗?你告诉它展示自己吗?如果您拥有不止一种视图技术怎么办?如果您需要以不同的格式显示您的对象怎么办?你要求你的对象给自己发电子邮件吗?拥有一个具有许多职责的对象并不一定是坏事。它的更改不太灵活,但提供了更容易使用 API。然而,大多数人更喜欢灵活性,并且拥有一个责任很少的对象是 SOLID 代码的一部分。

第四,通过使用tell、don't ask(当你需要共享数据时)让你的对象将它的私有传递给其他对象和拥有一个getter之间究竟有什么区别?不多,如果你问我。

我知道这是非常基于意见的,但我更喜欢您的第一个版本,因为它更简单、更清晰。但是,我会把它写成:

calculationResults.calculate(data);

无论如何,只是我的2美分。

于 2015-06-17T23:52:55.610 回答