私はこのAPI関数を持っています:
public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d,
string e, string f, out Guid code)
嫌いです。パラメータの順序が不必要に重要になるからです。新しいフィールドを追加するのが難しくなります。何が渡されているかを確認するのは困難です。メソッドを小さな部分にリファクタリングすることは、サブ関数ですべてのパラメータを渡すという別のオーバーヘッドが発生するため、難しくなります。コードは読みにくいです。
私は最も明白なアイデアを思いつきました:データをカプセル化するオブジェクトを持ち、各パラメーターを1つずつ渡すのではなく、渡します。これが私が思いついたものです:
public class DoSomeActionParameters
{
public string A;
public string B;
public DateTime C;
public OtherEnum D;
public string E;
public string F;
}
これにより、API宣言が次のように減少しました。
public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)
いいね。非常に無邪気に見えますが、実際には大きな変更が導入されました。可変性を導入しました。以前行っていたのは、実際には匿名の不変オブジェクト(スタック上の関数パラメーター)を渡すことでした。次に、非常に変更可能な新しいクラスを作成しました。呼び出し元の状態を操作する機能を作成しました。それは最悪です。オブジェクトを不変にしたいのですが、どうすればよいですか?
public class DoSomeActionParameters
{
public string A { get; private set; }
public string B { get; private set; }
public DateTime C { get; private set; }
public OtherEnum D { get; private set; }
public string E { get; private set; }
public string F { get; private set; }
public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d,
string e, string f)
{
this.A = a;
this.B = b;
// ... tears erased the text here
}
}
ご覧のとおり、実際に元の問題を再現しました。パラメーターが多すぎます。それが進むべき道ではないことは明らかです。私は何をしますか?このような不変性を実現する最後のオプションは、次のような「読み取り専用」構造体を使用することです。
public struct DoSomeActionParameters
{
public readonly string A;
public readonly string B;
public readonly DateTime C;
public readonly OtherEnum D;
public readonly string E;
public readonly string F;
}
これにより、パラメーターが多すぎるコンストラクターを回避し、不変性を実現できます。実際には、すべての問題(パラメーターの順序など)が修正されます。まだ:
- 誰もが(FXCopとJon Skeetを含む)パブリックフィールドを公開することは悪いことであることに同意します。
- エリック・リッパート他は言う は、不変性を読み取り専用フィールドに依存することはうそだと語っています。
そのとき、私は混乱してこの質問を書くことにしました。可変性を導入せずに「パラメーターが多すぎる」問題を回避するためのC#で最も簡単な方法は何ですか?その目的で読み取り専用の構造体を使用することは可能ですか?それでも悪いAPIデザインはありませんか?
明確化:
- 単一の責任の原則に違反していないと想定してください。私の元のケースでは、関数は与えられたパラメーターを単一のDBレコードに書き込むだけです。
- 特定の機能に対する特定の解決策を探しているのではありません。私はそのような問題への一般的なアプローチを求めています。私は特に、可変性やひどい設計を導入せずに「パラメーターが多すぎる」問題を解決することに興味があります。
更新
ここで提供される回答には、さまざまな利点/欠点があります。したがって、これをコミュニティーWikiに変換したいと思います。コードサンプルと長所/短所を含む各回答は、今後同様の問題の良いガイドになると思います。私は今それを行う方法を見つけようとしています。
DoSomeActionParameters
は、使い捨てオブジェクトであり、メソッド呼び出しの後に破棄されることになるためです。