多くのブール型プロパティを持つ列挙型


11

現在、ユーザーに返されるページに基づいてサーバーロジックを調整する必要があることが多いwebappに取り組んでいます。

各ページには4文字のページコードが与えられ、これらのページコードは現在、静的な文字列としてクラスにリストされています。

public class PageCodes {
    public static final String FOFP = "FOFP";
    public static final String FOMS = "FOMS";
    public static final String BKGD = "BKGD";
    public static final String ITCO = "ITCO";
    public static final String PURF = "PURF";
    // etc..
}

そして、多くの場合、コードには次のようなコードが表示されます(1番目の形式):

if (PageCode.PURF.equals(destinationPageCode) || PageCodes.ITCO.equals(destinationPageCode)) {
    // some code with no obvious intent
} 
if (PageCode.FOFP.equals(destinationPageCode) || PageCodes.FOMS.equals(destinationPageCode)) {
    // some other code with no obvious intent either
} 

これらのページのどの共通プロパティがコードの作者をここにまとめたのかを示していないため、これは読みにくいです。if理解するには、ブランチのコードを読む必要があります。

現在のソリューション

これらifは、さまざまなクラスのさまざまな人々によって宣言されたページのリストを使用して部分的に簡素化されています。これにより、コードは次のようになります(2番目の形式):

private static final List<String> pagesWithShoppingCart = Collections.unmodifiableList(Arrays.asList(PageCodes.ITCO, PageCodes.PURF));
private static final List<String> flightAvailabilityPages = Collections.unmodifiableList(Arrays.asList(PageCodes.FOMS, PageCodes.FOFP));

// later in the same class
if (pagesWithShoppingCart.contains(destinationPageCode)) {
    // some code with no obvious intent
} 
if (flightAvailabilityPages.contains(destinationPageCode)) {
    // some other code with no obvious intent either
} 

...これは意図をはるかによく表します。だが...

現在の問題

ここでの問題は、ページを追加する場合、理論的にはすべてのコードベースを調べif()て、そのようなリストにページを追加する必要があるかどうかを確認する必要があることです。

これらのリストをすべてPageCodes静的定数としてクラスに移動した場合でも、新しいページがこれらのリストのいずれかに適合するかどうかを確認し、それに応じて追加するには、開発者からの規律が必要です。

新しいソリューション

私の解決策は列挙型を作成することでした(ページコードには有限の既知のリストがあるため)。各ページには設定する必要のあるプロパティが含まれています。

public enum Page {
    FOFP(true, false),
    FOMS(true, false),
    BKGD(false, false),
    PURF(false, true),
    ITCO(false, true),
    // and so on

    private final boolean isAvailabilityPage;
    private final boolean hasShoppingCart;

    PageCode(boolean isAvailabilityPage, boolean hasShoppingCart) {
        // field initialization
    }

    // getters
}

次に、条件コードは次のようになります(3番目の形式)。

if (destinationPage.hasShoppingCart()) {
    // add some shopping-cart-related data to the response
}
if (destinationPage.isAvailabilityPage()) {
    // add some info related to flight availability
}

とても読みやすいです。さらに、誰かがページを追加する必要がある場合、彼/彼女は各ブール値と、これが彼の新しいページについて真であるか偽であるかについて考えることを余儀なくされます。

新しい問題

私が見る1つの問題は、このような10個のブール値が存在する可能性があることです。これにより、コンストラクタが非常に大きくなり、ページを追加するときに宣言を取得するのが難しくなる場合があります。誰もがより良い解決策を持っていますか?

回答:


13

アイデアをさらに一歩進め、ブール値を使用する代わりにページ機能の列挙を定義できます。

これにより、ページへの機能の追加/削除が簡単になり、30〜40の潜在的な機能がある場合でも、ページ定義をすぐに読み取ることができます。

public enum PageFeature {
    AVAIL_PAGE,
    SHOPPING_CART;
}

public enum Page {
    FOFP(AVAIL_PAGE),
    FOMS(AVAIL_PAGE),
    BKGD(),
    PURF(SHOPPING_CART, AVAIL_PAGE),

    private final EnumSet<PageFeature> features;

    PageCode(PageFeature ... features) {
       this.features = EnumSet.copyOf(Arrays.asList(features));
    }

    public boolean hasFeature(PageFeature feature) {
       return features.contains(feature);
    }
 }

私はこれについて考えましたが、ここでは、開発者は「仕様書ページですか?」、「ショッピングカートはありますか?」というすべての質問に答える必要はありません。など。それらがたくさんある場合、簡単に忘れてしまいます。
ジョフリー

5
@Joffreyあなたがそれについて考えるとき、10個のブール値を持つことは、彼らが答えを与えることを強制しません。少なくとも彼らが考える答えはありません。最も可能性の高いシナリオは、別のページの定義をコピーするか、IDEにすべてのパラメーターを入力してfalse、1つまたは2つを変更することです(おそらく、追跡が難しいため間違ったパラメーターです)。バカから完全に保護されるわけではなく、開発者が正しいことをすることを信頼しなければならない点があります。
biziclop

そうです、私はそれについてこのように考えませんでした:)そして、ブール値によって与えられる小さな余分な「フールプルーフ」は、可読性の低下の価値があるとは思わないので、おそらく可変引数のソリューションを使用します。洞察力をありがとう!
ジョフリー

1
良い解決策、賛成です。6502sでコーディングした私の一部は、すべてをビットに詰め込みたいと思っていますが。:-)
user949300

@ user949300私が考えた最初の可変引数のような解決策は実際にはビットマスクでした:)が、列挙型の真の可変引数はよりクリーンです
ジョフリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.