派生した値をプロパティとして公開するのは良い形式ですか?
質問
する必要がある 7 つの潜在的な入力を考慮して重要な値を導き出す. ボブおじさん あまりにも多くのパラメータを持つ関数を避けるように促されるので、 クラスを抽出しました. 。すべてのパラメータがプロパティになったので、引数のない計算メソッドが残ります。
「それ」はプロパティである可能性はあると思いますが、それが慣用的な C# かどうかはわかりません。
したほうがいい 最終結果をプロパティとして、または引数のないメソッドとして公開します。?平均的な C# プログラマーは、プロパティがわかりにくい、または不快だと感じるでしょうか?Alt.Net の群衆についてはどうですか?
decimal consumption = calculator.GetConsumption(); // obviously derived
decimal consumption = calculator.Consumption; // not so obvious
後者の場合:したほうがいい 中間結果を [プライベート] プロパティとして宣言する, 、 また?重いおかげで メソッド抽出, 中間結果がいくつかあります。これらの多くはパブリック API の一部であるべきではありません。ただし、そのうちのいくつかは興味深いものになる可能性があり、プロパティとしてアクセスできれば式がよりきれいに見えるでしょう。
decimal interim2 = this.ImportantInterimValue * otherval;
ハッピー実験部:
VS2008 でコードをデバッグしているときに、中間結果を計算するメソッド呼び出しの上にマウスを置き続け、戻り値が表示されることを期待していることに気づきました。すべてのメソッドをプロパティに変換した後、次のことがわかりました 中間結果をプロパティとして公開すると、デバッグに非常に役立ちます。 とても満足していますが、読みやすさについては懸念が残ります。
暫定値の宣言はさらに乱雑に見えます。ただし、式は括弧を使用しない方が読みやすくなります。メソッド名を動詞で始める必要性を感じなくなりました。対照的に:
// Clean method declaration; compulsive verby name; callers need
// parenthesis despite lack of any arguments.
decimal DetermineImportantInterimValue() {
return this.DetermineOtherInterimValue() * this.SomeProperty;
}
// Messier property declaration; clean name; clean access syntax
decimal ImportantInterimValue {
get {
return this.OtherInterimValue * this.SomeProperty;
}
}
私は 10 年間 Python でコーディングを行ってきたことを説明する必要があるかもしれません。コードを書くより呼び出しやすくするために余分な時間を費やす傾向が残っています。ただし、Python コミュニティがこのプロパティ指向のスタイルを「Python 的」であるとみなすかどうかはわかりません。
def determineImportantInterimValue(self):
"The usual way of doing it."
return self.determineOtherInterimValue() * self.someAttribute
importantInterimValue = property(
lambda self => self.otherInterimValue * self.someAttribute,
doc = "I'm not sure if this is Pythonic...")
解決
ここでの重要な質問は次のとおりです。
長期的に見て、より読みやすく保守しやすいコードを生成するのはどれでしょうか?
私の個人的な意見では、個々の計算をプロパティとして分離することには、単一のモノロシックなメソッド呼び出しよりも明確な利点がいくつかあります。
使用しているクラス メソッドに関係なく、デバッガーで実行される計算を確認できます。これにより、デバッグ中の生産性が向上します。 クラス.
計算が離散的である場合、プロパティは非常に高速に実行されます。これは、(私の意見では) プロパティ設計のルールが遵守されていることを意味します。デザインのガイドラインを一律に扱うべきだと考えるのはばかげています。覚えて: 特効薬はありません。
計算がプライベートまたは内部としてマークされている場合、クラスの利用者に不必要な複雑さが追加されることはありません。
すべてのプロパティが十分に離散的であれば、コンパイラのインライン化によってパフォーマンスの問題が解決される可能性があります。
最後に、最終的な計算を返す最終メソッドが、読むことができるため保守と理解がはるかに簡単である場合、それはそれ自体で完全に説得力のある議論になります。
あなたにできる最善のことの 1 つは、自分の頭で考え、同僚や先人たちの先入観に基づいた「フリーサイズ」の概念にあえて挑戦することです。すべてのルールには例外があります。今回のケースもその一つかもしれません。
追記:私は、ほとんどの場合において標準的な資産設計を放棄すべきではないと考えています。ただし、The Standard(TM) から逸脱することが合理的であるため、逸脱することが求められる場合もあります。
他のヒント
個人的には、パブリック API をプロパティではなくメソッドとして作成することを希望します。C# では、プロパティは可能な限り「高速」であることが想定されています。このディスカッションの詳細: プロパティとメソッド
内部的には、GetConsumption は結果を得るために任意の数のプライベート プロパティを使用でき、選択はあなた次第です。
私は通常、メソッドまたはプロパティが何を行うかに従います。少し時間がかかるものであれば、ある方法を使います。非常に速い場合、またはバックグラウンドで実行される操作の数が非常に少ない場合は、それをプロパティにします。
私はオブジェクトに対するアクションやオブジェクトの状態を変更するアクションを示すためにメソッドを使用します。したがって、この場合は、他のプロパティから値を計算する関数に CalculateConsumption() という名前を付けます。
7 つの入力から値を導出し、入力ごとに 1 つずつ、計 7 つのプロパティを実装し、結果のプロパティ ゲッターがあるとします。考慮すべき点は次のとおりです。
呼び出し元が 7 つの「入力」プロパティのうち 1 つ以上を設定できなかった場合はどうなりますか?この結果はまだ意味があるのでしょうか?例外がスローされますか (例:ゼロで割る)?
場合によっては、API が発見されにくい場合があります。7 つのパラメーターを取るメソッドを呼び出す必要がある場合、結果を取得するには 7 つのパラメーターすべてを指定する必要があることがわかります。また、一部のパラメーターがオプションの場合は、メソッドのさまざまなオーバーロードによって、どれがオプションであるかが明確になります。
対照的に、「結果」プロパティにアクセスする前に 7 つのプロパティを設定する必要があることはそれほど明確ではなく、1 つを忘れやすい可能性があります。
メソッドに複数のパラメーターがある場合、より簡単に豊富な検証を行うことができます。たとえば、「パラメータ A とパラメータ B が両方とも null」の場合、ArgumentException をスローできます。
入力にプロパティを使用する場合、各プロパティは個別に設定されるため、入力の設定中は検証を実行できません。結果のプロパティが逆参照されている場合にのみ検証を実行できますが、これは直感的ではない可能性があります。