Funny coding (II)

Como desarrollador, eres creativo. El Ferran Adriá del Java. Por eso, comparar fechas debe ser algo especial, mágico, una explosión de sensaciones. Como esta obra maestra:

void validateDate(Date date) {
  Date now = new Date();
  SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
  String date1 = sdf.format(date);
  String date2 = sdf.format(now);
  try {
    Date r1 = sdf.parse(date1);
    Date r2 = sdf.parse(date2);
    if (r1.compareTo(r2) < 0) {
      addError("Invalid date");
    }
  } catch (ParseException e) {}
}

El tiempo, causa y a la vez solución de todos los problemas de la vida

Dejemos de lado el hecho de que el tiempo, como tal, no existe; que lo que percibimos como tiempo es relativo; y que el calendario es una invención humana por pura conveniencia.

¿Cómo medimos el tiempo, entonces? Usando propiedades físicas que generan eventos regulares, los metrónomos de la naturaleza. Cuántos y cómo los llamemos ya es pura nomenclatura.

En informática, se utiliza habitualmente un reloj electrónico—más o menos preciso—y una fecha desde la que empezar a contar. Quizás, la medida más conocida pueda ser el "número de milisegundos desde el 1 de enero de 1970."

Know your APIs, bro

Java, concretamente, usa justo esa medida de tiempo. Las clases Date y Calendar son utilidades para manejar los datos de una forma más humanamente entendible, pero en el fondo se implementan en base a un número de milisegundos. Cierto es que ese detalle no es trivial. Todos estamos acostumbrados a usar new Date() sin pensar en lo que realmente ocurre entre bambalinas.

Por eso, me imagino a este buen cocinero mirando su pantalla y pensando: ¿cómo hago yo para quitar las horas, minutos y segundos y comparar estas dos fechas en igualdad de condiciones? Lo que no me puedo imaginar es por qué su primer paso no fue abrir la documentación de la clase para enterarse de lo que tenía entre manos. Joder, que lo pone en la puta segunda línea:

As of JDK 1.1, the Calendar class should be used to convert between dates and time fields

Reuse immutable objects, bro

Con lo anterior me eché unas risas, la verdad. Me pareció tremendamente ingenioso, aparte de lo ineficiente. Sin embargo, el new SimpleDateFormat() me provocó ganas de estrangular a alguien.

A diferencia de Joda Time, las clases de formateo—pre Java 8—son bastante costosas de construir, hasta el punto de que hay quien se crea un pool de formateadores para reutilizarlos—no son objetos concurrentes y no se pueden compartir entre hilos. Así que crear un SimpleDateFormat cada vez que quieres validar un dato es rizar el rizo de la mala praxis. ¡Y mucho más si tenemos en cuenta que el patrón de formato no cambia nunca!

Cada vez que reusas una instancia, sonríe un recolector de basura.

My way or the highway

Ya que me pongo quisquilloso, diré también que me gusta muy poco que la validación se encargue de añadir el mensaje de error, luego mi reinterpretación de este plato sería la siguiente:

// el miembro no puede ser estático, ni la clase un singleton
private final DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

private final Calendar startOfToday;

// en el constructor de turno
public Ctor() {
  startOfToday = Calendar.getInstance();
  startOfToday.set(Calendar.HOUR_OF_DAY, 0);
  startOfToday.set(Calendar.MINUTE, 0);
  startOfToday.set(Calendar.SECOND, 0);
  startOfToday.set(Calendar.MILLISECOND, 0);
}

private boolean isValidAndGeThanToday(Date date) {
  if (date == null) return false;
  return date.getTime() >= startOfToday.getTimeInMillis();
}

Madre, ¡y eso que ni siquiera hemos entrado en lo verdaderamente complicado de manejar fechas!

...el validate date date date date date date ha sido completamente intencionado...

Autor

Héctor

Viendo los bytes pasar desde mi ventana