web-dev-qa-db-ja.com

Javaで定数を実装するための最良の方法は何ですか?

私はこのような例を見ました:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

また、定数をラップして静的なfinalを宣言するConstantsクラスがあるとします。私は事実上Javaをまったく知らないので、これが定数を作成するための最良の方法であるかどうか疑問に思います。

373
mk.

それは完全に受け入れられます、おそらく標準さえあります。

(public/private) static final TYPE NAME = VALUE;

ここで、TYPEは型、NAMEはスペースをアンダースコアで囲むすべて大文字の名前、そしてVALUEは定数値です。

私は強くあなたの定数をそれら自身のクラスやインターフェースに入れないでください。

補足として、finalと宣言されていて変更可能な変数は変更することができます。ただし、変数は別のオブジェクトを指すことはできません。

例えば:

public static final Point Origin = new Point(0,0);

public static void main(String[] args){

    Origin.x = 3;

}

それは正当であり、Originは(3、0)のポイントになります。

403
jjnguy

私は単一の定数クラスを持つことに対して強く勧めます。当時は良い考えかもしれませんが、開発者が定数を文書化することを拒否し、クラスが互いにまったく関連しない500以上の定数を含むようになると(アプリケーションのまったく異なる側面に関連している)、一般的に、定数ファイルは完全に読めなくなっています。代わりに:

  • Java 5+にアクセスできる場合は、enumを使用してアプリケーション領域に固有の定数を定義してください。アプリケーション領域のすべての部分は、これらの定数について、定数ではなく列挙型を参照する必要があります。あなたはクラスを宣言するのと同じようにenumを宣言することができます。列挙型は、おそらくJava 5+の最も有用な(そしておそらく間違いなく唯一の)機能です。
  • 特定のクラスまたはそのサブクラスの1つに対してのみ有効な定数がある場合は、それらをprotectedまたはpublicとして宣言し、それらを階層の最上位クラスに配置します。このようにして、サブクラスはこれらの定数値にアクセスすることができます(そして他のクラスがpublicを通してそれらにアクセスするならば、定数は特定のクラスに有効なだけではありません...定数を含むクラス
  • 振る舞いが定義されたインターフェースを持っていても、戻り値や引数値が特定であるべきなら、他の実装者がそれらにアクセスできるようにそのインターフェース上で定数を定義することは完全に受け入れ可能です。ただし、定数を保持するためだけのインターフェースを作成することは避けてください。定数を保持するためだけに作成されたクラスと同じくらい悪くなる可能性があります。
235
MetroidFan2002

定数を保持するためだけにインタフェースを使用するのは BAD PRACTICE です(Josh Blochでは 定数インタフェースパターン と命名されています)。これがJoshのアドバイスです。

定数が既存のクラスまたはインタフェースに強く結び付けられている場合は、それらをクラスまたはインタフェースに追加する必要があります。たとえば、IntegerやDoubleなどのボックスで囲まれた数値プリミティブクラスはすべて、MIN_VALUEおよびMAX_VALUE定数をエクスポートします。定数が列挙型のメンバーとして最もよく表示される場合は、 enum 型を使用してそれらをエクスポートする必要があります。それ以外の場合は、インスタンス化できないユーティリティクラスを使用して定数をエクスポートする必要があります。

例:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

命名規則について

慣例により、そのようなフィールドは大文字からなる名前を持ち、単語はアンダースコアで区切られています。これらのフィールドがプリミティブ値または不変オブジェクトへの参照を含んでいることが重要です。

120
Marcio Aguiar

Effective Java(2nd edition)では、定数には静的なintの代わりにenumを使うことをお勧めします。

ここにJavaのenumに関する良い記事があります: http://Java.Sun.com/j2se/1.5.0/docs/guide/language/enums.html

この記事の最後にある質問は次のとおりです。

それで、あなたはいつenumを使うべきですか?

の答えで:

いつでもあなたは定数の固定セットが必要です

36
shelfoo

インターフェースを使わないでください。

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

魅力的ですが、カプセル化に違反し、クラス定義の区別があいまいになります。

21
stimpy

私は以下のアプローチを使います。

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

例えば、私はConstants.DB.Connection.URLを使って定数を取得しています。それは私にとってより「オブジェクト指向」に見えます。

19
albus.ua

別のクラスで静的な最終定数を作成すると、問題が発生する可能性があります。 Javaコンパイラは実際にこれを最適化し、定数の実際の値をそれを参照するクラスに配置します。

後で 'Constants'クラスを変更し、そのクラスを参照する他のクラスでハード再コンパイルをしない場合は、使用されている古い値と新しい値の組み合わせになります。

これらを定数と考える代わりに、それらを設定パラメータと見なし、それらを管理するクラスを作成します。値が最終的でないようにし、さらにゲッターの使用を検討してください。将来的には、これらのパラメーターのいくつかがユーザーまたは管理者によって実際に構成可能であるべきだとあなたが判断したとき、それはするのがはるかに簡単になるでしょう。

17
Kevin Day

あなたがすることができる一番の間違いは、Constantsのように、一般名で呼ばれるグローバルにアクセス可能なクラスを作成することです。これは単にゴミで散らばってしまい、あなたはあなたのシステムのどの部分がこれらの定数を使っているかを理解する全ての能力を失います。

代わりに、定数はそれらを「所有する」クラスに入れるべきです。 TIMEOUTという定数がありますか。それはおそらくあなたのCommunications()またはConnection()クラスに入るべきです。 MAX_BAD_LOGINS_PER_HOUR? User()に入ります。などなど。

実行時に「定数」を定義することはできますが、ユーザーが簡単に変更することはできない場合、もう1つの用途はJavaの.propertiesファイルです。これらを.jarsにパッケージ化して、それらをClass resourceLoaderで参照することができます。

13
Yann Ramin

それは正しい道です。

一般的に定数は発見できないので not は別々の "Constants"クラスに保存されます。定数が現在のクラスに関連している場合、それらをそこに保持すると次の開発者に役立ちます。

6
Jason Cohen

私は、インターフェースを使用することが目的ではないことに同意します。このパターンを避けることは、Blochの Effective Java にもそれ自身の項目(#18)があります。

Blochが定数インターフェースパターンに対して主張しているのは、定数の使用は実装の詳細であるということですが、それらを使用するためのインターフェースの実装はエクスポートされたAPIでその実装の詳細を公開します。

public|private static final TYPE NAME = VALUE;パターンは定数を宣言する良い方法です。個人的には、すべての定数を格納するために別のクラスを作成しない方が良いと思いますが、個人的な好みやスタイル以外に、これをしない理由は見たことがありません。

定数が列挙としてうまくモデル化できる場合は、1.5以降で使用可能な enum 構造体を検討してください。

1.5より前のバージョンを使用している場合でも、通常のJavaクラスを使用して型保証された列挙をやめることができます。 (詳しくは このサイト をご覧ください)。

5
Rob Dickerson

列挙についてはどうですか?

5
Sébastien D.

私は定数よりもゲッターを使うことを好みます。これらのゲッターは定数値を返すかもしれません。 public int getMaxConnections() {return 10;}、しかし定数を必要とするものはすべてゲッターを通ります。

1つの利点は、あなたのプログラムが定数を上回る場合 - それは設定可能である必要があることがわかった - あなたは単にgetterが定数を返す方法を変更できるということです。

もう1つの利点は、定数を変更するために、それを使用するすべてのものを再コンパイルする必要がないことです。静的最終フィールドを参照すると、その定数の値はそれを参照する任意のバイトコードにコンパイルされます。

5

上記のコメントに基づいて、私はこれが(公共の静的な最終変数を持つ)旧式のグローバル定数クラスをこのようなenumのような等価物に変更するための良い方法だと思います。

public class Constants {

    private Constants() {
        throw new AssertionError();
    }

    public interface ConstantType {}

    public enum StringConstant implements ConstantType {
        DB_Host("localhost");
        // other String constants come here

        private String value;
        private StringConstant(String value) {
            this.value = value;
        }
        public String value() {
            return value;
        }
    }

    public enum IntConstant implements ConstantType {
        DB_PORT(3128), 
        MAX_PAGE_SIZE(100);
        // other int constants come here

        private int value;
        private IntConstant(int value) {
            this.value = value;
        }
        public int value() {
            return value;
        }
    }

    public enum SimpleConstant implements ConstantType {
        STATE_INIT,
        STATE_START,
        STATE_END;
    }

}

それで、私はそれらを好きに呼ぶことができます:

Constants.StringConstant.DB_Host
4
Lorand Bendig

良いオブジェクト指向設計は、公に利用可能な多くの定数を必要とすべきではありません。ほとんどの定数は、その役割を果たすためにそれらを必要とするクラスにカプセル化されるべきです。

3
Bradley Harris

これに答えるためにある程度の意見があります。まず第一に、Javaの定数は一般にpublic、staticそしてfinalであると宣言されています。以下がその理由です。

public, so that they are accessible from everywhere
static, so that they can be accessed without any instance. Since they are constants it
  makes little sense to duplicate them for every object.
final, since they should not be allowed to change

単にインターフェースが実装されることが一般的に想定されているからといって、私は決してCONSTANTSアクセサ/オブジェクトのためにインターフェースを使用することはないだろう。これはおかしくないでしょう。

String myConstant = IMyInterface.CONSTANTX;

代わりに、いくつかの小さなトレードオフに基づいて、いくつかの方法から選択します。したがって、それは必要なものによって異なります。

1.  Use a regular enum with a default/private constructor. Most people would define 
     constants this way, IMHO.
  - drawback: cannot effectively Javadoc each constant member
  - advantage: var members are implicitly public, static, and final
  - advantage: type-safe
  - provides "a limited constructor" in a special way that only takes args which match
     predefined 'public static final' keys, thus limiting what you can pass to the
     constructor

2.  Use a altered enum WITHOUT a constructor, having all variables defined with 
     prefixed 'public static final' .
  - looks funny just having a floating semi-colon in the code
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you still have to put explicit 'public static final' before each variable
  - drawback: not type-safe
  - no 'limited constructor'

3.  Use a Class with a private constructor:
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you have to put explicit 'public static final' before each variable
  - you have the option of having a constructor to create an instance
     of the class if you want to provide additional functions related
     to your constants 
     (or just keep the constructor private)
  - drawback: not type-safe

4. Using interface:
  - advantage: you can JavaDoc each variable with an explanation
  - advantage: var members are implicitly 'public static final'
  - you are able to define default interface methods if you want to provide additional
     functions related to your constants (only if you implement the interface)
  - drawback: not type-safe
2
djangofan

Javaで定数を実装するための最良の方法は何ですか?

我々が本当に避けるべき一つのアプローチ:定数を定義するためにインターフェースを使う。

特に定数を宣言するためのインターフェースを作成することは、本当に最悪のことです。それは、インターフェースが設計された理由、すなわちメソッドコントラクトの定義を打ち破ることを打ち負かします。

特定のニーズに対処するためのインタフェースがすでに存在していても、定数をAPIの一部にしてはならず、クライアントクラスに提供される規約を使用してはならないので、定数を宣言することは実際には意味がありません。


簡単にするために、4つの有効なアプローチがあります

static final String/Integerフィールドの場合:

  • 1)内部で定数を宣言するクラスを使用します。
  • 1つの変形)定数を宣言することだけに専用のクラスを作成すること。

