私はすでに「 大きなインターフェースを扱う 」と尋ねました。
その状況についてさらに質問があります。ゲッターやセッターを多用していて、カプセル化を破ったことが指摘されました。私はこれを知っていますが、これをどのように異なる方法でコーディングするか本当に想像できません。私のゲッターはすべて自然に見えます。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();
}
編集:ForbiddenValues
とForbiddenVariables
の使用法
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);
}
ゲッターはオブジェクトを裏返します。彼らはこのデータをすべての人に提供すると言っています。私は情報を保存する場所です。あなたがこのことについて何かをしたいなら、あなたはそれをしなければなりません。
むしろ、それを隠す方が良いと尋ねるすべてのものにあなたの状態をあきらめます。その状態で実行する必要があることはすべて、その状態を保持するクラスのメソッドで実行する方が適切です。これにより、データと関連メソッドが一緒に収集されます。次に、それがどれだけ暑いかを尋ね、_thermostat.on()
と言うだけで家を暖めるか冷やすかを決定する必要があります。
GUIに表示したり、保存したり、ポートに送信したりするなど、境界を越えて状態を公開したい場合が多いため、ほとんどの人にとってこれを行う方法を理解することは困難です。
実際、これらのものにデータを送信するには、データを公開する必要があります。しかし、それはあなたのデータが公開されて生きるべきであることを意味しません。私はむしろthermostat.display()
の次にthermostat.getTemp()
を参照したいと思います。
それで、どうすればその仕事をすることができますか?まああなたのビューがそれを呼び出すことを可能にするインターフェースを提供したなら、その状態をビューにだけ意図的に状態を送ることができると尋ねる誰にでもその状態を公開するのではなく。ビューは、UIに送信する前に必要なロジック(CとF)を実行できます(実際にはロジックはありません)。
この方法で行うと、状態がどの程度公開されているかを簡単に制限できます。私たちは境界を越えていたので、ビューにそれを持たせることに同意しました。その境界の反対側には、サーモスタットオブジェクトに引き込めない動作ニーズがあります。この場合の動作は、ユーザーが温度を見ることです。中を吸うのは難しい。しかし、熱やACをオンにするなどのことは吸い込まれる可能性があるため、他の場所に実装されて走り回る理由はありません。
このように機能することで本当に強力なのは、ポリモーフィズムです。 thermostat.on()
は、thermostat
の設定に応じて、あらゆる種類の実装を持つことができます。確かに、温度が異なるだけでなく、on()
の完全に異なる実装である可能性もあります。
この方法でコードを書くと、あらゆる種類の変更を驚くほど簡単に行えることがわかります。結局のところ、これはソフトウェアのポイントです。簡単に変更できます。それがソフトウェアを柔らかく保つものです。
したがって、ゲッターを使用するすべてのものをよく見てください。いったんそれを得たら、それで何をしているのですか?それは得たものに基づいて決定を下していますか?もしそうなら、それはオブジェクトにくっつくことを考慮する行動です。そうでない場合、それは何らかの境界を越えて出て行くのですか?もしそうなら、彼らが彼らに送って欲しいものを受け入れる方法を境界に提供させてください。そうすれば、彼らは尋ねる必要がなく、何を尋ねるべきかを知る必要もありません。
これらの2つの活動により、ゲッターの必要性が大幅に削減されます。実際に状態を非表示にする動作オブジェクトの作成を開始します。しかし、場合によっては、実際に必要なデータのバッグが必要なだけです。それで大丈夫です。これらの値オブジェクトを呼び出します。ストリングは最も人気のあるものです。値オブジェクトがそれだけであることを確認してください。値。両方になろうとしている奇妙なハイブリッドを作らないでください。値オブジェクトを使用して、境界を越えるものを一緒に扱います。
これは新しい考えではありません。実際、これがオブジェクト指向プログラミングの核心です。 polymorphism多くの場所で呼ばれています、「教えてください、尋ねないでください " Andy Hunt、Dave Thomas & Martin Fowler 、そして Alec Sharp のような昔ながらのOOPersはそれを呼び出すメッセージパッシング "。そうしないと、Martin Fowlerには The Feature Envy Smell という名前の匂いがします。
ゲッターを使用すると、詳細が得られます。詳細は必要ありません。あなたはそれを行う方法を知っている何かによって行われる何かを望んでいます。詳細は控えてください。