请告诉我,如果我正在应用Tell,请不要在此示例中以正确的方式询问原则。
我有两个类,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);
Run Code Online (Sandbox Code Playgroud)
这段代码的第一个版本(在应用Tell之前,不要问)没有使用Data::calculatefunction 但它有一个getterfor dataForCalculations,所以我在某处调用了calculationResults.calculateMe(data.getDataForCalculations()).
新版本更好吗?
新版本更好吗?
这取决于你问谁。但可以肯定的是,新版本是 100% 告诉,不要问。这很容易判断,因为您的方法返回 void。
就我个人而言,我一直试图完全遵循告诉,不问原则,并且出于几个原因放弃了它。
一方面,告诉,不要问原则会导致概念上混淆对象交互。以您的代码为例。我不希望一个Data对象能够计算自己。我希望Data成为其他东西的输入。
再举一个例子。如果我正在编写一个模拟呼叫某人的程序,我可能有一个Phone、 和PhoneNumber和一个Person对象。现在,根据告诉,不要问,你应该问有数据的对象来完成某个动作。所以,在这种情况下,PhoneNumber可能会对它拨号()方法:phoneNumber.dial()。但这在概念上有意义吗?真的, a 将 aPerson拨入PhoneNumbera Phone。
所以,这是我的第一个问题。我发现它更难理解,而且我发现很难在对象与告诉,不要问之间进行自然交互,这让我慢了下来。
其次,当两个对象需要共享数据时,通常不清楚应该首先调用哪个对象。以 aBook和 aPen为例。你说book.writeWith(pen)还是pen.writeOn(book)?也许可以用那个例子来论证,但很多时候你会发现差异是任意的,我讨厌这样。
第三,用告诉,不要问,一个对象会慢慢积累越来越多的责任。你告诉对象自救吗?你告诉它显示自己吗?如果您有多个视图技术怎么办?如果需要以不同格式显示对象怎么办?你要求你的对象给自己发电子邮件吗?拥有一个承担许多责任的对象并不一定是坏事。更改的灵活性较低,但提供了更易于使用的 API。然而,大多数人更喜欢灵活性,并且拥有一个责任很少的对象是 SOLID 代码的一部分。
第四,让你的对象通过使用告诉,不要问(当你需要共享数据时)将它的私有传递给其他对象和使用 getter 之间的真正区别是什么?不多,如果你问我。
我知道这是非常基于意见的,但我更喜欢你的第一个版本,因为它更简单、更清晰。但是,我将其写为:
calculationResults.calculate(data);
Run Code Online (Sandbox Code Playgroud)
无论如何,只是我的 2 美分。