9

アプリケーションの内部で使用されるインターフェイスを設計しようとしています。Google の例に従って、私は公開 API の乱雑さを減らすよう努めています。ただし、最小限のメソッドに関して定義されている便利なメソッドがいくつかあります。利便性と整理整頓のバランスをとるには、どのような要素を考慮する必要がありますか?

Google の例: HashBiMap( doc ):

BiMap に getKeyForValue() メソッドがないのはなぜですか?

私たちはそれについて考えました (Doug Lea は半分冗談で teg()! という名前を付けることを提案しました)。しかし、実際には必要ありません。inverse().get() を呼び出すだけです。

Google コレクションに関するよくある質問

Setインターフェイスでの例:add()remove()は最小限のメソッドですが、addAll()removeAll()は便宜上のものです。addAll()の観点から実装できるadd()ため、クライアントにSet. ただし、クライアント コードはクリーンアップされます。

Utilityより便利なメソッドを含むクラスを作成することを検討しました。しかし、私は OOP から離れており、操作対象のオブジェクトをすべての呼び出しに引数として含める必要があります。私はそれがJavaのCollectionsクラスの例に従っていると思いますが。

4

9 に答える 9

4

クラスがクライアントよりも効率的な方法でその API を実装できる可能性がある場合はいつでも、追加の API を確実に提供します。(たとえばSet.removeAll().) そして一般的に、クライアント コードをクリーンアップするたびに、追加の API を提供します。

クライアントが複数の呼び出しを行うことを支持して、一見便利な便利なメソッドを提供しない Google API の例を挙げていただけますか?

于 2010-01-01T04:57:29.460 に答える
4

より多くのメソッドを提供すると、仮想メソッドのオーバーライドがより困難/危険になります。

たとえば、add() と addAll() を考えてみましょう。addAll() は add() を呼び出しますか? それは可能ですが (要素ごとに順番に add() を呼び出す単純なラッパーの可能性があります)、そうする必要はありません。したがって、サブクラス化し、新しい不変条件を追加すると (たとえば、 add() で別のコンテナーに何かを追加して挿入順序を保存するなど、さまざまなアプリケーションで役立つコンテナーにはさまざまなバリエーションがあります)。 、addAll()がadd()を呼び出すかどうかを知る必要があります。そうであれば、サブクラスは正しい動作を維持します。しかし、そうする必要はありません!

確かに、適切なドキュメントを通じてこれらすべてを解決できます。しかし、それは危険なことをより簡単にします。

一般に、より良いアプローチは、クラス インターフェイスを最小限で、直交し、完全なものにしてから、これらの便利なユーティリティ メソッドを非メンバー非フレンドにすることです。これにより、パブリック インターフェイスのみを呼び出すことができることが明確になり、問題全体が回避されます。

ときどき、ユーティリティをメソッドにすることで (非メンバ非フレンドではなく) 実装上の優位性が得られる状況が発生します。この例はソートです。一般に、(配列、両端キュー、ベクトルなどの) 並べ替えは非メンバー、非フレンドでなければなりませんが、リンクされたリストの場合、sort() をメソッドにすることには特に利点があります。具体的には、メソッドはノード リンクを操作できるため、インプレース マージ ソートを使用できます。これは、適切なリンク リスト インターフェイスでは困難または不可能です。これらの例外的なケースでは、ユーティリティ メソッドをオーバーライドできないようにし、それらが呼び出すメソッドを明示的に示すことをお勧めします (そして、それが意味のある場合は、どの順序で)。これにより、サブクラスが壊れない可能性が最大になります。

于 2010-01-01T05:34:25.900 に答える
2

John F.の答えに便乗します:

私は、便利だと思うすべての便利なメソッドが必要です。他のすべての便利なメソッドは必要ありません。Firefox は、この種のことをプラグインで対応します。ブラウザは、基本的なブラウザがサポートするものをサポートしています。ただし、個人的な好みに合わせて、プラグインで強化できます。私は便利なメソッドを同じ観点から見ています。

好きなモジュールを追加できるので、必要な便利なメソッドだけを使用できます。