Java 5 enumの場合:

  • 2)列挙型を関連する目的のクラス(ネストしたクラスなど)で宣言する。
  • 2つの方法は、enumをスタンドアロンクラスとして作成することです(独自のクラスファイルで定義されています)。

TLDR:どちらが最良の方法で、どこに定数がありますか?

ほとんどの場合、enumのほうがおそらくstatic final String/Integerの方法よりも細かいです _そして個人的にはstatic final String/Integerの方法は、enumを使用しない正当な理由がある場合にのみ使用すべきだと思います。
そして、定数値をどこで宣言すべきかについて、アイデアは、定数値を持つ特定の強力な関数結合を所有する単一の既存のクラスが存在するかどうかを検索することです。定数ホルダーとして使用する必要があります。それ以外の場合、定数は特定のクラスに関連付けないでください。


static final String/static final Integerenum

列挙型の使用法は、実際に強く考慮する方法です。
列挙型はStringまたはInteger定数フィールドよりも大きな利点があります。
彼らはより強い編集制約を設定しました。 enumをパラメータとするメソッドを定義した場合は、enumクラスで定義されたenum値のみを渡すことができます(またはnull)。
StringとIntegerを使えば、互換性のある型の値に置き換えることができ、値がstatic final String/static final Integerフィールドで定義された定数でなくてもコンパイルは問題ありません。

