Project Lombok: ordine e pulizia in Java

Uno degli strumenti che dovrebbe necessariamente far parte dell’“arsenale del giovane programmatore Java” è certamente Project Lombok.

Project Lombok è una simpatica libreria che permette di scrivere codice Java estremamente pulito e conciso riducendo drasticamente la verbosità del linguaggio.

Tramite l’utilizzo di Java annotation (e reflection) la libreria genererà per noi il codice di getter e setter, costruttori, metodi toString e molti altri elementi utili (e noiosi da definire di volta in volta).

Installazione

Se stiamo usando Maven nel nostro progetto, possiamo aggiungere Project Lombok come dipendenza:

<dependency>
  <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>...versione...</version>
  <scope>provided</scope>
</dependency>

Se invece state utilizzando altri build automation tool, vi rimando alla sezione Install => Build tools del sito ufficiale.

Dichiarare classi

Uno dei motivi principali per utilizzare Project Lombok è la semplicità con cui riusciamo a dichiarare le nostre classi evitando di creare codice ripetitivo e difficile da manutenere.

La libreria mette a disposizione diverse annotazioni che ci consentono di definire quali elementi dovranno essere presenti nella nostra classe.

Par comprendere la semplificazione che si riesce ad ottenere, partiamo da un classico Java bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.Objects;

public class Point {
    private int x;
    private int y;

    public Point() {
    }

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x &&
                y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }

    @Override
    public String toString() {
        return "Point{" + "x=" + x + ", y=" + y + '}';
    }
}

Nonostante abbia scelto un oggetto molto semplice e non mi sia soffermato particolarmente sull’ implementazione del metodo hashCode, ho ottenuto quasi 50 linee di codice!

Applichiamo ora le annotazioni di Project Lombok e facciamo un po’ di pulizia:

1
2
3
4
5
6
7
8
9
10
11
12
import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class Point {
    private int x;
    private int y;
}

Che ve ne pare? 12 righe di codice… Niente male!

Ma possiamo fare di più:

1
2
3
4
5
6
7
8
9
import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Point {
    private int x;
    private int y;
}

Alcune utili annotazioni

Passiamo ora in rassegna le annotazioni utilizzate nell’esempio precedente:

  • @Getter e @Setter, prevedibilmente, sono le annotazioni che consentono di omettere gli accessors nella definizione della nostra classe. Entrambe le annotazioni possono essere utilizzate a livello di campo o a livello di classe: nel secondo caso, i metodi get e set verranno generati per tutti i campi non-statici.

  • @EqualsAndHashCode genera automaticamente i metodi equals e hashCode per la nostra classe. È possibile configurare quali campi verranno utilizzati per l’implementazione utilizzando gli elementi exclude e of dell’annotazione.

  • @ToString è ovviamente la scorciatoia da utilizzare per ottenere la rappresentazione testuale dei nostri oggetti. Anche in questo caso è possibile utilizzare gli elementi exclude e of dell’annotazione per configurare in modo granulare quali campi includere (o escludere).

  • @NoArgsConstructor consente di generare il costruttore senza argomenti, mentre @AllArgsConstructor produce un costruttore sulla base di tutti i campi dichiarati nella classe.

Nell’ultimo esempio, infine, abbiamo utilizzato un’ulteriore scorciatoia: l’annotazione @Data consente di applicare in un solo colpo @ToString, @EqualsAndHashCode, @Getter, @Setter e @RequiredArgsConstructor. Quest’ultima annotazione non è però utile nel nostro caso, in quanto serve a generare un costruttore sulla base dei campi contrassegnati con l’annotazione @NonNull.

Per la documentazione completa e per conoscere le altre annotazioni disponibili vi rimando alla pagina ufficiale del progetto.

var e val

Molto prima dell’arrivo di Java 10, in tempi non sospetti, Project Lombok metteva a disposizione degli sviluppatori Java la keyword var.

Utilizzando var possiamo sfruttare la type inference per le variabili locali, caratteristica a lungo invidiata a linguaggi più giovani.

In un certo senso, però, Project Lombok continua a fare meglio di Java, introducendo anche una seconda parola chiave, val, attraverso la quale possiamo indicare una variabile final:

void test() {
    var i = 0;
    val y = 6;
    y = i + 3; // Error: cannot assign a value to final variable y
    System.out.println(i + y);
}

Eseguendo il codice appena riportato potreste incappare in questo errore:

Error: Use of var is disabled by default. Please add 'lombok.var.flagUsage = ALLOW' to 'lombok.config' if you want to enable is.

Come chiaramente descritto, per utilizzare la keyword var nel nostro codice sarà necessario aggiungere nella root del nostro progetto (di norma /src/main/java) il file lombok.config, abilitando esplicitamente la funzionalità.

Integrazione con gli IDE

Per lavorare con Project Lombok nel nostro IDE di fiducia tipicamente basta aggiungere un apposito plugin.

Per IntelliJ IDEA, il plugin da installare è Lombok Plugin. Piccola accortezza: per far sì che il plugin funzioni correttamente accertatevi che l’opzione Enable annotation processing, nel menù Settings => Build, Execution, Deployment => Compiler => Annotation Processors, sia spuntata.

Il plugin per Eclipse invece, è (insospettabilmente) incluso all’interno del jar contentente la libreria. Basterà scaricare il pacchetto dal sito di Project Lombok ed eseguirlo facendo doppio click.

Per gli altri ambienti di sviluppo attualmente supportati vi rimando alla sezione Install => IDEs della pagina ufficiale.

In conclusione

Chi lavora con Java da qualche anno sa bene quanto può essere verboso questo linguaggio in alcune situazioni e quanto lavoro può comportare aggiungere (o semplicemente rinominare) un singolo campo di una classe.

Project Lombok ci risparmia un po’ di noia e ci aiuta a migliorare in modo sensibile la leggibilità del nostro codice.

Con questo concludo; fatemi sapere cosa ne pensate. :-)

Alla prossima,

David