これには多くの側面があります。

http://martinfowler.com/bliki/HumaneInterface.html

于 2010-08-09T20:27:58.953 に答える
1

これにはいくつかの可能なアプローチがあります。他の場所で使用されているのを私が見たのは、最小限のコア API と、コアをより便利にする「拡張機能」または「ユーティリティ」API を使用することですが、サポートされることは保証されていません。

一般に、開発者コミュニティが十分に大きくなると、API 用に独自の拡張機能、ヘルパー、およびユーティリティを作成します。

于 2010-01-01T04:59:56.860 に答える
1

1 つの解決策は、便利なメソッドを実装するインターフェイスと抽象実装の両方を提供することです。例として、比較します。

interface List ...

class AbstractList implements List ...

java.utilパッケージに。したがって、クライアントは抽象クラスからサブクラス化し、抽象メソッドを実装するだけです。

しかし個人的には、便利なメソッドをユーティリティ クラスに入れることを恥じることはありません。壊れた言語で純粋な OO をプログラムすることはできません。ここで Java が見逃しているのは、特性または拡張メソッドのいずれかです。私の知る限り、拡張メソッドは Java 7 で議論されています。

于 2010-01-01T05:13:25.600 に答える
0

ユーティリティ メソッドが本当に有用であり、単なる想像の産物ではない限り (「人狼が米国を征服するなら、いつか役立つかもしれない」)、元のクラスにそれらを追加します。

あなたの例に従って、 addAll() と removeAll() は妥当なユーティリティ メソッドであり、Set に追加する必要があります。しかし、 addEven() と removeEven() は、たとえ特定のケースで役立つかもしれないとしても、合理的ではありません。

では、どの方法が合理的かをどのように検出するのでしょうか? 経験と経験の2つの方法のみ。

実際のシナリオでクラスを試して、一般的なケースでどのユーティリティ メソッドが本当に役立つかを確認する必要があります。

于 2010-01-01T05:03:26.440 に答える
0

ソースを見なくても、最初に ArrayList.addAll によって容量が十分に大きくなるため、操作の実行中に配列のサイズが変更されないようになると思います。これは内部実装の詳細であるため、ユーティリティ クラスでは不可能です。

したがって、答えは、クラスの内部でユーティリティメソッドを実行できるようにする必要があるかどうかによって異なります。そうでない場合は、クラスから移動するための強力な議論があります。そうでない場合は、クラスの一部にする必要があります。

于 2010-01-01T05:09:59.820 に答える
0

別の参照ポイント: JavaListには と の両方がadd()ありaddAll()ます。

重要なことは、自分の中でどれが基本でどれが便利かを明確にすることだと思います。それぞれ、アトミック(これ以上細分化できない) および化合物(アトミック メソッドを組み合わせて形成できる) とも呼ばれます。

基本的なメソッドを認識することは、コードに関することを証明するのに非常に役立ちます。また、ユーザーが実際にコードを使用して何でもできるようにするため、コードは完全です (たとえば、便利なメソッド内でのみ使用できる機能がないことを確認してください)。

別の言い方をすれば、ライブラリの目的は有用であることです。便利なメソッドを使用すると、より使いやすくなりますが、そもそもライブラリが役に立たない場合は役に立ちません。基本的な方法は、コードが完全であることを保証するのに役立ちます(数学的完全性の側面)。ただし、そもそもライブラリが役に立たない場合は役に立ちません。

言い換えれば、100% 役に立つものにすることに集中し、そこから使いやすさと完全性を引き出します。

于 2010-01-01T05:20:40.337 に答える
0

より簡素化された API を提供しながら、必要に応じてユーザーにより多くの機能を提供するための私の推奨方法は、コア コマンドのサブセットを提供するインターフェイスを API に実装させることです。このようにして、ユーザーは単純にしたい場合はインターフェイスを介してアクセスでき、addAllUsersExceptOnesNamedJeff() にアクセスしたい場合は実際のクラスを介してアクセスできます。

于 2010-01-01T13:29:42.293 に答える