たとえば、クラス内でstatic final Stringフィールドとして定義されている2つの定数は、以下のとおりです。

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

ここで、パラメータとしてこれらの定数の1つを持つことを期待しているメソッド:

public void process(String constantExpected){
    ...    
}

このようにして呼び出すことができます。

process(MyClass.ONE_CONSTANT);

または

process(MyClass.ANOTHER_CONSTANT);

しかし、コンパイル制約がないため、このようにして呼び出すことができません。

process("a not defined constant value");

あなたは実行時にだけ、そしてあなたが一度に送信された値のチェックをした場合にのみエラーがあるでしょう。

Enumでは、クライアントはenumパラメータにenum値を渡すことしかできないため、チェックは不要です。

たとえば、ここでは2つの値がenumクラスで定義されています(そのまま箱から出して定数):

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

ここで、これらの列挙値の1つをパラメータとして持つことを期待しているメソッド:

public void process(MyEnum myEnum){
    ...    
}

このようにして呼び出すことができます。

process(MyEnum.ONE_CONSTANT);

または

process(MyEnum.ANOTHER_CONSTANT);

しかし、コンパイルでは、このようにして呼び出すことはできません。

process("a not defined constant value");

どこで定数を宣言すべきですか?

アプリケーションに、定数値を使用した特定の強力な機能的結合を所有する単一の既存クラスが含まれている場合は、1)と2)がより直感的に見えます。
一般に、定数がそれらを操作するメインクラスで宣言されているか、内部で見つかると推測するのに非常に自然な名前が付けられている場合、定数の使用は容易になります。

