web-dev-qa-db-ja.com

多くのゲッターとセッターを扱う

私はすでに「 大きなインターフェースを扱う 」と尋ねました。

その状況についてさらに質問があります。ゲッターやセッターを多用していて、カプセル化を破ったことが指摘されました。私はこれを知っていますが、これをどのように異なる方法でコーディングするか本当に想像できません。私のゲッターはすべて自然に見えます。UIで直接反応する情報を公開します。この方法でどのように改善できますか?

元の質問のコード:

public interface ISystemSolver
{
    // Configuration
    int NumberBase { get; set; }
    bool CaseSensitive { get; set; }
    bool LeadingZeros { get; set; }

    // State
    IReadOnlyList<int> ForbiddenValues { get; }
    IReadOnlyList<char> ForbiddenVariables { get; }
    event EventHandler OnTooManyVariables;
    bool AreThereTooManyVariables { get; }

    // Variables
    IEnumerable<Variable> Variables { get; }
    void RemoveVariable(int index);
    void AddVariable(char variable, int value);

    // Equations
    IEnumerable<Equation> Equations { get; }
    void RemoveEquation(int index);
    void AddEquation(string equation);

    // Solving
    IEnumerable<Solution> Solve();
}

編集:ForbiddenValuesForbiddenVariablesの使用法

private void UpdateVariablesComboBox()
{
    // Get the forbidden variables
    var forbiddenVariables = _manager.ForbiddenVariables;

    // Get the variables that are not forbidden
    var items = _manager.Variables
        .Where(c => !forbiddenVariables.Contains(c))
        .Select(c => c.ToString())
        .Cast<object>()
        .ToArray();

    // Clear the combo box
    _variablesComboBox.Items.Clear();

    // Update the combo box
    _variablesComboBox.Items.AddRange(items);
}

private void UpdateValuesComboBox()
{
    // Get the current number base
    var currentBase = _manager.NumberBase;

    // Get the forbidden values
    var forbiddenValues = _manager.ForbiddenValues;

    // Get possible values that are not forbidden
    var items = Enumerable.Range(0, currentBase)
        .Where(i => !forbiddenValues.Contains(i))
        .Select(i => i.ToString())
        .Cast<object>()
        .ToArray();

    // Clear the combo box
    _valuesComboBox.Items.Clear();

    // Update the combo box
    _valuesComboBox.Items.AddRange(items);
}
3
Patrik Bak

ゲッター

ゲッターはオブジェクトを裏返します。彼らはこのデータをすべての人に提供すると言っています。私は情報を保存する場所です。あなたがこのことについて何かをしたいなら、あなたはそれをしなければなりません。

カプセル化

むしろ、それを隠す方が良いと尋ねるすべてのものにあなたの状態をあきらめます。その状態で実行する必要があることはすべて、その状態を保持するクラスのメソッドで実行する方が適切です。これにより、データと関連メソッドが一緒に収集されます。次に、それがどれだけ暑いかを尋ね、_thermostat.on()と言うだけで家を暖めるか冷やすかを決定する必要があります。

境界

GUIに表示したり、保存したり、ポートに送信したりするなど、境界を越えて状態を公開したい場合が多いため、ほとんどの人にとってこれを行う方法を理解することは困難です。

実際、これらのものにデータを送信するには、データを公開する必要があります。しかし、それはあなたのデータが公開されて生きるべきであることを意味しません。私はむしろthermostat.display()の次にthermostat.getTemp()を参照したいと思います。

それで、どうすればその仕事をすることができますか?まああなたのビューがそれを呼び出すことを可能にするインターフェースを提供したなら、その状態をビューにだけ意図的に状態を送ることができると尋ねる誰にでもその状態を公開するのではなく。ビューは、UIに送信する前に必要なロジック(CとF)を実行できます(実際にはロジックはありません)。

この方法で行うと、状態がどの程度公開されているかを簡単に制限できます。私たちは境界を越えていたので、ビューにそれを持たせることに同意しました。その境界の反対側には、サーモスタットオブジェクトに引き込めない動作ニーズがあります。この場合の動作は、ユーザーが温度を見ることです。中を吸うのは難しい。しかし、熱やACをオンにするなどのことは吸い込まれる可能性があるため、他の場所に実装されて走り回る理由はありません。

ポリモーフィズム

このように機能することで本当に強力なのは、ポリモーフィズムです。 thermostat.on()は、thermostatの設定に応じて、あらゆる種類の実装を持つことができます。確かに、温度が異なるだけでなく、on()の完全に異なる実装である可能性もあります。

この方法でコードを書くと、あらゆる種類の変更を驚くほど簡単に行えることがわかります。結局のところ、これはソフトウェアのポイントです。簡単に変更できます。それがソフトウェアを柔らかく保つものです。

ゲッターの削除

したがって、ゲッターを使用するすべてのものをよく見てください。いったんそれを得たら、それで何をしているのですか?それは得たものに基づいて決定を下していますか?もしそうなら、それはオブジェクトにくっつくことを考慮する行動です。そうでない場合、それは何らかの境界を越えて出て行くのですか?もしそうなら、彼らが彼らに送って欲しいものを受け入れる方法を境界に提供させてください。そうすれば、彼らは尋ねる必要がなく、何を尋ねるべきかを知る必要もありません。

これらの2つの活動により、ゲッターの必要性が大幅に削減されます。実際に状態を非表示にする動作オブジェクトの作成を開始します。しかし、場合によっては、実際に必要なデータのバッグが必要なだけです。それで大丈夫です。これらの値オブジェクトを呼び出します。ストリングは最も人気のあるものです。値オブジェクトがそれだけであることを確認してください。値。両方になろうとしている奇妙なハイブリッドを作らないでください。値オブジェクトを使用して、境界を越えるものを一緒に扱います。

同じものの異なる名前

これは新しい考えではありません。実際、これがオブジェクト指向プログラミングの核心です。 polymorphism多くの場所で呼ばれています、「教えてください、尋ねないでください " Andy Hunt、Dave ThomasMartin Fowler 、そして Alec Sharp のような昔ながらのOOPersはそれを呼び出すメッセージパッシング "。そうしないと、Martin Fowlerには The Feature Envy Smell という名前の匂いがします。

細部

ゲッターを使用すると、詳細が得られます。詳細は必要ありません。あなたはそれを行う方法を知っている何かによって行われる何かを望んでいます。詳細は控えてください。

13
candied_orange
  1. これらの変更可能なプロパティはすべて変更可能である必要がありますか?自分でソルバーに取り組んだのではないかと思います。
  2. 「構成」可変プロパティを受け取り、それらをクラスの不変フィールドに変換します。コンストラクタを使用してそれらを初期化します。これはにつながります...
  3. 代わりに基本クラスを使用できる場合は、インターフェースの使用を停止してください。これにより、コンストラクターを使用して不変フィールドを初期化できるようになります。
  4. ソルバーは何をしますか?方程式を解くのに必要な期間よりも長い期間存在する必要がありますか?私はそうは思わない。次に、ソルバーを操作オブジェクトの一種と見なす必要があります。ソルバーを初期化し、緩めに設定して、進行状況を監視します。状態を変更することはありません。これは、操作にアプローチするためのより堅牢な方法であり、より不変性を使用できます。
  5. ソルバーが完了すると、解決策の試行に関する情報を含む結果オブジェクトを返すことができます。
  6. ドキュメントがないので、変数のプロパティが正確に何を意味するのかわかりません。しかし、変数の正当性を判断するプロセスを別のクラスに委任できる場合もあります。
1
Frank Hileman