Attualmente sto lavorando su una webapp in cui spesso è necessario condizionare la logica del server in base alla pagina che verrà restituita all'utente.
A ciascuna 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 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 ha portato l'autore del codice a metterle insieme qui. Dobbiamo leggere il codice nel if
ramo per capire.
Soluzione attuale
Questi messaggi if
sono stati parzialmente semplificati utilizzando elenchi di pagine dichiarate da persone diverse in classi diverse. Questo fa apparire il codice ( secondo 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 l'intento molto meglio. Ma...
Problema attuale
Il problema qui è che se aggiungiamo una pagina, in teoria avremmo bisogno di esaminare tutta la base di codice per scoprire se dobbiamo aggiungere la nostra pagina a una if()
o a una lista come quella.
Anche se abbiamo spostato tutti quegli elenchi nella PageCodes
classe come costanti statiche, è comunque necessaria la disciplina da parte degli sviluppatori per verificare se la loro nuova pagina rientra in uno di quegli elenchi e aggiungerlo di conseguenza.
Nuova soluzione
La mia soluzione era quella di creare un enum (perché esiste un elenco ben noto di codici di pagina) in cui ogni pagina contiene alcune proprietà che dobbiamo 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 così ( 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, è costretto a pensare a ogni booleano e se questo è 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 davvero grande e potrebbe essere difficile ottenere la dichiarazione giusta quando aggiungi una pagina. Qualcuno ha una soluzione migliore?