2

テスト駆動開発の関係者から、暗黙のうちに大量の情報を取得する関数を持つことは悪いことだとよく耳にします。テストの観点からこれが悪いことはわかりますが、カプセル化の観点からは必要な場合があるのではないでしょうか? 次の質問が頭に浮かびます。

Random と OrderBy を使用するのは良いシャッフル アルゴリズムですか?

基本的に、誰かが C# で配列をランダムにシャッフルする関数を作成したいと考えていました。何人かの人々は、乱数ジェネレーターをパラメーターとして渡す必要があると彼に言いました。これは、テストが容易になるとしても、カプセル化のひどい違反のように思えます。配列シャッフル アルゴリズムがシャッフルしている配列以外の状態を必要とするという事実は、呼び出し元が気にする必要のない実装の詳細ではないでしょうか? この情報を取得する正しい場所は、暗黙のうちに、おそらくスレッドローカル シングルトンからではないでしょうか?

4

3 に答える 3

10

カプセル化を破るとは思わない。配列内の唯一の状態はデータ自体であり、「ランダム性のソース」は本質的にサービスです。配列にランダム性のソースが自然に関連付けられている必要があるのはなぜですか? なぜそれがシングルトンでなければならないのですか?さまざまな要件を持つさまざまな状況についてはどうですか? たとえば、速度と暗号的に安全なランダム性などです。java.util.Randomがサブクラスを持つのには理由がありますSecureRandom:) おそらく、シャッフルの結果が多くの努力と観察によって予測可能かどうかは問題ではありません。それはコンテキストに依存し、シャッフル アルゴリズムが気にする必要のない情報です。

それをサービスと考え始めると、依存関係として渡されることが理にかなっています。

はい、スレッド ローカルシングルトンから取得することもできます (実際、これについては数日中にブログで取り上げるつもりです) 。

「サービスとしてのランダム性」の概念の利点の 1 つは、再現性を高めることです。テストが失敗した場合、Random特定のシードを指定して を渡すことができ、常に同じ結果が得られることがわかります。デバッグが容易になります。

もちろん、オプションを作成するオプションは常にありますRandom。呼び出し元が独自のものを提供しない場合は、デフォルトとしてスレッドローカル シングルトンを使用します。

于 2009-11-03T14:18:03.280 に答える
4

はい、それはカプセル化を破ります。ほとんどのソフトウェア設計の決定と同様に、これは 2 つの相反する力の間のトレードオフです。RNG をカプセル化すると、単体テスト用の変更が難しくなります。これをパラメーターにすると、ユーザーが RNG を簡単に変更できるようになります (そして、間違ってしまう可能性もあります)。

私の個人的な好みは、テストを簡単にし、デフォルトの実装 (この特定のケースでは独自の RNG を作成するデフォルトのコンストラクター) とエンド ユーザー向けの優れたドキュメントを提供することです。署名付きのメソッドを追加する

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)

これは、現在のシステム時間をシードとして使用して を作成し、Randomこのメソッドのほとんどの通常の使用例を処理します。元の方法

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)

テスト (Random既知のシードを持つオブジェクトを渡す) に使用できます。また、ユーザーが暗号的に安全な RNG が必要であると判断したまれなケースでも使用できます。1 パラメータの実装では、このメソッドを呼び出す必要があります。

于 2009-11-03T14:20:25.583 に答える
1

これはカプセル化に違反しているとは思いません。

あなたの例

RNG を提供できることは、このクラスの特徴であると言えます。私は明らかにそれを必要としない方法を提供しますが、ランダム化を複製できると便利な場合があります。

配列シャフラーが、レベル生成に RNG を使用するゲームの一部だったとしたらどうでしょう。ユーザーがレベルを保存して後でもう一度再生したい場合は、RNG シードを保存する方が効率的かもしれません。

一般的なケース

このような単一のタスクを持つ単純なクラスは、通常、内部の仕組みを明らかにすることを心配する必要はありません。それらがカプセル化するのは、そのロジックに必要な要素ではなく、タスクのロジックです。

于 2009-11-03T14:18:27.163 に答える