Pri Lombok

Estas prinoto por tio!
  EN, FR
 6 min. legi
 chop
 Ankoraŭ neniu komento
  (laste mod.: 2022-04-20)

Kelkajn monatojn antaŭe, nia teamo bonvenigis novulon. Aldone al nia misio, li ankaŭ malkovris Java, post kelkaj jaroj kiel .NET-programisto. Inter iliaj unuaj reagoj, estis pluraj “Kio, vi devas fari ĝin vi mem, en Java? En .NET, estas la tradukilo, kiu faras ĝin por vi!”

Vere, en Java, la lingvo kaj konvencioj kondukas al signifa kvanto de malaltvalora kodo. Sed ne timu! Lombok celas simpligi tiun taskon por vi.

Ĉi tiu afiŝo ne estas lernilo, sed simple rapida enkonduko pri tio, kion Lombok povas fari por vi.

La celo #

Kio estas boilerplate kodo? #

Imagu skribi Java klason, respektante ĉiujn bonajn praktikojn. Ĉiu kampo devas esti private kaj alirebla per… nu, aliriloj.

Ĝi signifas, ke ĉiufoje vi aldonas ckampon, vi devas deklari novajn getters kaj setters. Se via objekto estas neŝanĝebla, ĉiuj kampoj devas esti inicialigitaj al la generado. Tio implicas, ke via konstruilo devas provizi ilin per valoro kaj novaj kampoj devas esti aldonitaj al la argumentoj.

Tio estas boilerplate kodo. Estas kodo en ĉiuj projektoj, kun malmulte da logiko, frustrante da skribi ĉar oni ofte sentas, ke maŝino povus fari ĝin anstataŭe al homo (fakte, la plimulto de la programadaj medioj povas generi ĝin per kelkaj klakoj aŭ klavarokomandoj).

