web-dev-qa-db-ja.com

定数を定義するインターフェースを持つことは悪い習慣ですか?

Javaでjunitテストクラスのセットを書いています。たとえば、さまざまなテストクラスで必要になる文字列など、いくつかの定数があります。それらを定義し、すべてのテストクラスがそれを実装するインターフェースについて考えています。

私が目にする利点は次のとおりです。

  • 定数への簡単なアクセス:MY_CONSTANT の代わりに ThatClass.MY_CONSTANT
  • 各定数は一度だけ定義されます

このアプローチは、良いまたは悪い習慣ですか?そうするのは、インターフェースの概念を悪用するようなものです。

インターフェース/定数について一般に答えることができますが、何か特別なことがあればユニットテストについても答えることができます。

45
FabianB

Joshua Blochは、彼の著書Effective Javaでこれに対して助言しています:

クラスがいくつかの定数を内部的に使用することは、実装の詳細です。定数インターフェースを実装すると、この実装の詳細がクラスのエクスポートされたAPIにリークします。クラスが定数インターフェースを実装することは、クラスのユーザーにとって重要ではありません。実際、それらを混乱させることさえあるかもしれません。さらに悪いことに、これはコミットメントを表しています。将来のリリースでクラスが変更され、定数を使用する必要がなくなった場合でも、バイナリ互換性を確保するためにインターフェイスを実装する必要があります。

定数を定義する通常のクラスで同じ効果を得ることができ、次にimport static com.example.Constants.*;を使用します

88
matt

私たちのケースでは、定数の値が、サービス実装が提供する必要がある最終状態の規約を表すため、これを行っています。これらの定数をインターフェイスに配置すると、契約の一部として最終状態が指定されます。インターフェイスの実装がそれらを使用しなかった場合、その状態は機能しません。

SOMETIMES定数は実装の詳細です。時にはそうではありません。いつものように、エンジニアは自分の脳を使って何をすべきかを決める必要があり、抜本的なパターンや練習に頼る必要はありません。

14
user144901

定数を持つためのインターフェースonlyがあるのは良いことではないと思います。

しかし、振る舞いを定義するインターフェース(クラスを実装するメソッドが実装する必要がある)に定数がある場合、それは問題ありません。それが「APIに一部の実装者の詳細を漏らす」場合、それは本来あるべき姿だからです。また、実装者が.foo()および.bar()メソッドを実装していることもリークしています。

たとえば、_Java.awt.Transparency_インターフェイスを見てみましょう。 OPAQUEBITMASKTRANSLUCENT定数がありますが、.getTransparency()メソッドもあります。

設計者がこれらの定数をそこに置いたのは、.getTransparency()がそうであるように、インターフェースの一部になるのに十分安定していると彼/彼女が考えたからです。

6

私が働いていた会社がインターフェースインポートを多用しました1 定数。害はないと思います。

あなたが自問しなければならない質問は次のとおりですあなたにとって名前空間はどれほど重要ですか?定数の場合、それはクラスが実際に振る舞うすべてのことです。何千もの定数がある場合、それらすべての定数を常に利用できるようにしたくない場合があります。

インターフェースの優れた点は、どちらの方法でも作業できるという利点があることです。つまり、必要なすべての名前空間を組み込むか、まったく使用しない(そしてMyInterface.CONSTANTで明示的にアクセスする)ことができます。 import static MyInterface.*とほとんど同じですが、もう少し明白です。


1:Javaに慣れていない場合は、importキーワードを意味しているのではなく、implements MyConstantsInterfaceを介して導入されていることを意味します

2
Nicole

契約によるデザインが普及している場所で最も人気のある視点だと思います。
インターフェイスは契約です。定数をインターフェイスに配置するということは、コントラクトを遵守するすべてのクラスが、定数によって識別される値/概念に同意することを意味します。

2
CMR

いいえ、それは一般的な悪い習慣ではありません。

重要なのは、他のアーティファクトと同様に、定数は最小限の可視性と適切な抽象化レベルのルールの下で導入する必要があるということです。

構文を使用するのは本当の問題です。

1
oopexpert

私は主に「エイダの方法」と「。ネットの方法」に主に影響を受けているバックグラウンドを持っています。いえ、インターフェイス内で定数を宣言するのはおそらく最善ではないでしょう。 c#では技術的に許可されていません。

私がノーと言う理由は、インターフェースは状態や構造ではなく、動作を定義するコントラクトの形式であるためです。定数は、ある種の状態(プリミティブ)、または状態の側面(複合または集約)を意味します。

デフォルトと事前定義値をインターフェースを実装するすべての人が利用できるようにしたいという衝動に感謝しますが、デフォルトの状態は、抽象または値オブジェクトまたはテンプレートでより適切に説明され、デフォルトには少なくとも最小限のコンテキストがあります。

より技術的なガイドについては、download.Oracle.com/javase/1.5.0/docs/guide/language/static-import.html

1
JustinC