Enum con molte proprietà booleane

11

Attualmente sto lavorando a una webapp in cui spesso è necessario condizionare alcune logiche del server in base alla pagina che verrà restituita all'utente.

A ogni pagina viene assegnato un codice di pagina di 4 lettere e questi codici di pagina sono attualmente elencati in una classe come stringhe statiche:

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

E spesso nel codice vediamo un codice come questo ( 1 ° modulo ):

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
} 

Che è orribile da leggere perché non mostra quale proprietà comune di queste pagine abbia portato l'autore del codice a metterle insieme qui. Dobbiamo leggere il codice nel ramo if per capire.

Soluzione corrente

Questi if s sono stati parzialmente semplificati utilizzando elenchi di pagine dichiarate da persone diverse in classi diverse. Questo rende il codice simile ( 2 ° modulo ):

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
} 

... che esprime molto meglio l'intento. Ma ...

Problema corrente

Il problema qui è che se aggiungessimo una pagina, avremmo in teoria bisogno di esaminare tutti i codici base per scoprire se abbiamo bisogno di aggiungere la nostra pagina a if() o ad una lista come quella.

Anche se spostassimo tutti questi elenchi nella classe PageCodes come costanti statiche, è necessario disciplinare gli sviluppatori per verificare se la loro nuova pagina si adatta a uno di questi elenchi e aggiungerla di conseguenza.

Nuova soluzione

La mia soluzione era creare un enum (perché esiste un elenco ben noto di codici di pagina) in cui ogni pagina contiene alcune proprietà che è necessario impostare:

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
}

Quindi il codice condizionale ora appare come questo ( 3 ° modulo ):

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

Che è molto leggibile. Inoltre, se qualcuno ha bisogno di aggiungere una pagina, lui / lei è forzato a pensare a ogni booleano e se è vero o falso per la sua nuova pagina.

Nuovo problema

Un problema che vedo è che ci saranno forse 10 booleani come questo, il che rende il costruttore veramente grande e potrebbe essere difficile ottenere la dichiarazione giusta quando si aggiunge una pagina. Qualcuno ha una soluzione migliore?

    
posta Joffrey 15.01.2016 - 17:38
fonte

1 risposta

13

Puoi portare l'idea un passo avanti e definire un enum per le tue funzioni di pagina invece di usare i booleani.

Ciò semplifica l'aggiunta / rimozione di una funzionalità a una pagina e rende le definizioni di pagina immediatamente leggibili anche quando vi sono 30-40 potenziali funzionalità.

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);
    }
 }
    
risposta data 15.01.2016 - 17:54
fonte

Leggi altre domande sui tag