たとえばJDKライブラリでは、指数およびπの定数値は、定数宣言だけではなく宣言するクラス(Java.lang.Math)で宣言されています。

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

数学関数を使用しているクライアントはしばしばMathクラスに頼ります。そのため、彼らは十分に簡単に定数を見つけることができ、EPIが非常に自然な方法で定義されている場所を思い出すこともできます。

あなたのアプリケーションが、定数値を持つ非常に具体的で強力な機能的結合を持つ既存のクラスを含んでいない場合は、1)と2)の方法がより直感的に見えます。
一般的に、定数をそれらを操作する1つのクラスで宣言しても、定数を使用するのは簡単ではありません。ホスト定数値に対して他のものよりも自然です。
ここでは、定数値のみを保持するようにカスタムクラスを定義するのが合理的です。
例えば、JDKライブラリでは、Java.util.concurrent.TimeUnit列挙型は特定のクラスで宣言されていません。それを保持するのが最も直感的にわかるようなJDK固有のクラスが実際には1つしかないからです。

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

Java.util.concurrentで宣言されている多くのクラスはそれらを使用します:BlockingQueueArrayBlockingQueue<E>CompletableFutureExecutorService、...そしてそれらのどれもenumを保持するのにより適切ではないようです。

2
davidxxx

ちなみに、秒単位のタイムアウト値はおそらく構成設定(プロパティー・ファイルから読み込まれるか、Springのようにインジェクションを通じて)であり、定数ではありません。

1
Tim Howland

違いはなんですか

1。

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2。

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

そして、この定数が必要なところではどこでもMyGlobalConstants.TIMEOUT_IN_SECSを使います。どちらも同じだと思います。

1
chandrayya

単一の総称定数クラスは悪い考えです。定数は、それらが最も論理的に関連しているクラスと一緒にグループ化されるべきです。

