Actualmente estoy trabajando en una aplicación web en la que a menudo necesitamos condicionar cierta lógica del servidor en función de la página que se devolverá al usuario.
Cada página recibe un código de página de 4 letras, y estos códigos de página se enumeran actualmente en una clase como cadenas estáticas:
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..
}
Y a menudo en el código vemos código como este ( 1er formulario ):
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
}
Lo cual es horrible de leer porque no muestra qué propiedad común de estas páginas llevó al autor del código a reunirlas aquí. Tenemos que leer el código en la if
rama para entender.
Solución actual
Estos if
mensajes se han simplificado en parte mediante listas de páginas declaradas por diferentes personas en diferentes clases. Esto hace que el código se vea como ( 2da forma ):
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
}
... que expresa la intención mucho mejor. Pero...
Problema actual
El problema aquí es que si agregamos una página, en teoría tendríamos que revisar toda la base de código para encontrar si necesitamos agregar nuestra página if()
a una lista como esa.
Incluso si movimos todas esas listas a la PageCodes
clase como constantes estáticas, aún necesita disciplina de los desarrolladores para verificar si su nueva página encaja en alguna de esas listas y agregarla en consecuencia.
Nueva solución
Mi solución fue crear una enumeración (porque hay una lista finita bien conocida de códigos de página) donde cada página contiene algunas propiedades que necesitamos establecer:
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
}
Entonces el código condicional ahora se ve así ( tercera forma ):
if (destinationPage.hasShoppingCart()) {
// add some shopping-cart-related data to the response
}
if (destinationPage.isAvailabilityPage()) {
// add some info related to flight availability
}
Lo cual es muy legible. Además, si alguien necesita agregar una página, se ve obligado a pensar en cada booleano y si esto es verdadero o falso para su nueva página.
Nuevo problema
Un problema que veo es que tal vez habrá 10 booleanos como este, lo que hace que el constructor sea realmente grande y puede ser difícil obtener la declaración correcta cuando agrega una página. ¿Alguien tiene una solución mejor?
false
y luego modifiquen uno o dos (probablemente el incorrecto, ya que es muy difícil hacer un seguimiento). No hay una protección perfecta contra los estúpidos, y llega un punto en el que debes confiar en tus desarrolladores para hacer lo correcto.