web-dev-qa-db-ja.com

関数にパラメーターを追加するためのベストプラクティス

私は現在非常に大規模なシステムで作業しており、200を超えるさまざまな場所から直接呼び出されるメソッドにパラメーターを追加するように求められました。

メソッドシグネチャは次のようになります。

public static bool SendMessageAndLog(long id, long userId, string message, string cc="", params Attachment[] attachments) 
{ ... }

このメッセージが関連付けられているイベントのIDを記録できるようにする必要があります。私は2つの解決策の間に行き詰まっています:

  1. まったく同じことをするがイベントIDも受け取る新しいメソッドを作成し、古いメソッドを取り除いて新しいメソッドを呼び出すようにする
  2. イベントIDにオプションのパラメーターを追加し、200回の呼び出しに名前付きパラメーターを通過して使用することは、大変な苦痛のようです

これに対する他の潜在的な解決策はありますか?これをあまりリファクタリングできないことに留意して、この場合のベストプラクティスは何でしょうか。

5
GoodPie

追加のパラメーターを使用して新しいメソッドを作成し、元のメソッドからすべてのコードを移動して、追加のパラメーターを想定どおりに使用できるようにします。元のメソッドを(追加のパラメーターなしで)そのままにします。追加のパラメーターのデフォルト値をいくつか使用して新しいメソッドを呼び出すだけで、基本的にはラッパーメソッドになります。もちろん、これは追加パラメーターのデフォルト値がある場合にのみ機能します。ない場合でも、値が呼び出しごとに異なる場合は、弾丸を噛み、全体をリファクタリングする必要があります。これは難しいことではありません。追加のパラメーターを追加して署名を壊すと、コンパイラーは他に修正が必要な場所を教えてください。

あなたの特定のケースでは、プログラムの実行中は変更されないのメッセージイベントIDマッピングがある場合、メソッドを含むクラスの内部属性としてマップを作成するだけです。メソッドの最初の行は、マップを読み取り、メッセージに基づいてイベントのIDを取得することです。次に、それを好きなように使用します。そうすれば、メソッドシグネチャを変更する必要はありません。マップの要素が多すぎるとは思わないので、このようなパフォーマンスヒットになることはありません。

24
Vladimir Stokic

受け入れられた回答に同意しますが、要件に応じて採用できる別の2つのアプローチもあります。

1。メソッドのオーバーロード

同じ名前を持ち、同じアクションを実行するが異なるパラメーターを取るc#クラスに複数のメソッドを含めることができます。確かに、コードが重複しているため、自分のシナリオに最適なアプローチではありません。起動するメソッドは、指定したパラメーターによって異なります。

public static bool SendMessageAndLog(long id, long userId, string message, string cc="", 
                                     params Attachment[] attachments) 
{ ... }

// overloaded method
public static bool SendMessageAndLog(long id, long userId, string message,  string cc="", 
                                     int eventId, params Attachment[] attachments) 
{ ... }

2。null可能パラメーター/デフォルトのパラメーター値を割り当てます

このアプローチでは、1つのメソッドを保持できますが、デフォルト値を割り当てるすべてのパラメーターは、メソッド内の最も右のパラメーターでなければなりません。つまり、後でパラメーターを追加する必要があり、メソッドを呼び出すコードを書き直すことができない場合は、新しいパラメーターにもデフォルト値を割り当てる必要があります(必要に応じてnullにすることもできます)。

また、あなたのケースではパラメータからparamsを削除する必要があるため、やはり理想的ではありません!とにかく、名前付きリストまたは配列をその場所に渡すことができる場合、私はparamsのファンではありません。

public static bool SendMessageAndLog(long id, long userId, string message, string cc="", 
                                     Attachment[] attachments, int? eventId = null) 
{ ... }

//You can now call this method in two ways...

//1)eventId param not provided so it will default to null inside method block
SendMessageAndLog(id, userId, message, attachments);

//2)eventId value provided so it will be whatever value you provide.
SendMessageAndLog(id, userid, message, attachments, eventId);   
3
Sean T