Kiam oni konas aliajn lingvojn, kie ĉio estas implicita aŭ simple deklaracia (kiel TyepScript aŭ C#), eksplicite tajpi ĉi tiun kodon aspektas kiel relikvo el alia tempo. Ĝi ŝajnas malaktuala, aŭ almenaŭ dolora.

Kiel Lombok solvas tion? #

Lombok rondiras cirkaŭ prinotoj: anstataŭ tajpi mem la boilerplate kodo, vi deklaras tion, kion vi volas have en via klaso. Ekzemple, se vi bezonas konstruilon kiu prenas unu argumenton per kampo, vi prinotas vian klason per @AllArgsConstructor. Mi donos kelkajn aliajn ekzemplojn malsupre.

Sed kio okazas al ĉi tiuj prinotoj? Ni alkutimiĝis, ke ili estas uzataj ĉe rultempo por personecigi la konduton, injekti aspekton aŭ alian helpon por malkovri la klason (Spring, Jackson, dankon pro via helpo). Lomnok tamen estas malsama.

Krom provizi kolekton de prinotoj, Lombok ankaŭ estas prinotprocesoro: se ĝi estas sur la klasvojo de via Java kompililo, ĝi analizos la prinotan kodon je kompiltempo kaj generos klasojn laŭ viaj indikoj. Dank’al tio, tajpi la kodon estas pli komforta, sed estas neniun efikon al la rendimento de via aplikaĵo ĉar reflektado ne estos uzata tiam.1

Kie komenci? #

Mi preferas insisti: tio afiŝo ne estas lernilo. Mi nur montras al vi tion, kion vi povus malkovri, se vi pli studos Lombok.

Por labori kun Lombok vi bezonos:

  • Maven dependeco;
  • etendaĵo por via programa medio.

Agordo de Maven #

Ne estas komplika, vi vidos. En via POM, aldonu la dependecon:

1<dependency>
2  <groupId>org.projectlombok</groupId>
3  <artifactId>lombok</artifactId>
4  <version>1.18.22</version>
5  <scope>provided</scope>
6</dependency>

Ĉi tio estas ĉio! En le plimulto de la kazoj, ĝi sufiĉas.

Esceptoj #

Vi bezonos plian agordon en du kazoj:

  • se vi uzas JDK9+ kun module-info.java;
  • aŭ se vi jam agordis prinotprocesoron2.

Se vi estas en ĉi tiu situacio, vi devas agordi la etikedoj annotationProcessorPaths de Maven Compiler Plugin. Ĝi aspektas jene:

1<annotationProcessorPaths>
2	<path>
3		<groupId>org.projectlombok</groupId>
4		<artifactId>lombok</artifactId>
5		<version>1.18.22</version>
6	</path>
7</annotationProcessorPaths>

Ĉio estas bona!

Noto pri la scope de la dependeco #

Vi eble rimarkis, ke mi metis la dependecon en la scope provided. Ĝi estas maniero diri al Maven, “Mi ne bezonas ĉi tiun dependecon inkluzivita ĉe rultempo.” Vi bezonas la prinotojn por la programtradukado, sed ili estas forigitaj de la klaso tiam.

Se vi uzas la fat jar de Spring Boot (kaj verŝajne aliajn similajn mekanismojn), la scope provided estas ignorita. En ĉi tiu kazo, vi povas uzi la etikedon <optional>true</optional> por indiki ne enigi la dependecon.

1<dependency>
2  <groupId>org.projectlombok</groupId>
3  <artifactId>lombok</artifactId>
4  <version>1.18.22</version>
5  <scope>provided</scope>
6  <optional>true</optional>
7</dependency>

La etendaĵo de la programa medio #

La programaj medoij kutime kompilas la klasojn ĉiufoje kiam oni modifas ilin, sed ili uzas siajn proprajn agordojn por tio kaj ne zorgas pri prinotprocesoroj, krom se vi instalis la ĝustajn etendaĵojn. Por Lombok, la medio avertos, ke ĝi ne konas la la getter kiun vi alvokas.

Lombok provizas la etendaĵojn por Eclipse-bazita medioj, IntelliJ produktoj, Netbeansredaktilo kongrua kun Visual Studio Code. Nur retumu al la adekvata paĝon en la retejo de Lombok (en la menuo « Install ») kaj eltrovu la instalan metodon por via ilo.

Kelkajn ekzemploj de Lombok prinotoj #

Ĉio estas en loko. Per kio komenci?

Mi proponas vidi la bazaĵojn: aliriloj.

Aliriloj #

Ni imagu, ke ni tajpas DTO, kaj ni ne volas ekspliciti getters kaj setters. Ni nur bezonas prinoti la klason (aŭ kampojn) per @Getter kaj @Setter, kaj la programado estas farita!

Defaŭlte, aliriloj estos public, sed eblas anstataŭi ĉi tiun agordon.

 1import lombok.AccessLevel;
 2import lombok.Getter;
 3import lombok.Setter;
 4
 5@Getter
 6@Setter
 7public class Book {
 8    private String title;
 9    private String author;
10
11    @Getter(access = AccessLevel.NONE)
12    private String somePrivateFieldThatMustNotHaveAGetter;
13}

Malpli multvorta ol niaj regulaj POJO-oj, ĉu ne?

Konstruiloj #

Vi bezonas konstruilon por krei vian klason. Lombok disponigas tri prinotojn por tiu celo:

  • @NoArgsConstructor estas memklarigebla.
  • @AllArgsConstructor ankaŭ estas.
  • @RequiredArgsConstructor kreas konstruilon kun argumento por ĉiu kampo, kiu devas esti pravigita ĉe instiigo (ekz. final kampoj).

Kiel ĉe aliriloj, vi povas ŝanĝi la videblecon per la parametro access.

 1import lombok.AccessLevel;
 2import lombok.AllArgsConstructor;
 3import lombok.Getter;
 4import lombok.NoArgsConstructor;
 5import lombok.Setter;
 6
 7@Getter
 8@Setter
 9@AllArgsConstructor
10@NoArgsConstructor(access = AccessLevel.PROTECTED)
11public class Book {
12    private String title;
13    private String author;
14}

Kaj tie, la bonŝanca ĉarmo: vi ne plu bezonas ĝisdatigi vian konstruilon ĉiufoje kiam vi modifas la kampojn. Ĉi tio ĉio okazos aŭtomate!3

Builders #

Kun la tempo, mi emas fari neŝanĝeblajn objektojn. Tamen, krei neŝanĝeblan POJO kun multaj kampoj estas doloro, kaj la kosntruilo kun ĉiuj argumentoj ofte rapide perdas klarecon. Pro ĉi tiuj kialoj, mi amas la ŝablono builder.

Kaj Lombok havas prinoton por tio ankaŭ!

Mi do povas ŝanĝi mia Book klason tiel:

1import lombok.Builder;
2import lombok.Getter;
3
4@Builder
5@Getter
6public class Book {
7    private String title;
8    private String author;
9}

Kaj anstataŭ uzi new, mi kreos instanco kun la sekva kodo:

1Book.builder()
2    .title("Roverandom")
3    .author("John Ronald Reuel Tolkien")
4    .build();

Se vi iam tajpis builder mem, vi devas aprezi la ŝparitan tempon per eta prinoto.

Pli, multe pli #

Ni ĉesos la ekzemplojn ĉi ti. Mi ne volas enuigi vin. Nur konsciu, ke Lombok ankaŭ provigas prinotojn por generi viajn equals() kaj hashcode(), viaj toString(), aŭ eĉ aldoni log kampon de via plej ŝatata registrada framo.

Rimarku ankaŭ, ke vi povas modifi iujn defaŭltajn kondutojn per lombok.config dosiero ĉe la radiko de via projekto, apud via pom.xml.

Por plu #

Komprenenble, vi povas trovi multajn lernilojn pri Lombok, sed mi kore invitas vin rigardi la oficialan dokumentaron. Ĝi estas bone, ĉiu pronoto estas detala kun ekzemplo, la ekvivalenta “vanila” Java kodo kaj eblaj agordoj.

Kaj kiel kun ajna nova ilo, iom da eksperimentado helpos vin lerni ĝin pli rapide.


  1. En la plej malbona kazo, la efiko estos sur la kompiltempo, sed krom se vi havas vere grandan projekton kaj multe uzas Lombok, mi ne certas, ke vi povas fari la diferencon. ↩︎

  2. Normale, Maven Compiler Plugin aŭtomate detektas la prinotprocesorojn el la dependecojn. Tamen, se procesorojn estis mane agorditaj, tiu detekto estas malŝaltita. ↩︎

  3. Kompreneble, alvokoj al tio ĉi konstruilo devos esti adaptitaj, sed la kompililo povos rapide informi vin pri iuj alvokoj, kiuj nun estas nevalidaj. ↩︎