Si, soy haragán.

Monday January 01st 2007, 11:19 pm
Filed under: Java, Spring, Stripes

A consecuencia de haber leido este post, me puse a pensar que fue lo último que hice tratando de buscar la mejor solución, y no la que hubiera usado sino me ponía a investigar 5 minutos.

Y encontré este simple caso:

Como decía en un post anterior, estuve haciendo un programador (scheduler) de reportes. El requerimiento era que fuera flexible y fácil de usar, ya que los mismos usuarios finales lo van a utilizar para programar los reportes. Para el caso de la periodicidad, obviamente no podia simplemente poner un campo donde ingresar una expresión Cron, porque entonces nadia iba a ser capáz de usarlo. Se me ocurrió entonces poner una serie de opciones, que el usuario podía elegir: Una vez, Diario, Semanal, Quincenal, Mensual, etc.  

Para la parte de interface del usuario, ya habia decidido usar Stripes para todo lo nuevo (e ir lentamente migrando lo antiguo de Struts). Stripes se basa fuertemente en Java 5, y por lo tanto trae algo muy interesante que es un tag de JSP stripes:enumName() , que sirve para mostrar los valores de una enumeración. Esto está buenísimo, porque me hago un loop y muestro todos los valores de un Enum como radio buttons: 

<c:forEach var=”freq” items=”<%= ReportFrequency.values() %>”>
    <s:radio value=”${s:enumName(freq)}” name=”definition.frequency” id=”definition.frequency.${s:enumName(freq)}”     class=”radio”/>
    <s:label for=”definition.frequency.${s:enumName(freq)}”>${s:enumName(freq)}</s:label>
</c:forEach> 

Lo mejor de todo esto, es que cuano el valor llega a mi Action de Stripes, me llega como un Enum del tipo ReportFrecuency (gracias al maravilloso binding de Stripes). El detalle acá, es que los Enum de Java 5 no son simples constantes, sino que también pueden tener comportamiento.
Mi Enum ReportFrecuency esta definido asi:
 

public enum ReportFrequency {
    Once(TriggerUtils.makeImmediateTrigger(0, 0)),
    Hourly(TriggerUtils.makeHourlyTrigger()),
    Daily(TriggerUtils.makeHourlyTrigger(24)),
    //etc

    private Trigger trigger;

    ReportFrequency(Trigger trigger) {
        this.trigger = trigger;
    }

    public Trigger getTrigger() {
        return trigger;
    }
}

O sea que luego, lo único que tengo que hacer cuando creo el Trigger para el Scheduler, es: 

Trigger trigger = definition.getFrequency().getTrigger();

Facilícimo. Y agregar una nueva frecuencia solo implica agregar un nuevo valor al Enum, no hay que tocar absolutamente nada más!.

Ahora, cómo hubiera hecho sino hubiera usado Enums y Stripes? Lo mas asqueroso que se me ocurre es todo hardcodeado, con los valores en strings repetidos en la vista y en el action, y una serie de ifs para elegi el Trigger. Algo un poco mejor podría haber sido usar constantes  static final String (pero igualmente hubiera tenido que escribir cada radiobutton individualmente), y después haber usado algún factory para obtener el Trigger correspondiente.

Creo yo que esta es la mejor solución posible (por lo menos a mi no se me ocurrió nada mejor), y además es extremádamente fácil de mantener. Las otras soluciones implican escribir mas, y son difíciles de mantener, porque hay que cambiar varias cosas en varios lados, y mantener esos cambios sincronizados. Es cierto, quizá haya tardado un poco más en implementar esta solución porque tuve que investigar un poco sobre Enums y Stripes, pero el resultado es mucho mas robusto, agregar alguna frecuencia en el futuro es una pavada, y además aprendí algo nuevo.

Y la satisfacción de haber hecho las cosas bien, es impagable.


| show comment »