タイトルに記載されているように、C#で使用されるパラメータなどのオプションのパラメータは有用ですか、それともアプリケーションのメンテナンスの妨げになり、コードを理解しにくくするために避けるべきですか?
タイトルに記載されているように、C#で使用されるパラメータなどのオプションのパラメータは有用ですか、それともアプリケーションのメンテナンスの妨げになり、コードを理解しにくくするために避けるべきですか?
回答:
私の経験では、オプションのパラメーターは良いことでした。常にデフォルト値を取得して、何が呼び出されているかを知ることができるので、それらを混乱させることはありません(少なくとも実際の関数ほど混乱することはありません)。
それらの用途の1つは、すでに一般的に使用されている関数、または少なくともパブリックインターフェイスで別のパラメーターを追加する必要がある場合です。それらがなければ、別の引数を持っている関数を呼び出すために元の関数をやり直す必要があり、引数を複数回追加すると、それは本当に古くなる可能性があります。
new Circle(size, color, filled, ellipseProportions)
場所size
やcolor
必須などの引数を追加するオーバーロードされたメソッドで価値があり、残りはデフォルトです。
一般に、多くの/オプションのパラメーターが頻繁に必要な場合、関数の実行が多すぎるため、分割する必要があります。SRP(単一責任原則)に違反している可能性があります。
グループ化できるパラメーターを探します。たとえば(xとy、ポイントになります)。
これらのオプションのパラメータはデフォルトのフラグですか?フラグを使用している場合、関数を分割する必要があります。
これは、オプションのパラメーターを使用すべきではないということではありませんが、一般的に、1つまたは2つ以上のパラメーターがコードのにおいを示唆しています。
また、関数が実際にはクラスであり、オプションのパラメーターがプロパティに変更され、必要なパラメーターがコンストラクターの一部である必要があるという手掛かりになる場合もあります。
オプションのパラメーターは問題ありません
通常、正当な理由は、a)メソッドの引数がたくさんある可能性があるが、APIが乱雑になるのを恐れてオーバーロードしたくないということ、またはb)可能な引数がすべてわからないときにユーザーに強制的に配列を提供させたくない。いずれの場合も、オプションのパラメーターがきちんとエレガントな方法で助けになります。
ここではいくつかの例を示します。
1.オーバーロードを避けたい、配列を指定したくない
C、Perl、Javaなどのprintf()を見てください。これは、オプションのパラメーターの威力を示すすばらしい例です。
例えば:
printf("I want %d %s %s",1,"chocolate","biccies");
printf("I want %d banana",1);
オーバーロード、配列、シンプルで直感的ではありません(標準の文字列形式コードを理解したら)。一部のIDEでは、フォーマット文字列がオプションのパラメーターと一致しない場合でも通知します。
2.デフォルトの使用を許可し、メソッドのユーザーから非表示にしたい
sendEmail( "test@example.org");
sendEmailメソッドは、さまざまな必須値が欠落していることを検出し、定義済みのデフォルト(subject、body、cc、bccなど)を使用してそれらを埋めます。APIはクリーンでありながら柔軟です。
パラメーターが多すぎることに注意
ただし、他の人が述べているように、メソッドに必須のパラメーターが多すぎるということは、おそらく設計に何か問題があることを示しています。開発者が偶然に切り替えて実行時に奇妙な結果をもたらす可能性があるため、同じタイプを共有している場合、これは特に当てはまります。
String myMethod(String x, String y, String z, String a, int b, String c, int d) {}
Introduce Parameter Objectリファクタリングを作成する理想的な候補です
String myMethod(ParameterObject po) {}
class ParameterObject {
// Left as public for clarity
public String x;
public String y;
... etc
}
これにより、指定された仕様をパラメーターオブジェクトとして持つFactoryパターンに基づいて、より優れたデザインを作成できます。
それはあなたのコードが何をしているかに依存します。賢明なデフォルトがある場合はオプションのパラメーターを使用する必要がありますが、賢明なデフォルトがない場合はオプションのパラメーターを追加するとコードがより複雑になります。多くの場合、オプションのパラメーターは、nilチェックを回避し、分岐ロジックを切り取るための適切な方法です。Javascriptにはオプションのパラメーターはありませんが、||でそれらをエミュレートする方法があります (論理的または)データベース関連のものを実行するときに常に使用します。ユーザーが値を提供しない場合、||の助けを借りて自分の値を置き換えるからです。これにより、大量のif thenステートメントを記述する手間が省けます。
オプションのパラメーターは、単純なものを単純なものと複雑なものを同時に可能にする優れた方法です。少なくとも迅速で汚いユースケースで、ほとんどのユーザーが望む明確で合理的なデフォルトがある場合、関数を呼び出すたびに手動で指定するために定型句を記述する必要はありません。一方、人々がそれを変更したいと思う正当な理由があるかもしれないならば、それは暴露される必要があります。
クラスを使用することは、クラスが行うことの典型的なメンタルモデルと冗長で非効率的で一貫性がないため、ひどい解決策です。関数は、動詞の完璧な抽象化です。つまり、何かをして戻ります。クラスは名詞の正しい抽象化です。つまり、状態を持ち、いくつかの方法で操作できるものです。前者をAPIユーザーのメンタルモデルにする必要がある場合は、クラスにしないでください。
オプションの引数の問題は、関連するコードを新しい関数に抽出するのではなく、関数に対する引数がますます増えているということです。これはphpで極端に行われます。例えば:
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
[, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
私は当初、Pythonでこの機能を気に入っており、既に使用されているメソッドを「拡張」するためにそれを使用しました。それは見た目も簡単でしたが、すぐに戻ってきました。オプションのパラメーターを追加すると、古いクライアントが依存していた既存のメソッドの動作が、既存のユニットテストケースでキャッチされない方法で変更されたためです。基本的にこれを行うことは、Open Closed Principleを破ることです。コードは拡張のために開かれていますが、変更のために閉じられています。したがって、この機能を使用して既存のコードを変更することはお勧めできません。しかし、最初から使用する場合は大丈夫
オプションのパラメーターを使用するよりも、異なるシグネチャ(つまりパラメーター)で関数をオーバーロードする方が良いと思います。