Date vs. Boolean

traducido por I. A.

Cuando diseñamos modelos de datos y sus correspondientes tablas a veces aparece Boolean como tipo de dato. En general estos indicadores no son realmente problemáticos. Pero tal vez podría haber una mejor solución para el diseño de datos. Permítanme darles un breve ejemplo de mi intención.

Supongamos que tenemos que diseñar un dominio simple para almacenar artículos. Como un Sistema de Blog o cualquier otro Gestor de Contenidos. Además del contenido del artículo y el nombre del autor, podríamos necesitar una bandera que indique al sistema si el artículo es visible para el público. Algo así como publicado como un booleano. Pero también hay un requisito de cuando el artículo está programado una fecha para su publicación. En la mayoría de los diseños de bases de datos observé para esas circunstancias un Booleano: published y una Fecha: publishingDate. En mi opinión este diseño es un poco redundante y también propenso a errores. Como conclusión rápida me gustaría aconsejarte que utilices desde el principio sólo Date en lugar de Boolean. El escenario que he descrito anteriormente también puede transformarse en muchas otras soluciones de dominio.

Por ahora, después de tener una idea de por qué debemos sustituir Boolean por Date datatype nos centraremos en los detalles de cómo podemos alcanzar este objetivo.

Tratar con SQL estándar sugiere que reemplazar un Sistema de Gestión de Bases de Datos (SGBD) por otro no debería ser un gran problema. Desgraciadamente, la realidad es un poco diferente. No es recomendable utilizar todos los tipos de datos disponibles para fechas como Timestamp. Por experiencia prefiero usar el simple java.util.Date para evitar futuros problemas y otras sorpresas. El formato almacenado en la tabla de la base de datos se parece a: ‘YYYY-MM-dd HH:mm:ss.0’. Entre la Fecha y la Hora hay un espacio y .0 indica un offset. Este desfase describe la zona horaria. La zona horaria estándar de Europa Central CET tiene un desfase de una hora. Eso significa UTC+01:00 en formato internacional. Para definir el offset por separado obtuve buenos resultados utilizando java.util.TimeZone, que funciona perfectamente junto con Date.

Antes de continuar os voy a mostrar un pequeño fragmento de código en Java para el gestor OR de Hibernate y cómo podríais crear esas columnas de la tabla.

@Table(name = "ARTICLE")
public class ArticleDO {

    @CreationTimestamp
    @Column(name = "CREATED")
    @Temporal(TemporalType.DATE)
    private Date created;

    @Column(name = "PUBLISHED")
    @Temporal(TemporalType.DATE)
    private Date published;

    @Column(name = "DEFAULT_TIMEZONE")
    private String defaultTimezone;

    //Constructor
    public ArticleDO() {
        TimeZone.setDefault(Constraints.SYSTEM_DEFAULT_TIMEZONE);
        this.defaultTimezone = "UTC+00:00";
        this.published = new Date('0000-00-00 00:00:00.0');
    }

    public Date isPublished() {
        return published;
    }

    public void setPublished(Date publicationDate) {
    	if(publicationDate != null) {
        	this.published = publicationDate;
    	} else {
    		this.published = new Date(System.currentTimeMillis());
    	}
    }
}  
Java
INSERT INTO ARTICLE (CREATED, PUBLISHED, DEFAULT_TIMEZONE)
    VALUES ('1984-04-01 12:00:01.0', '0000-00-00 00:00:00,0', 'UTC+00:00);
SQL

Veamos un poco más de cerca el listado anterior. Primero vemos la anotación @CreationTimestamp. Esto significa que cuando el objeto ArticleDO se crea, la variable creada se inicializa con la hora actual. Este valor nunca debe cambiar, porque un artículo puede ser creado una sola vez pero cambiado varias veces. La Zona Horaria se almacena en un String. En el Constructor puedes ver como la Zona Horaria del sistema puede ser tomada – pero ten cuidado este valor no debe confiarse mucho. Si tienes un usuario como yo que viaja mucho, verás que en todos los lugares en los que estoy tengo la misma hora del sistema, porque normalmente nunca la cambio. Como zona horaria por defecto defino la cadena correcta para UTC-0. Lo mismo hago para la variable publicada. Date también puede ser creada por un String lo que usamos para establecer nuestro valor cero por defecto. El Setter para published tiene la opción de definir una fecha futura o usar la hora actual en el caso de que el artículo se publique inmediatamente. Al final del listado demuestro una simple importación SQL para un solo registro.

Pero no hay que precipitarse. También tenemos que prestar un poco de atención a cómo tratar con el desplazamiento UTC. Debido a que he observado en los sistemas enormes varias veces los problemas que se produjeron porque el desarrollador se utilizó sólo los valores predeterminados.

La zona horaria en general forma parte del concepto de internacionalización. Para gestionar correctamente los ajustes de desfase podemos decidir entre diferentes estrategias. Como en tantos otros casos, no hay un claro correcto o incorrecto. Todo depende de las circunstancias y necesidades de su aplicación. Si se trata de un sitio web de ámbito nacional, como el de una pequeña empresa, y no hay eventos críticos en el tiempo, todo resulta muy sencillo. En este caso no será problemático gestionar la configuración de la zona horaria automáticamente por el DBMS. Pero hay que tener en cuenta que en el mundo existen países como México con más de una zona horaria. Un sistema internacional donde los clientes se extienden por todo el mundo podría ser útil para configurar cada DBMS en el clúster a UTC-0 y gestionar el desplazamiento por la aplicación y los clientes conectados.

Otra cuestión que debemos resolver es cómo inicializar el valor de la fecha de un registro por defecto. Porque los valores nulos deben evitarse. Una explicación completa de por qué devolver null no es un buen estilo de programación se encuentra en libros como ‘Effective Java’ y ‘Clean Code’. Tratar con Excepciones de Puntero Nulo es algo que realmente no necesito. Una buena práctica que funciona bien para mí es una fecha por defecto – valor de tiempo por ‘0000-00-00 00:00:00.0’. Así evito publicaciones no deseadas y el significado es muy claro para todos.

As you can see there are good reasons why Boolean data types should replaced by Date. In this little article I demonstrated how easy you can deal with Date and timezone in Java and Hibernate. It should also not be a big thing to convert this example to other programming languages and Frameworks. If you have an own solution feel free to leave a comment and share this article with your colleagues and friends.

La Ley de Conway

Dado que el diseño elegido en primer lugar casi nunca es el mejor posible, el…

Lo último no siempre es lo mejor

A qué hay que prestar atención en el entorno comercial para que las actualizaciones de…

README – cómo saber

Los archivos README son archivos de texto y están formateados en notación markdown. El portal…

Opciones de automatización en la gestión de la configuración del software

El desarrollo de software ofrece algunas formas extremadamente eficaces de simplificar tareas recurrentes mediante la…

Anti-Pattern de números de versión

En este artículo analizamos algunas de las mejores prácticas para trabajar con números de versión…

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *