メソッドを引数の名前(タイプではなく)だけで区別するのに十分ですか、それともより明示的に名前を付けた方が良いですか?
たとえば、T Find<T>(int id)
とT FindById<T>(int id)
です。
引数名だけを維持するよりも、明示的に名前を付ける(つまり、ById
を追加する)正当な理由はありますか?
考えられる理由の1つは、メソッドのシグネチャが同じでも、意味が異なる場合です。
FindByFirstName(string name)
およびFindByLastName(string name)
もちろん、より明確に名前を付けるのには十分な理由があります。
説明が必要なのは主にメソッドdefinitionではなく、メソッドseです。そして、findById(string id)
とfind(string id)
はどちらも一目瞭然ですが、findById("BOB")
とfind("BOB")
の間には大きな違いがあります。前者の場合、ランダムリテラルは実際にはIDであることがわかります。後者の場合、あなたは確信が持てません-それは実際には与えられた名前か何か他のものかもしれません。
FindById()の利点。
Future-proofing:Find(int)
で開始し、後で他のメソッド(FindByName(string)
、FindByLegacyId(int)
、FindByCustomerId(int)
、FindByOrderId(int)
など)、私のような人々はFindById(int)
を探すために年齢を重ねる傾向があります。本当に問題ではありませんifできますし、必要に応じてFind(int)
をFindById(int)
に変更します-将来の証明はこれらについてですifs。
読みやすい。 Find
は、呼び出しがrecord = Find(customerId);
のようであれば完全に問題ありませんが、record = FindById(AFunction());
の場合、FindById
の方が読みやすいです。
一貫性。 FindByX(int)
/FindByY(int)
パターンはどこでも一貫して適用できますが、Find(int X)
/Find(int Y)
は競合するため不可能です。
Find()の利点
Find
は単純明快で、_operator[]
_と並んで、このコンテキストで最も期待される2つの関数名の1つです。 (一部の一般的な代替案は、コンテキストに応じて get
、lookup
、またはfetch
です)。FindById(int id)
を見ると、冗長性をFind(int id)
に変更することで簡単に削除できますが、トレードオフがあり、明確さが失われます。または、厳密に型指定されたIDを使用して、両方の利点を得るを行うことができます。
_CustomerRecord Find(Id<Customer> id)
// Or, depending on local coding standards
CustomerRecord Find(CustomerId id)
_
_Id<>
_の実装: C#でID値を強く入力
ここのコメントと上記のリンクから、_Id<Customer>
_に関して複数の懸念がありました。
CustomerId
とOrderID
は異なる型(_customerId1 = customerId2;
_ =>良い、_customerId1 = orderId1;
_ =>悪い)ですが、それらの実装はほとんど同じです。コピーペーストまたはメタプログラミングを使用して実装できます。ジェネリックの公開または非表示についての議論には価値がありますが、メタプログラミングはジェネリックの目的です。DoSomething(int customerId, int orderId, int productId)
。強く型付けされたIdは、OPが尋ねたものを含む他の問題も防ぎます。int aVariable
_に保持されているかどうかを判別するのは困難です。 Idが_Id<Customer> aVariable
_で保持されていることは簡単にわかります。さらに、それが顧客IDであることもわかります。String
は、_byte[]
_の単なるラッパーです。ラップ、つまりカプセル化は、強い型付けと競合しません。Equals
だけに依存したくない場合は、_operator==
_および_operator!=
_も追加することをお勧めします。。
_public struct Id<T>: {
private readonly int _value ;
public Id(int value) { _value = value; }
public static explicit operator int(Id<T> id) { return id._value; }
}
_
これについてのもう1つの考え方は、言語のタイプセーフを使用することです。
次のようなメソッドを実装できます。
Find(FirstName name);
ここで、FirstNameは、名を含む文字列をラップする単純なオブジェクトであり、メソッドが何をしているのか、それを呼び出す引数に混乱がないことを意味します。
FindByIDのような明示的な宣言に投票します。..変更のためにソフトウェアを構築する必要があります。開いて閉じている必要があります(SOLID)。したがって、クラスは開いていて、FindByNameなどの同様の検索メソッドを追加できます。
ただし、FindByIDはクローズされており、その実装はユニットテストされています。
述語を持つメソッドはお勧めしません。述語はジェネリックレベルで優れています。フィールド(ByID)に基づいている場合は、完全に異なる方法論があるとします。
次のような述語を使用するよう提案された人がいないことに驚きます。
User Find(Predicate<User> predicate)
このアプローチでは、APIの表面を縮小するだけでなく、それを使用するユーザーにより多くの制御を提供します。
それで十分でない場合は、いつでも必要に応じて拡張できます。