Migrar código (léase: código heredado) no es divertido. Se necesita una enorme cantidad de planificación y esfuerzo para lograrlo. Si bien no es el trabajo más emocionante o motivador para los desarrolladores, sí que requiere determinación y la experiencia adecuada para migrar el código heredado a las nuevas versiones de la biblioteca. Hora de Joda a java.time es una de esas migraciones que requiere una planificación y ejecución meticulosas.
Si su proyecto Java comenzó su vida antes de Java SE 8 y utiliza el procesamiento de fecha y hora, es probable que haya utilizado Joda-Time, una biblioteca excelente y un estándar de facto para gestionar las funciones de fecha y hora anteriores a SE 8. Si tu proyecto Aún así usa Joda-Time pero le gustaría migrar a java.time y luego siga leyendo.
La versión de Java SE 8 incluía una API de fecha y hora estándar nueva y mejorada, comúnmente denominada java.time (JSR-310). El proyecto Joda-Time ahora recomienda migrar a java.time (JSR-310).
Si bien java.time (JSR-310) se inspiró en gran medida en Joda-Time, no es compatible con versiones anteriores y los conceptos y terminologías han cambiado. Por eso, migrar de Joda-Time a java.time requiere prestar mucha atención a todas y cada una de las líneas de código que cambias. Esto puede llevar mucho tiempo y casi haría que deseara que hubiera una forma más fácil y automatizada de migrar.
Hay una forma mejor de migrar y la hemos creado con Sensei, un complemento de IntelliJ que realiza automáticamente transformaciones de código según las recetas (reglas) definidas por usted. Dedica tu tiempo a definir recetas reutilizables, en lugar de a realizar tareas de migración repetitivas. La automatización no solo transformará tu código heredado de Joda-Time, sino que también ayudará a los equipos a seguir las directrices que aparecen en el IDE a medida que escriben código nuevo.
Para ayudarlo a comenzar con ventaja, hemos creado un libro de cocina público sobre Sensei Estandarización en java.time (JSR-310) que incluye recetas para migrar de Joda-Time a java.time de una manera menos dolorosa. Se trata de un conjunto de recetas cada vez mayor que seguiremos ampliando para añadir más cobertura con más recetas.
Este es un ejemplo de un ejemplo de migración que puede ayudarle a ver cómo Sensei facilita la migración del código heredado.
Desde la migración manual repetitiva hasta las transformaciones de código automatizadas Veamos un ejemplo de creación de un nuevo DateTime que muestra algunas trampas ocultas al migrar una sola línea de código de Joda-Time a java.time. A continuación, analizaremos una de las recetas de Sensei de nuestro libro de recetas sobre la estandarización de java.time (JSR-310) y mostraremos cómo captura toda esta información para que cualquier desarrollador pueda volver a utilizar esta misma migración una y otra vez.
En este ejemplo, estamos construyendo un Joda-Time DateTime a partir de 7 argumentos int que representan los valores de los campos DateTime.
¿Cómo migramos esto a un equivalente de java.time?
El javadoc en Joda-Time para este constructor dice:
Construye una instancia a partir de los valores de los campos de fecha y hora utilizando IsoChronology en la zona horaria predeterminada. Al principio, podemos suponer que hay Fecha/hora clase en java.time, pero no hay ninguna. Si buscas en Google «migrar de la hora de Joda a la hora de Java», lo más probable es que encuentres la entrada del blog de Stephen Colebourne Conversión de Joda-Time a java.time .
Esto le da un buen comienzo y nos indica cómo usar java.time.zonedDateTime o java.time.offsetDateTime. Esta es nuestra primera pregunta, ¿cuál uso? Probablemente ZonedDateTime se basa en los comentarios de Stephen.
Buscando el ZonedDateTime javadoc , no podemos ver ningún constructor en absoluto. Volviendo a la entrada del blog de Stephen, leemos más abajo:
Construcción . Joda-Time tiene un constructor que acepta un objeto y realiza la conversión de tipos. java.time solo tiene métodos de fábrica, por lo que la conversión es un problema del usuario, aunque se proporciona un método parse () para las cadenas. Por lo tanto, debe haber un método de fábrica estático, al buscar los métodos estáticos encontramos uno que se parece bastante, pero no es exactamente el mismo.
Tiene 7 parámetros int como nuestro constructor Joda-Time DateTime original, sin embargo, si no prestas atención, te perderás un detalle importante. El séptimo parámetro ya no representa milisegundos, sino nanosegundos, ya que java.time tiene una precisión mayor que Joda-Time y mide los instantes hasta el nano-segundo. Un detalle importante que podrías haber pasado por alto fácilmente. Además, este método espera un ZoneID, por lo que hace que te preguntes por qué no necesitabas uno antes y por qué lo necesitas ahora.
Recordando el javadoc de nuestro constructor original que mencionaba que usaría la zona horaria predeterminada, ¿tal vez haya una forma de obtener el ZoneID predeterminado?
El javadoc para ZoneID no nos informa sobre ningún constructor de la lista, pero al observar los métodos estáticos vemos que podemos usar Predeterminado del sistema ()
Ahora que hemos resuelto el ZoneID, ¿qué debemos hacer con nuestra conversión de milisegundos a nanosegundos? Tal vez podamos usar java.util.Concurrent.TimeUnit para realizar la conversión.
Este método devuelve un valor long y nuestro método espera un int, por lo que ahora también tenemos que resolver un problema de conversión. Tal vez podríamos probar algo simple. ¿Una multiplicación?
Esto funcionará, pero parece un poco fuera de lugar. Si aún no lo has notado, hemos dedicado una cantidad considerable de tiempo y esfuerzo a migrar una sola línea de código. Pero como puedes imaginar, tenemos muchas ediciones de este tipo que hacer a mano y no hay nada mejor.
Sin embargo, si analizamos un poco más la API java.time, podemos descubrir una solución que parece un poco más fluida.
Aunque ZonedDateTime no tiene una forma obvia de configurar los milisegundos, se puede hacer usando el con el método (campo temporalField, newValue largo) , utilizando Cronofield. Mili_de_segundo como TemporalField.
Y el documento de Java menciona que realizará la conversión a nanosegundos por nosotros:
Cuando este campo se usa para establecer un valor, debe comportarse de la misma manera que si se establece NANO_OF_SECOND con el valor multiplicado por 1 000 000. Así que podemos simplemente especificar 0 para nuestros nanosegundos en el método de fábrica y, a continuación, usar el con método para crear un ZonedDateTime que tenga todos los valores originales, así como los milisegundos.
Al observar nuestro resultado final, parece que solo hemos cambiado una línea de código, ¡realmente no muestra el esfuerzo que se dedicó a investigar solo una migración!
Cree una receta para migrar de forma más rápida y sencilla Sensei nos proporciona una forma de compartir esta información ganada con tanto esfuerzo con otros desarrolladores. Al crear una receta que recoja todos estos requisitos, permitirá a los usuarios de Sensei realizar esta migración con solo un clic del ratón.
Una receta de Sensei consta de 3 secciones principales:
Metadatos Búsqueda Correcciones disponibles Veamos una receta de Sensei (también se puede ver como una receta de YAML) que nos ayudará a migrar esta llamada a su equivalente en java.time.
DateTime foo = nueva fecha y hora (año, mes del año, día del mes, hora del día, minuto de hora, segundo de minuto, milisegundo de segundo); Sección de metadatos La sección de metadatos contiene información sobre la receta y cómo debe usarse.
Sección de búsqueda La sección de búsqueda de una receta de Sensei especifica a qué elementos de código se debe aplicar esta receta.
buscar: Creación de instancias: argumentos: 1: tipo: int 2: tipo: int 3: tipo: int 4: tipo: int 5: tipo: int 6: tipo: int 7: tipo: int Recuento de arg: 7 tipo: org.joda.time.DateTime
En esta sección de búsqueda vemos que estamos:
En busca de un Creación de instancias, es decir, el uso de un Constructor. Nota: hay muchos otros objetivos de búsqueda disponibles El constructor debe tener 7 argumentos, esto se especifica en Recuento de arg propiedad argumentos 1-7 debe ser de tipo intEstamos buscando a los constructores del tipo org.joda.time.dateTime
Sección de correcciones disponibles La sección AvailableFixes puede especificar una o más correcciones que se pueden aplicar al elemento de código coincidente. Cada corrección puede tener varias acciones y, en nuestro caso, tenemos una única solución que realiza 2 acciones.
El nombre de la solución se muestra al usuario en el menú «Correcciones rápidas» y describe lo que ocurrirá si el usuario aplica esta solución rápida La lista de acciones muestra las acciones que realizará esta solución rápida. El volver a escribir la acción reescribirá el elemento de código utilizando una plantilla de bigote. Puede hacer uso de variables y funciones de reemplazo de cadenas. El Modificar variable asignada action comprobará si este constructor se utiliza para asignar el valor a una variable. Si es así, esta acción modificará la variable para declararla como el tipo especificado por tipo
Uso de la receta para realizar la transformación del código Con nuestra receta escrita y habilitada, escanea nuestro código y resalta los segmentos a los que se puede aplicar.
En la siguiente captura de pantalla podemos ver que el constructor objetivo ha sido marcado por Sensei. Al pasar el ratón sobre el constructor marcado, aparecen la opción Recipe ShortDescription y Quickfix Migrar a java.time.ZonedDateTime
Después de seleccionar el Migrar a java.time.ZonedDateTime Quickfix, el código se transforma de acuerdo con las acciones que especificamos en la receta.
Una migración única y prácticas de codificación uniformes en todos los equipos, con Sensei En nuestro ejemplo anterior, podemos ver que la migración de una sola línea de código puede implicar un conocimiento adquirido con esfuerzo. Sensei puede convertir ese conocimiento en recetas prácticas o libros de cocina que puedan compartirse entre equipos. Puedes planificar una migración rápida única o adoptar el enfoque de realizar transformaciones instantáneas incrementales a java.time a medida que te encuentres con el código de Joda-Time. Puedes activar o desactivar las recetas para realizar las migraciones por etapas o pasos lógicos e incluso ampliar o reducir el alcance de los archivos analizados por Sensei, con la flexibilidad que hace que las migraciones de código sean menos complicadas.
La migración de bibliotecas es solo un ejemplo de las muchas maneras en las que se puede usar Sensei para estandarizar sus proyectos. Siempre puedes estar atento a los antipatrones o a ciertas transformaciones manuales de código que aparecen con frecuencia en las solicitudes de cambios o mientras codificas tú mismo. Si tienes un conjunto de directrices de codificación que los desarrolladores suelen pasar por alto, podrías convertir las directrices en recetas, lo que permitiría a los desarrolladores aplicar las transformaciones de código aprobadas con confianza.
Si tiene alguna pregunta, ¡nos encantaría saber de usted! Únete a nosotros en Slack en: sensei-scw.slack.com