Easy classes with Kotlin

kotlinlang.org

Tengo que decir que a pesar de todo me encanta programar en Java; y el JDK11 (en realidad a partir del 8) le han dado una nueva vida con lambdas, opcionales, inferencia de tipos,…

Pero el principal problema de Java sigue ahí: algunas cosas que deberían ser sencillas son tan treméndamente farragosas que se hacen insufribles.

Una de estas cosas son las clases de datos (JavaBeans o DTO si quieres). De hecho es tan terrible la cantidad de código trivial(*) que tienes que implementar que buscas atajos.

(*) código trivial es aquel que no debería necesitar un test ya que no-puede-fallar; pero con la cantidad de código que pide Java eso no existe: un JavaBean necesita probarse, ¡no es trivial!

Ejemplo muy simple: una clase que sólo quiere almacenar mi nombre y apellidos.

public final class Person {
private final String name;
private final String surname;

public Person(final String name, final String surname) {
this.name = name;
this.surname = surname;
}

public String getName() {
return name;
}

public String getSurname() {
return surname;
}
}

Y todo esto sin poner equals, hashcode,… es realmente irritante, mucho, la estructura por ejemplo del constructor:

this.name = name;
¿El constructor asigna a la propiedad name de la clase el valor name correspondiente al parámetro name?

Lo único que puede ocurrir aquí es que te equivoques (lo mismo pasa con los dichosos getters) así que me temo, yo este código no lo tolero sin tests:

public class PersonTest {

//Class Under Test
private Person p;

@Before
public void setup() {
p = new Person("Ernesto","Arroyo");
}

@Test
public void getName() {
assertEquals("Ernesto",p.getName());
}

@Test
public void getSurname() {
assertEquals("Arroyo",p.getSurname());
}

}

¿soy el único al que esto le parece una payasada este código? ¿de verdad voy a tener que escribir todo ese código en producción, y todos esos test a mantener, para una clase que encierre mi nombre y apellido?

No. No lo soy, lo piensa mucha gente. De forma que el agua busca su cauce.

Lombok

La primera solución es usar Lombok, que no es para nada mala idea:

@Data public final class Person {
private final String name;
private final String surname;
}

Lombok está muy bien, pero hay un pequeño problema, quizás académico si quieres, y es que es casi un framework. Si empiezas a usar DDD y te dicen que el modelo de dominio debe probarse sin depender de nada que no sea el lenguaje empiezas a rayarte.

Y ocurren cosas: por ejemplo que Lombok no funciona (al escribir este artículo al menos) con JDK11. Lombok es intrusivo en el código y tienes que incluir plugins para que reescriba las clases en el momento adecuado de la compilación; también necesitas un plugin en tu IDE.

Es mucho mejor, pero no es perfecto.

Otros lenguajes de la JVM

Todos los lenguajes que salen sobre la JVM han mejorado esta tarea.

Groovy

Groovy incorpora los GroovyBeans:

class Person {
String name
String surname
}

Esto pinta bien: la clase es pública si no digo nada, me da los accesos a las propiedades,

Scala

case class Person(name: String, surname: String)

¡Ah! me gusta más todavía. Además en Scala una case class es inmutable, tienen su método copy,…

Kotlin

Las opciones de Groovy y Scala aún tienen una pequeña pega: su integración en proyectos mixtos con Java da un poco la lata. Es más, para meter “un poco de Scala” yo haría el proyecto entero en Scala.

Pero Scala no es sencillo, y si como en mi caso trabajas con Spring vas a sudar la gota gorda (ni siquiera tienes un bootstrap con Scala en spring.start.io)

Y entonces llega Kotlin:

class Person(val name: String, val surname: String)

Es, en realidad casi similar a Scala, es también una clase final por defecto y al indicar val las propiedades son inmutables, pero con la ventaja de que Kotlin tiene un soporte mucho mejor de los amigos de Pivotal sobre Spring.

En ninguna de las 4 alternativas expuestas: Lombok, Groovy, Scala y Kotlin) vas a necesitar test ya que no has tenido que hacer código para implementar una clase que sólo quiere guardar propiedades del objeto.

Aunque Scala es aún la alternativa al Java para la JVM, Kotlin está subiendo como la espuma, y ya ha desbancado a Groovy.