最近、私は自分のAPIを開発しており、そのAPI設計への投資に対する関心から、API設計を改善する方法に強い関心を持っています。
数回出てきた1つの側面は(私のAPIのユーザーではなく、トピックに関する私の観察中の議論):APIを呼び出すコードを見るだけで、APIやっている。
たとえば このGitHubでの議論についての議論 リポジトリを参照してください。次のようになります。
_foo.update_pinned(true, true);
_
(パラメーター名やドキュメントなどを知らなくても)コードを見るだけでは、コードが何をするのかを推測することはできません。2番目の引数はどういう意味ですか?推奨される改善は、次のようなものにすることです。
_foo.pin()
foo.unpin()
foo.pin_globally()
_
これで問題が解決しました(2番目の引数はfooをグローバルに固定するかどうかでした)、この場合、後者は確実に改善されることに同意します。
ただし、異なるが論理的に関連する状態を設定するメソッドは、個別のメソッド呼び出しではなく、1つのメソッド呼び出しとして公開する方がよい場合があると思います(== --- ==)。コードを見てください。 (そのため、パラメーター名とドキュメントを調べて調べる必要があります。個人的には、APIに慣れていない場合でも、個人的には常にそうします)。
たとえば、1つのメソッドSetVisibility(bool, string, bool)
を FalconPeer で公開し、次の行を見ただけで確認します。
_falconPeer.SetVisibility(true, "aerw3", true);
_
あなたはそれが何をしているのか分からないでしょう。論理的な意味でのfalconPeer
の「可視性」を制御する3つの異なる値を設定しています。結合要求を受け入れ、パスワードのみを使用して、検出要求に応答します。 これを3つのメソッド呼び出しに分割すると、APIのユーザーが「可視性」の1つの側面を設定して、1つのメソッドを公開するだけで考えさせる他の設定を忘れてしまう可能性があります。 「可視性」のすべての側面を設定します。さらに、ユーザーが1つのアスペクトを変更したい場合、ほとんどの場合、別のアスペクトを変更する必要があり、1回の呼び出しで変更できます。
これを3つのメソッド呼び出しに分割しないことの望みは完全に理解できますが、ブールパラメータ以外のオプションもあります。
列挙型を使用できます:
falconPeer.SetVisibility(JoinRequestOptions.Accept, "aerw3", DiscoveryRequestOptions.Reply);
またはフラグ列挙型(言語がサポートしている場合):
falconPeer.SetVisibility(VisibilityOptions.AcceptJoinRequests | VisibilityOptions.ReplyToDiscoveryRequests, "aerw3");
または、 Parameter Object を使用できます。
var options = new VisibilityOptions();
options.AcceptJoinRequests = true;
options.ReplyToDiscoveryRequest = true;
options.Password="aerw3";
falconPeer.SetVisibility(options);
パラメーターオブジェクトパターンには、他にも役立ついくつかの利点があります。これにより、一連のパラメータの受け渡しとシリアル化が容易になり、指定されていないパラメータに「デフォルト」値を簡単に指定できます。
または、ブールパラメータを使用することもできます。マイクロソフトは常に.NET Framework APIでそれを行うようですので、肩をすくめて「彼らにとって十分であれば、私にとっても十分です」と言うだけで済みます。
当然、このルールには常に例外がありますが、自分でよく説明したように、読み取り可能なAPIを使用することには特定の利点があります。ブール引数は、1)インテントを明らかにしないこと、2)ブールフラグに応じて異なることが発生するため、実際に2つ必要な関数を呼び出すことを意味するため、特に厄介です。
主な質問は、APIを読みやすくするためにどれだけの労力を費やしたいかということです。外側を向くほど、より多くの努力を簡単に正当化できます。他の1つのユニットでのみ使用されるAPIであれば、それほど大きな問題ではありません。 REST APIについて話している場合、全世界がそれに負けようと計画しているのであれば、理解しやすくするためにさらに努力する必要があります。
あなたの例については、単純な解決策があります:どうやら、あなたの場合、可視性は単なる真実か偽りのものではありません。代わりに、「可視性」と見なすものの全体セットがあります。 1つの解決策は、Visibility
クラスのようなものを導入することです。これは、これらすべての異なる種類の可視性をカバーします。これらを作成するためのビルダーパターンをさらに適用すると、次のようなコードが作成される可能性があります。
Visibility visibility = Visibility.builder()
.acceptJoinRequests()
.withPassword("aerw3")
.replyToDiscoveryRequests()
.build();
falconPeer.setVisibility(visibility);