web-dev-qa-db-ja.com

ネストされたパブリッククラスを使用して定数を整理する

多くの定数を持つアプリケーションに取り組んでいます。最後のコードレビューで、定数があまりにも散在しており、すべてを単一の「マスター」定数ファイルに編成する必要があることがわかりました。意見の相違は、それらをどのように整理するかについてです。大多数は定数名を使用することで十分であると感じていますが、これは次のようなコードになります:

public static final String CREDITCARD_ACTION_SUBMITDATA = "6767";
public static final String CREDITCARD_UIFIELDID_CARDHOLDER_NAME = "3959854";
public static final String CREDITCARD_UIFIELDID_EXPIRY_MONTH = "3524";
public static final String CREDITCARD_UIFIELDID_ACCOUNT_ID = "3524";
...
public static final String BANKPAYMENT_UIFIELDID_ACCOUNT_ID = "9987";

このタイプの命名規則は扱いにくいと思います。ネストされたパブリッククラスを使用する方が簡単かもしれないと思いました。

public class IntegrationSystemConstants
{
    public class CreditCard
    {
        public static final String UI_EXPIRY_MONTH = "3524";
        public static final String UI_ACCOUNT_ID = "3524";
        ...
    }
    public class BankAccount
    {
        public static final String UI_ACCOUNT_ID = "9987";
        ...
    }
}

「あまりにも複雑」だったため、このアイデアはあまり受け入れられませんでした(なぜこれについてはあまり複雑ではありません)。これにより、関連する定数のグループ間の分割が改善され、オートコンプリートにより、これらも簡単に見つけられるようになると思います。私はこれが行われるのを見たことがないので、これが受け入れられた慣習なのか、それを行わないほうがよい理由があるのか​​疑問に思っています。

2つの提案のどちらにも同意しません。

定数は適切なクラスすべて定数クラスではないである必要があります2つの形式のいずれかが提案されます。

定数のみのクラス/インターフェイスであってはなりません。

クラスCreditCard(内部クラスではない)が存在する必要があります。このクラス/インターフェイスには、クレジットカードに関連するメソッドと、定数UI_EXPIRY_MONTHおよびUI_ACCOUNT_IDがあります。

クラス/インターフェースBankAccountが存在する必要があります(内部クラスではありません)。このクラス/インターフェースには、銀行口座に関連するメソッドと定数UI_ACCOUNT_IDがあります。

たとえば、Java APIでは、すべてのクラス/インターフェイスに定数があります。それらは、内部クラスにグループ化されているかどうかに関係なく、何百もの定数を持つ定数クラス/インターフェイスにはありません。

たとえば、結果セットに関連するこれらの定数は、インターフェイスResultSetにあります。

static int  CLOSE_CURSORS_AT_COMMIT 
static int  CONCUR_READ_ONLY 
static int  CONCUR_UPDATABLE 
static int  FETCH_FORWARD 
static int  FETCH_REVERSE 
static int  FETCH_UNKNOWN 
static int  HOLD_CURSORS_OVER_COMMIT 
static int  TYPE_FORWARD_ONLY 
static int  TYPE_SCROLL_INSENSITIVE 
static int  TYPE_SCROLL_SENSITIVE 

このインターフェイスには結果セットに関連するメソッドシグネチャがあり、実装クラスはその動作を実装します。それらは単なる定数保有者ではありません。

UIアクションに関連するこれらの定数は、インターフェースjavax.swing.Actionにあります。

static String   ACCELERATOR_KEY 
static String   ACTION_COMMAND_KEY 
static String   DEFAULT 
static String   LONG_DESCRIPTION 
static String   MNEMONIC_KEY 
static String   NAME 
static String   SHORT_DESCRIPTION 
static String   SMALL_ICON 

実装クラスには、UIアクションに関連する動作があり、単なる定数ホルダーではありません。

メソッドのない「定数」インターフェース(SwingConstants)は少なくとも1つは知っていますが、数百の定数はなく、ほんの数個しかありません。これらはすべて、UI要素の方向と位置に関連しています。

static int  BOTTOM 
static int  CENTER 
static int  EAST 
static int  HORIZONTAL 
static int  LEADING 
static int  LEFT 
static int  NEXT 
static int  NORTH 
static int  NORTH_EAST 
static int  NORTH_WEST 
static int  PREVIOUS 
static int  RIGHT 
static int  SOUTH 
static int  SOUTH_EAST 
static int  SOUTH_WEST 
static int  TOP 
static int  TRAILING 
static int  VERTICAL 
static int  WEST 

