5

副作用のないセッターをどこまで使うかについて、あなたの意見を聞きたいと思います。

次の例を考えてみましょう。

Activity activity;
activity.Start    = "2010-01-01";
activity.Duration = "10 days";   // sets Finish property to "2010-01-10"

日付と期間の値は、表示のみを目的として示されていることに注意してください。

Startしたがって、いずれかのプロパティにsetterを使用すると、FinishDurationのプロパティが変更されるため、副作用がないと見なすことはできません。Rectangle同じことがクラスのインスタンスにも当てはまります。ここで、setterforXはなどの値を変更しTopますBottom

問題は、論理的に関連するプロパティの値を変更するという副作用があるセッターを使用することと、とにかくこれ以上説明できないメソッドを使用することの間に、どこで線を引くかです。たとえば、呼び出されるメソッドを定義SetDurationTo(Duration duration)しても、開始または終了のいずれかが変更されることは反映されません。

4

5 に答える 5

10

プログラムの設計に当てはまる「副作用」という言葉を誤解していると思います。プロパティの設定は、ある種の状態が変化する限り、内部状態がどれだけ変化しても、少し変化しても、副作用です。「副作用のないセッター」はあまり役に立ちません。

副作用は、プロパティゲッターで避けたいものです。プロパティの値を読み取ることは、呼び出し元が状態を変更することを期待しない(つまり、副作用を引き起こす)ため、変更する場合、通常は間違っているか、少なくとも疑わしいものです(遅延読み込みなどの例外があります)。しかし、ゲッターとセッターは同様に、とにかくメソッドの単なるラッパーです。DurationCLRに関する限り、プロパティはメソッドの単なる構文糖衣ですset_Duration

これはまさに、クラスなどの抽象化の目的です。一貫した内部状態を維持しながら、粗粒度の操作を提供します。単一のプロパティ割り当てで複数の副作用が発生しないように意図的に試みると、クラスはダムデータコンテナにすぎなくなります。

だから、質問に直接答える:どこに線を引くのですか?メソッド/プロパティがその名前が意味することを実際に実行する限り、どこにもありません。Durationも変更した場合ActivityNameは、問題になる可能性があります。それがプロパティを変更する場合、それFinishは明白であるはずです。を変更して、とを同じに保つこと不可能です。OOPの基本的な前提は、オブジェクトがこれらの操作を単独で管理するのに十分インテリジェントであるということです。DurationStartFinish

これが概念レベルで気になる場合は、ミューテータープロパティをまったく使用しないでください。必要なすべての引数がコンストラクターで提供される、読み取り専用プロパティを持つ不変のデータ構造を使用してください。次に、2つのオーバーロードがあります。1つはStart/を取りDuration、もう1つはStart/を取りFinishます。または、プロパティの1つだけを書き込み可能にし(たとえばFinish、一貫性を保つようにStart)、Duration読み取り専用にします。可変プロパティと不変プロパティの適切な組み合わせを使用して、特定の状態を変更する方法が1つしかないことを確認します。

そうでなければ、これについてはそれほど心配しないでください。プロパティ(およびメソッド)に意図しないまたは文書化されていない副作用があってはなりませんが、それが私が使用する唯一のガイドラインです。

于 2010-03-16T03:40:12.250 に答える
1

個人的には、一貫した状態を維持するために副作用があることは理にかなっていると思います。あなたが言ったように、論理的に関連する値を変更することは理にかなっています。ある意味で、副作用が予想されます。しかし、重要なことはその点を明確にすることです。つまり、メソッドが実行しているタスクに何らかの副作用があることは明らかです。したがって、代わりにSetDurationTo関数を呼び出すことができます。ChangeDurationToこれは、何か他のことが起こっていることを意味します。AdjustDurationTo期間を調整して値を渡す関数/メソッドを使用することで、これを別の方法で行うこともできdeltaます。関数を副作用があるものとして文書化すると役立ちます。

別の見方をすると、副作用が予想されるかどうかを確認することだと思います。top長方形の例では、の値を変更するかbottom、内部的に一貫性のある状態を維持することを期待しています。これが主観的なものかどうかはわかりません。それは私には理にかなっているようです。いつものように、私はドキュメントが勝つと思います。副作用がある場合は、それを十分に文書化してください。できれば、メソッドの名前とサポートドキュメントを使用してください。

于 2010-03-16T03:24:32.537 に答える
1

1つのオプションは、クラスを不変にし、メソッドに、すべての適切な値が変更されたクラスの新しいインスタンスを作成して返すようにすることです。そうすれば、副作用やセッターはありません。のようなものをDateTime呼び出すことができ、変更が適用された新しいインスタンスを返すようなものを考えてください。AddDaysAddHoursDateTime

于 2010-03-16T03:24:40.033 に答える
0

publicパブリックセッターの呼び出し元は何が起こるかわからないため、副作用のないプロパティでセッターを許可しないという一般的なルールに常に取り組んできましたが、もちろん、アセンブリ自体を変更する人は、彼らはコードを見ることができるので、かなり良い考えです。

もちろん、読みやすさのため、オブジェクトモデルを論理的にするため、または単に物事を正しく機能させるために、ルールを破らなければならない場合が常にあります。あなたが言ったように、実際には一般的に好みの問題です。

于 2010-03-16T03:23:28.603 に答える
-2

それはほとんど常識の問題だと思います。

この特定の例では、私の問題は、「関連する」プロパティを調整するプロパティがあるということではありません。文字列値を取得するプロパティがあり、それを内部でDateTime(またはその他の)値に解析しているということです。

私はむしろこのようなものを見たいです:

Activity activity;
activity.Start    = DateTime.Parse("2010-01-01");
activity.Duration = Duration.Parse("10 days");

つまり、文字列の解析を行っていることに明示的に注意します。必要に応じて、プログラマーが強い型のオブジェクトを指定できるようにします。

于 2010-03-16T03:24:37.133 に答える