30

Tell, don't ask Principle hereは、私が getter や setter を使用するときによく貼り付けられますが、人々はそれらを使用しないように言っています。このサイトは、私がすべきこととすべきでないことを明確に説明していますが、質問する代わりに、なぜ私が言うべきかを実際には説明していません. ゲッターとセッターを使用すると、はるかに効率的であり、より多くのことができるようになりました。


Warrior属性healthとを持つクラスを想像してくださいarmor:

class Warrior {
    unsigned int m_health;
    unsigned int m_armor;
};

今、誰かが私の戦士を特別な攻撃で攻撃し、彼のアーマーを 5 秒間減少させます。セッターを使用すると、次のようになります。

void Attacker::attack(Warrior *target)
{
    target->setHealth(target->getHealth() - m_damage);
    target->setArmor(target->getArmor() - 20);
    // wait 5 seconds
    target->setArmor(target->getArmor() + 20);
}

そして、言うと、原則を尋ねないでください。それは次のようになります(間違っている場合は修正してください):

void Attacker::attack(Warrior *target)
{
    target->hurt(m_damage);
    target->reduceArmor(20);
    // wait 5 seconds
    target->increaseArmor(20);
}

明らかに 2 番目の方が優れているように見えますが、これの本当のメリットはわかりません。同じ量のメソッド ( increase/decreaseset/ get) が依然として必要であり、尋ねる必要があるかどうかを尋ねる利点が失われます。たとえば、戦士の体力を 100 に設定するにはどうすればよいでしょうか? と のどちらを使うべきhealhurt、また、癒すか傷つけるのにどれだけのヘルスが必要かをどのように判断しますか?

また、セッターとゲッターが世界最高のプログラマーによって使用されていることも知っています。ほとんどの API で使用されており、標準ライブラリで常に使用されています。

for (i = 0; i < vector.size(); i++) {
    my_func(i);
}
// vs.
vector.execForElements(my_func);

そして、ここにいる人々が私にリンクしている 1 つの記事を信じて、質問せずに話すことを信じるか、大企業 (アップル、マイクロソフト、アンドロイド、ほとんどのゲームなど) の 90% を信じるかを決める必要がある場合は、多くのお金を稼ぎ、プログラムを実行しましたが、なぜ教えてくれるのか理解するのはちょっと難しいです。

ゲッターとセッターを使用するとすべてが簡単に見えるのに、なぜそれを使用する必要があるのですか?

4

4 に答える 4

2

そうだとすれば、ゲッターとセッターをわざわざ使う必要があるのでしょうか。パブリックフィールドを持つことができます。

void Attacker::attack(Warrior *target)
{
    target->health -= m_damage;
    target->armor -= 20;
    // wait 5 seconds
    target->armor += 20;
}

理由は簡単です。カプセル化。セッターとゲッターがある場合、パブリック フィールドに勝るものはありません。ここでは構造体を作成しません。定義されたセマンティクスを使用して、プログラムの適切なメンバーを作成します。

記事引用:

ここでの最大の危険は、オブジェクトからデータを要求しても、データしか取得できないことです。オブジェクトを取得していません—大きな意味ではありません。クエリから受け取ったものが構造的にオブジェクト (たとえば、文字列) であっても、意味的にはオブジェクトではなくなります。所有者オブジェクトとの関連付けはなくなりました。内容が「RED」である文字列を取得したからといって、その文字列にそれが何を意味するのかを尋ねることはできません。所有者の姓ですか?車の色?タコメーターの現状は?オブジェクトはこれらのことを知っていますが、データは知りません。

ここの記事では、意味のないことはできないので、「聞かないで教えて」の方がよいと示唆しています。

target->setHealth(target->getArmor() - m_damage);

鎧は健康とは何の関係もないので、ここでは意味がありません。

また、ここで std lib を間違えました。ゲッターとセッターはでのみ使用されstd::complex、それは言語が機能を欠いているためです (当時 C++ には参照がありませんでした)。実際は逆です。C++ 標準ライブラリは、アルゴリズムの使用を奨励し、コンテナーで行うべきことを伝えます。

std::for_each(begin(v), end(v), my_func);
std::copy(begin(v), end(v), begin(u));
于 2013-05-19T14:19:07.173 に答える
1

頭に浮かぶ理由の 1 つは、コントロールを配置する場所を決定できることです。

たとえば、セッター/ゲッターの例では、呼び出し元は戦士の健康を任意に変更できます。せいぜい、セッターが最大値と最小値を適用して、ヘルスが有効なままであることを確認するだけです。ただし、"tell" フォームを使用すると、追加のルールを適用できます。一度に一定量以上のダメージや回復を許可しない場合があります。

このフォームを使用すると、Warrior のインターフェースをより細かく制御できます。許可される操作を定義でき、それらを呼び出すすべてのコードを書き直すことなく実装を変更できます。

于 2013-05-19T14:20:16.297 に答える
0

私の見解では、どちらのコードも同じことを行います。違いはそれぞれの表現力にあります。最初のもの (セッターとゲッター) は、2 番目のもの (教えて、聞かないでください)よりも表現力があります。

質問すると、決定を下すことになるのは事実です。しかし、ほとんどの場合、それは起こりません。オブジェクトの値を知りたい、または設定したい場合がありますが、これはtell, don't ask では不可能です。

もちろん、プログラムを作成するときは、オブジェクトの責任を定義し、これらの責任がオブジェクト内のみに留まり、アプリケーションのロジックをオブジェクトの外に出すことが重要です。これはすでにわかっていますが、オブジェクトの責任ではない決定を下すように依頼する必要がある場合、tell, don't askでどのようにそれを行うのでしょうか?

実際には、getter と setterが優勢ですが、言うことはよくありますが、一緒に尋ねることはありません。つまり、一部の API には getter と setter があり、またtell, don't ask idea のメソッドもあります。

于 2013-05-19T14:33:25.207 に答える