あらゆる種類の変数(特に列挙型)を使用するのではなく、メソッドを使用することをお勧めします。変数と同じ名前のメソッドを作成し、変数に割り当てた値を返すようにします。今すぐ変数を削除し、作成したメソッドへの呼び出しで変数へのすべての参照を置き換えます。定数が一般的なもので、使用するだけでクラスのインスタンスを作成する必要がないと思われる場合は、定数メソッドをクラスメソッドにします。

1
ab

任意の型の定数は、クラス内の不変プロパティ(つまり、final修飾子を持つメンバ変数)を作成することによって宣言できます。通常staticおよびpublic修飾子も提供されています。

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

定数の値が選択のnタプル(例えば、enumeration)からの選択を示す多くの用途がある。この例では、可能な割り当て値を制限する列挙型を定義することを選択できます(つまり、type-safetyの向上)。

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}
1
Ryan Delucchi

このクラスを定数と同じ(大文字と小文字の区別を除く)とは呼ばないでしょう...少なくともすべての定数が存在する、 "Settings"、 "Values"、または "Constants"の少なくとも1つのクラスがあります。それらが多数ある場合は、それらを論理定数クラス(UserSettings、AppSettingsなど)にグループ化します。

0
Joel Martinez

static finalが私の好みです。アイテムが本当に列挙可能であれば、enumを使うだけです。

0
wulfgarpro

基本的なゼロからゼロの原理主義を理解せずにJoshua Blochを引用するのは悪い習慣でひどくANNOYINGの練習です。

Joshua Blochは何も読んでいないので、

  • 彼はひどいプログラマーです
  • あるいは、これまで私が彼を引用していると思う人々(Joshuaは私が推測している男の子の名前です)は、単に彼らのソフトウェアの宗教的な耽溺を正当化するための宗教的な脚本として彼の資料を使っています。

聖書原理主義と同様に、すべての聖書の法則は以下のようにまとめることができます。

  • すべてのあなたの心とすべてのあなたの心との基本的なアイデンティティを愛しなさい
  • あなた自身のようにあなたの隣人を愛しなさい

そして同様にソフトウェア工学の原理主義は次のようにまとめることができます。

  • あなたのプログラミングのすべての力と心で、ゼロを基本とする基礎に専念しましょう。
  • そしてあなたがあなた自身のためにするようにあなたの仲間のプログラマーの卓越性に向けて捧げなさい。

また、聖書原理主義者サークルの中には、強く合理的な推論が描かれています。

  • まず自分を愛しなさい。なぜなら、あなたが自分自身をあまり愛していないのであれば、「自分をどれだけ自分自身を愛しているか」という概念は、それを超えると他の人を愛する基準線となるからです。

同様に、あなたがプログラマーであることを尊重しないで、基礎を疑問に思うことなくプログラミングの専門家達の発言や予言を受け入れるだけなら、あなたの引用やJoshua Bloch(など)への信頼は無意味です。それゆえ、あなたは実際にはあなたの仲間のプログラマーを尊敬しないでしょう。

ソフトウェアプログラミングの基本法則

  • 怠惰は良いプログラマーの美徳です
  • あなたはあなたのプログラミングの生活をできるだけ怠惰にして、そしてそれ故にできるだけ効果的にすることを容易にする
  • あなたはあなたのプログラミングの結果と内臓をあなたと一緒に働きそしてあなたのプログラミング内臓を拾うあなたの隣人プログラマーにとってできるだけ怠惰で、そしてそれ故にできるだけ効果的にすることです。

インターフェイスパターン定数は悪い習慣です???

根本的に効果的で責任あるプログラミングのどの法律の下でこの宗教的な叙述は陥りますか?

