Enum dengan banyak properti boolean

11

Saat ini saya sedang mengerjakan webapp di mana kita sering perlu mengkondisikan beberapa logika server berdasarkan halaman yang akan dikembalikan kepada pengguna.

Setiap halaman diberi kode halaman 4 huruf, dan kode halaman ini saat ini terdaftar dalam kelas sebagai String statis:

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..
}

Dan seringkali dalam kode kita melihat kode seperti ini ( formulir 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
} 

Yang agak mengerikan untuk dibaca karena tidak menunjukkan apa yang menjadi milik umum dari halaman-halaman ini yang menyebabkan penulis kode menyatukannya di sini. Kita harus membaca kode di ifcabang untuk mengerti.

Solusi saat ini

Ini ifsebagian disederhanakan menggunakan daftar halaman yang dideklarasikan oleh orang yang berbeda di kelas yang berbeda. Ini membuat kode terlihat seperti ( formulir ke-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
} 

... yang menyatakan niatnya jauh lebih baik. Tapi...

Masalah saat ini

Masalahnya di sini adalah bahwa jika kita menambahkan halaman, secara teori kita harus melalui semua basis kode untuk menemukan apakah kita perlu menambahkan halaman kita ke if()atau ke daftar seperti itu.

Bahkan jika kita memindahkan semua daftar itu ke PageCodeskelas sebagai konstanta statis, masih perlu disiplin dari pengembang untuk memeriksa apakah halaman baru mereka cocok dengan salah satu daftar itu dan menambahkannya sesuai.

Solusi baru

Solusi saya adalah membuat enum (karena ada daftar kode halaman terkenal yang terbatas) di mana setiap halaman berisi beberapa properti yang perlu kita atur:

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
}

Maka kode kondisional sekarang terlihat seperti ini ( formulir ke-3 ):

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

Itu sangat mudah dibaca. Selain itu, jika seseorang perlu menambahkan halaman, dia dipaksa untuk memikirkan setiap boolean dan apakah ini benar atau salah untuk halaman barunya.

Masalah Baru

Satu masalah yang saya lihat adalah mungkin akan ada 10 boolean seperti ini, yang membuat konstruktornya sangat besar dan mungkin sulit untuk mendapatkan deklarasi dengan benar ketika Anda menambahkan halaman. Adakah yang punya solusi yang lebih baik?

Joffrey
sumber

Jawaban:

13

Anda dapat mengambil ide satu langkah lebih jauh dan menentukan enum untuk fitur halaman Anda daripada menggunakan boolean.

Ini membuatnya mudah untuk menambah / menghapus fitur ke halaman dan membuat definisi halaman langsung dapat dibaca bahkan ketika ada 30-40 fitur potensial.

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);
    }
 }
biziclop
sumber
Saya memikirkan hal ini, tetapi di sini, pengembang tidak dipaksa untuk memberikan jawaban untuk semua pertanyaan "apakah ini halaman faedah?", "Apakah ia memiliki keranjang belanja?" dll. Ketika ada banyak dari mereka, Anda dengan mudah melupakannya.
Joffrey
5
@Offrey Ketika Anda memikirkannya, memiliki sepuluh boolean tidak memaksa mereka untuk memberikan jawaban juga, setidaknya bukan jawaban yang mereka pikirkan. Skenario yang paling mungkin adalah mereka hanya akan menyalin definisi halaman lain atau membiarkan IDE mengisi semua parameter false, kemudian memodifikasi satu atau dua (mungkin yang salah, karena sangat sulit untuk melacak). Tidak ada perlindungan sempurna dari bodoh, dan ada titik di mana Anda harus memercayai pengembang Anda untuk melakukan hal yang benar.
biziclop
Benar, saya tidak berpikir seperti ini :) Dan saya tidak berpikir "bukti bodoh" ekstra kecil yang diberikan oleh boolean sebanding dengan degradasi dalam kelonggaran, jadi saya mungkin akan pergi dengan solusi vararg. Terima kasih atas wawasan Anda!
Joffrey
1
Solusi bagus, terunggah. Meskipun bagian dari diriku yang berkode 6502 ingin menjejalkan semuanya menjadi bit. :-)
user949300
@ user949300 solusi seperti-vararg pertama yang saya pikirkan sebenarnya adalah topeng bit :) tetapi vararg sejati dengan tipe enum lebih bersih
Joffrey