クラスのみの定数は良くないと思いますOOデザイン。

13

定数が散在しすぎて、すべてを単一の「マスター」定数ファイルに編成する必要があることがわかりました。

これは、定数が「見つけるのが難しい」という問題の100%間違った解決策です。定数、列挙型、インターフェイスなどの技術的な基準で物事をグループ化することは、基本的なエラーです(残念ながら、プログラマーが一般的に犯しすぎます)。

レイヤーアーキテクチャを除いて、物はドメインによってグループ化される必要があります、そして定数は非常に低レベルの要素であるため、さらにそうです。定数は、それらをAPIの一部として使用するクラスまたはインターフェースの一部である必要があります。彼らが住むための自然な場所が見つからない場合は、API設計をクリーンアップする必要があります。

さらに、-単一の巨大な定数ファイルはJavaの開発速度を低下させます定数はコンパイル時にそれらを使用するクラスにインライン化されるため、変更を加えると、それらすべてのファイルとそれらに依存するすべてのファイルが強制的に再コンパイルされます。どこでも使用される定数を持つ1つのファイルがある場合、インクリメンタルコンパイルのメリットはほとんど失われます。Eclipseが15分間ロックして、そのファイルに変更が加えられるたびにプロジェクト全体が再コンパイルされるのを観察してください。また、そのファイルにはどこでも使用されるすべての定数が含まれているため、頻繁に変更することになります。はい、私は個人的な経験から話しています。

10

あなたが正しいです。あなたの提案により、プログラマはimport static Constants.BankAccount.*そして、 'BANKACCOUNT_'の無数の繰り返しを排除します。連結は、実際のスコープの代替としては不十分です。とは言っても、チームカルチャーを変えてほしいという希望はあまりありません。彼らは適切な実践の概念を持っており、彼らが間違っていると言っている100人の専門家を彼らに見せても変わらないでしょう。

また、なぜ「Constants」ファイルが1つしか存在しないのかと思います。これらの定数が何らかの形で関連し、非常に安定していない限り、これは非常に悪い習慣です。より一般的には、常に変化し、すべてに依存する一種のキッチンシンククラスになります。

9
kevin cline

どちらのアプローチも機能しますが、それが結局のところ重要なことです。

とは言っても、あなたのアプローチはパターンと見なすのに十分一般的であり、より正確には 定数インターフェイス アンチパターンよりも十分に優れています。何が複雑なのかはわかりませんが、それはあなたがチームと持つべき議論です。

6
yannis

定数の長いリストでの課題の1つは、使用する「正しい」定数を見つけることです。常に、誰かが所属するグループに定数を追加するのではなく、行の最後に定数を追加します。

これは、チームと話し合う別のポイントを提示します-定数の名前による事実上の分類はすでにあります。ですから、彼らにとって、それは現在の状態からあなたが提案しているものへの大きなシフトであってはなりません。オートコンプリートを使用すると、一定のルックアップがさらに簡単になります。

どちらかと言えば、あなたの提案は、それが特定の状況に適合するかもしれないとしても、「間違った」定数の使用を思いとどまらせるのに役立ちます。定数を代表的なクラスでラップすることにより、開発者が定数を使用する必要があるかどうかを検討するよう促します。たとえば、一般的な使用法のためにCreditCard.SomeConstantをプルする場合、そのような状況のためにGeneral.SomeConstantがないのはなぜかと疑問に思うはずです。

私は定数のモンスター量でプロジェクトに取り組んできました、そしてあなたが提案している方法を持っていることを望みました。クリーンで、より直接的で、不注意な使用を避けるのに役立ちます。

1
user53019

特にC#でこれをときどき行います。特に、既知の固定されたXML構造または同様にネストされ、文字列が重いものに対してプログラム/パースする必要がある場合は、たとえばカスタム構成ブロックパーサーを使用します。

XMLの階層構造と一致するネストされたクラス構造を構築します。const文字列の「ElementName」プロパティと各属性(存在する場合)に対応する同様のプロパティを含む要素に対応するクラス名が含まれます。

対応するXmlに対して非常に簡単にプログラミングできます。

1
Ed Hastings