leanmind logo leanmind text logo

Blog

Código Sostenible

Cómo escribir código fácil de mantener mediante valores, principios y técnicas.

Simplificando Java con Lombok

Por José Luis Rodríguez Alonso

Uno de los problemas de Java es lo verboso y complicado que puede llegar a ser para tareas tan cotidianas como hacer un simple objeto y poder compararlo con otro. Pelearse con un equals y hashcode no es nada divertido.

El Proyecto Lombok viene a solucionar esos detalles. Lombok es algo así como un preprocesador de CSS o Javascript, pero para Java. A partir de unas anotaciones, es capaz de generar código por nosotros. La gracia es que el código se genera al compilar nuestros archivos .java, por lo que no supone ninguna penalización en tiempo de ejecución.

He utilizado Lombok en los tres últimos proyectos y estoy bastante contento con el resultado. Es cierto que solo utilizamos una fracción de las opciones disponibles, pero aún así vale la pena darle una oportunidad.

Configuración

Lombok genera código en tiempo de compilación, por eso debemos configurar nuestro proyecto en IDE para ello.

En primer lugar, debemos configurar nuestro archivo Gradle añadiendo las dependencias de Lombok:

compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'

Con esto, ya podríamos hacer uso de Lombok, pero nos faltaría otra parte importante. Necesitamos configurar nuestro IDE para que sea consciente del código que Lombok está generando para nosotros, de lo contrario obtendríamos errores por todos lados. IntelliJ IDEA, Eclipse, Netbeans… todos tienen un plugin de Lombok disponible. En el caso de IntelliJ, debemos configurar el proyecto para activar el “preprocesado” de anotaciones.

Esto se puede hacer desde Preferences > Annotation Processors > Enable annotation processing

Ejemplos

Para no hacer muy extenso el artículo, solo hablaré de las opciones que utilizo en el día a día. El resto las tienes en la documentación oficial.

@Value

Con la anotación @Value indicamos a Lombok que queremos convertir nuestro objeto en un objeto inmutable.

1
2
3
4
5
@Value
public class Student {
	private final int id;
	private final String name;
}

Solo tenemos que añadir la anotación y declarar nuestras propiedades como private final. Con esta anotación conseguimos varias cosas:

  1. Crear los getters para nuestras propiedades
  2. Crear un constructor con nuestras propiedades
  3. Crear un método toString
  4. Crear un método equals
  5. Crear un método hashcode

Todo eso escribiendo solo una palabra :) Además, al no tener que escribir todo ese código, tenemos más espacio para añadir funcionalidad a nuestros objetos. :tada:

También es posible configurar el comportamiento de Lombok de forma más granular, por ejemplo, si no te interesa generar los getters o no quieres crear un toString.

@Builder

El patrón builder resulta muy útil si estamos trabajando con objetos inmutables. Hacer un builder a mano es una tarea que requiere cierto tiempo y es también propenso a errores si no lo testeamos bien. Con Lombok, solo es necesario anotar tu modelo con @Builder.

1
2
3
4
5
6
@Value
@Builder
public class Student {
	private final int id;
	private final String name;
}

Al añadir esa anotación, Lombok nos crea automáticamente un Builder para nuestra clase usando todas las propiedades. Luego, lo podemos utilizar en nuestra aplicación de esta forma:

1
2
3
4
var student = Student.builder()
	.id(1)
	.name("Ignatius")
	.build();

Pretty cool, tbh :) Solo con estas dos anotaciones ya merece la pena darle una oportunidad.

En el paquete “estable” de Lombok, hay otras anotaciones que he usado en algunos casos puntuales:

@With

Con With, podemos hacer una copia de un objeto inmutable cambiando solo alguna de sus propiedades. Por ejemplo:

1
2
3
4
5
6
7
@Value
@With
public class User {
	private final int id;
	private final String name;
	private final String accessToken;
}

El código anterior nos crea métodos with para cada una de las propiedades:

var user = currentUser.withAccessToken(newAccessToken);

De esta forma, a partir de un “usuario” existente, podemos obtener un nuevo “usuario” con solo una de sus propiedades modificadas. También es posible encadenar varios withX o anotar solamente la propiedad donde nos interesa tener esta funcionalidad.

@Singular

En algunas situaciones, puede ser interesante añadir @Singular sobre una colección cuando estamos utilizando un @Builder. Con Singular, conseguimos crear un método con el nombre de la colección en singular y con un solo elemento como parámetro. De esta forma, podemos añadir elementos a la lista de forma fluida en lugar de crear primero la lista y luego establecerla.

1
2
3
4
5
@Builder
public class Company {
	@Singular
	private final List<String> skills;
}

Al añadir “Singular” a nuestra lista de skills, podemos hacer cosas como esta:

1
2
3
var company = Company.builder()
	.skill("TDD")
	.build();

En el ejemplo anterior, estaríamos añadiendo una única “skill” a nuestra lista. También es posible llamar a ese método varias veces para añadir más elementos a la lista:

1
2
3
4
var company = Company.builder()
	.skill("TDD")
	.skill("Java")
	.build();

Por supuesto, la versión en plural sigue estando disponible en nuestro builder:

1
2
3
var company = Company.builder()
	.skills(List.of("TDD", "Java"))
	.build();

Conclusión

El proyecto Lombok es algo controvertido, hay gente que lo ama y gente que lo odia. En mi caso, me simplifica tanto la vida que me da igual todo lo demás :D

Es cierto que con cada nueva versión de Java, algunas de sus funcionalidades dejan de tener sentido, por ejemplo, con la inclusión de las nuevas clases record de Java 14, puede que no tenga sentido usar @Value. Aún así, es un proyecto estable con más de 10 años de desarrollo que ahorra una cantidad importante de bugs y nos simplifica la vida como desarrolladores.

Publicado el 06/03/2020 por
José Luis image

José Luis Rodríguez Alonso

¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.

Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?

Impulsamos el crecimiento profesional de tu equipo de developers