インターフェースパターン定数に関するウィキペディアの記事( https://en.wikipedia.org/wiki/Constant_interface )を読むだけで、インターフェースパターン定数に対して愚かな言い訳がされています。

  • Whatif - いいえIDE?ソフトウェアプログラマーとして誰がIDEを使わないのでしょうか。私たちのほとんどは、IDEの使用を回避することによってマッチョな無神論的生存主義を持つことを証明する必要がないことを好むプログラマです。

    • また、IDEを必要としない手段として、マイクロファンクションプログラミングの第2の支持者を待ってください。データモデルの正規化に関する私の説明を読むまで待ってください。
  • 現在のスコープ内で使用されていない変数で名前空間を汚染しますか?それはこの意見の支持者かもしれません

    • データモデルの正規化を認識しておらず、その必要性も
  • 定数を強制するためにインターフェースを使用することは、インターフェースの悪用です。そのような支持者はの悪い習慣を持っています

    • 「定数」が契約として扱われなければならないとは思わない。そしてインターフェースは、契約の遵守を強化または予測するために使用されます。
  • 将来、インタフェースを実装クラスに変換することは不可能ではないにしても困難です。うーん……うーん……?

    • なぜあなたはあなたの持続的な生活のようなプログラミングのそのようなパターンに従事したいと思いますか?さて、どうしてそんなAMBIVALENTと悪いプログラミング習慣に没頭するのでしょうか?

たとえどんな言い訳でも、それが基本的に効果的なソフトウェアエンジニアリングに関しては、インターフェース定数の使用を非公式にするか、一般的に推奨しないことには正当な言い訳はありません。

それは、合衆国憲法を作り上げた創設者の父親の当初の意図と精神状態が何であったかは関係ありません。私たちは創設した父親の当初の意図について議論することができましたが、私が気にしているのは米国憲法の書面による声明だけです。そしてそれは、米国憲法の文書化されていない創設意図ではなく、文書化された文学原理主義を利用することがすべての米国市民の責任です。

同様に、私は、Javaプラットフォームとプログラミング言語の創設者の「元々の」意図がインターフェースに対して持っていたことを気にしません。私が気にしているのは、Java仕様が提供する効果的な機能です。これらの機能を最大限に活用して、責任あるソフトウェアプログラミングの基本的な法則を満たすのに役立ちます。 「インターフェースの意図に違反する」と感じても構わない。 Goslingや他の誰かが "Javaを使うための適切な方法"について何を言っていても、私がEFFECTIVEを満たすための基本を満たすための必要性を侵害していないのであれば、構いません。

基本はデータモデルの正規化です。

データモデルがどのようにホストまたは送信されているかは関係ありません。データモデルの正規化の必要性とプロセスを理解していない場合は、インターフェースまたは列挙型を使用しているかどうかにかかわらず、リレーショナルかSQLなしかを問わず使用できます。

最初に、一連のプロセスのデータモデルを定義して正規化する必要があります。コヒーレントなデータモデルがあるときには、そのコンポーネントのプロセスフローを使用して機能的な振る舞いを定義し、プロセスがアプリケーションの分野や分野をブロックすることしかできません。そしてそのとき初めて、各機能プロセスのAPIを定義することができます。

EF Coddによって提案されたようなデータ正規化の面でさえ、今や厳しく挑戦され、そして厳しく挑戦されています。例えば彼の1NFに関する声明は、特に現代のデータサービス、レポテクノロジーおよび伝送の出現における残りの声明と同様に、あいまいで、位置ずれがあり、単純化されすぎていると批判されてきた。 IMO、EF Coddステートメントは完全に廃止され、より数学的にもっともらしいステートメントの新しいセットが設計されるべきです。

EF Coddの明白な欠陥と人間の効果的な理解に対するそのずれの原因は、人間が知覚できる多次元の可変次元データが、断片的な2次元マッピングのセットを通して効率的に知覚されるという彼の信念です。

データ正規化の基礎

EF Coddが表現できなかったこと.

各コヒーレントデータモデル内で、これらは達成すべきデータモデルコヒーレンスの逐次段階的順序である。

  1. データインスタンスの統一性とアイデンティティ。
    • 各データコンポーネントの粒度を設計します。それによって、それらの粒度は、コンポーネントの各インスタンスを一意に識別して取得できるレベルになります。
    • インスタンスのエイリアシングがない。つまり、識別によってコンポーネントのインスタンスが複数生成されることはありません。
  2. インスタンスクロストークがない。コンポーネントのインスタンスの識別に貢献するために、コンポーネントの1つ以上の他のインスタンスを使用する必要性はありません。
  3. データコンポーネント/ディメンションの統一性と同一性。
    • コンポーネントのエリアシング除去の存在コンポーネント/ディメンションを一意に識別できる定義が1つ存在する必要があります。これはコンポーネントの主な定義です。
    • 主な定義によって、意図したコンポーネントの一部ではないサブディメンションまたはメンバーコンポーネントが公開されない場合。
  4. コンポーネントのエイリアシング除去のユニークな方法。コンポーネントには、そのようなコンポーネントの別名除去定義が1つだけ存在する必要があります。
  5. 構成要素の階層関係において親構成要素を識別するための定義インターフェースまたは契約はただ1つだけ存在する。
  6. コンポーネントクロストークがありません。構成要素の明確な識別に貢献するために他の構成要素の構成員を使用する必要性は存在しない。
    • そのような親子関係では、親の識別定義は、子の一連のメンバーコンポーネントの一部に依存してはなりません。親のアイデンティティのメンバー構成要素は、子供の子供の一部または全部を参照することに頼らずに、完全な子供のアイデンティティでなければなりません。
  7. データモデルの先制バイモーダルまたはマルチモーダル外観
    • コンポーネントの定義が2つ存在する場合は、2つの異なるデータモデルが混在していることは明らかです。つまり、データモデルレベルまたはフィールドレベルで矛盾があります。
    • 応用分野は、首尾一貫して、唯一無二のデータモデルを使用しなければならない。
  8. 構成要素の変異を検出して特定します。巨大なデータの統計的成分分析を行ったのでなければ、おそらく成分の変異を見たことがないか、または治療の必要性を見たことがないでしょう。
    • データモデルは、その構成要素のいくつかが周期的または徐々に変化することがあります。
    • モードは、部材回転または転置回転であり得る。
    • メンバーローテーションの突然変異は、コンポーネント間の子コンポーネントの明確な入れ替えである可能性があります。あるいは、まったく新しいコンポーネントを定義する必要がある場所です。
    • 転置変異は、次元メンバーが属性に変異することとして現れ、逆もまた同様です。
    • 各突然変異サイクルは、異なるデータ様相として識別されなければなりません。
  9. 各変異をバージョン管理します。おそらく、データモデルの8歳の変異を治療する必要が生じたときに、以前のバージョンのデータモデルを引き出すことができるように。

サービス間のコンポーネントアプリケーションの分野またはグリッドでは、唯一のコヒーレントデータモデルがなければならないか、またはデータモデル/バージョンがそれ自体を識別するための手段が存在する。

インタフェース定数を使用できるかどうか、まだ質問していますか?本当に ?

この平凡な質問よりも結果的に危険にさらされているデータ正規化問題があります。あなたがそれらの問題を解決しないならば、あなたがインターフェース定数が引き起こすと思う混乱は比較的なにもありません。 Zilch.

データモデルの正規化から、コンポーネントを変数、プロパティ、コントラクトインターフェイス定数として決定します。

次に、どちらが値の注入、プロパティ設定のプレースホルダ、インターフェイス、最終文字列などに入るかを決定します。

インターフェース定数に対して指示しやすいコンポーネントを探す必要があるという言い訳をしなければならない場合は、データモデルの正規化を行わないという悪い習慣があります。

おそらくあなたはデータモデルをvcsリリースにコンパイルしたいと思うでしょう。データモデルの明確に識別可能なバージョンを引き出すことができます。

インターフェースで定義された値は、変更不可能であることが完全に保証されています。そして共有可能です。あなたが必要としているのが定数のそのセットだけなのに、なぜ別のクラスからあなたのクラスに一連の最終文字列をロードするのでしょうか。

それでは、これでデータモデル契約を公開しないのはなぜでしょうか。私はあなたがそれを首尾一貫して管理し正規化することができれば、なぜですか? ...

public interface CustomerService {
  public interface Label{
    char AssignmentCharacter = ':';
    public interface Address{
      String Street = "Street";
      String Unit= "Unit/Suite";
      String Municipal = "City";
      String County = "County";
      String Provincial = "State";
      String PostalCode = "Zip"
    }

    public interface Person {
      public interface NameParts{
        String Given = "First/Given name"
        String Auxiliary = "Middle initial"
        String Family = "Last name"
      }
    }
  }
}

これで、アプリの契約ラベルを次のような方法で参照できます。

CustomerService.Label.Address.Street
CustomerService.Label.Person.NameParts.Family

これはjarファイルの内容を混乱させるのですか? Javaプログラマーとして、私はjarファイルの構造を気にしません。

これはosgiに動機付けられたランタイムスワッピングの複雑さを表していますか? Osgiは、プログラマーが悪い習慣を続けられるようにするための非常に効率的な手段です。 osgiよりも優れた選択肢があります。

それともどうしてですか?公開された契約への私的定数の漏洩はありません。私は定数を検索する必要はありませんし、「private final String」を繰り返し入力するのは面倒なので、すべてのプライベート定数は「Constants」という名前のプライベートインターフェイスにグループ化する必要があります。

public class PurchaseRequest {
  private interface Constants{
    String INTERESTINGName = "Interesting Name";
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

おそらくこれさえ:

public interface PurchaseOrderConstants {
  public interface Properties{
    default String InterestingName(){
       return something();
    }
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

考慮に値するインタフェース定数に関する唯一の問題は、インタフェースが実装されている場合です。

これはインターフェースの「本来の意図」ではありませんか。私が最高裁判所が米国憲法の書面による手紙を解釈する方法よりもむしろ、米国憲法を作成する際の創設者の父親の「本来の意図」を気にするように?

結局のところ、私は勇者の自由、野生そして家の土地に住んでいます。勇敢になり、自由になり、ワイルドになりましょう - インターフェースを使ってください。私の仲間のプログラマーが効率的で怠惰なプログラミング手段の使用を拒否した場合、私は自分のプログラミング効率を低下させるという黄金律を義務付けていますか。おそらく私はすべきですが、それは理想的な状況ではありません。

0
Blessed Geek

さらに一歩進めて、グローバルに使用される定数をインターフェイスに配置して、システム全体で使用できるようにすることができます。例えば。

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

しかし、それを実装しないでください。完全修飾クラス名を介してコード内で直接参照するだけです。

0

私はstatic finalを使って定数を宣言し、ALL_CAPS命名法を使います。私は、すべての定数が1つのインターフェースにまとめられている実生活の例をかなり見ました。いくつかの投稿では、それが悪い習慣だと正しく主張しています。それは、主にそれがインターフェースの目的ではないためです。インターフェイスはコントラクトを強制するべきであり、関係のない定数を入れる場所にすべきではありません。インスタンス化できないクラスにそれをまとめる(プライベートコンストラクタを通して)こともできません。 es)私はいつもそれが最も関連しているクラスに定数を入れました。

列挙型は値の範囲を表すのに適していますが、絶対値を重視してスタンドアロンの定数を保存する場合(たとえばTIMEOUT = 100 ms)、static finalアプローチを使用することができます。

0
bincob

定数の場合、Enumはより良い選択です。これが例です

パブリッククラスmyClass {

public enum myEnum {
    Option1("String1", 2), 
    Option2("String2", 2) 
    ;
    String str;
            int i;

            myEnum(String str1, int i1) { this.str = str1 ; this.i1 = i }


}
0
mmansoor

私はほとんどの人が言っていることに同意します。定数の集まりを扱うときはenumを使うのが最善です。あなたがAndroidでプログラミングしている場合は、より良い解決策があります: IntDef Annotation

@Retention(SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST,NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();

IntDefアノテーションは、単純な点でenumよりも優れています。コンパイル時のマーカーであるためスペースが大幅に少なくなります。これはクラスではなく、自動文字列変換プロパティもありません。

0
Quinn Turner

私が行う方法の1つは、定数値を使って「Global」クラスを作成し、その定数にアクセスする必要があるクラスで静的インポートを実行することです。

0
Javamann