Uma visão sobre o Projeto Lombok

Veja neste artigo uma introdução acerca do Projeto Lombok, um projeto licenciado pela Apache que provê o uso de anotações para substituir os métodos tidos como clichês no Java.

O que é o Projeto Lombok?

Todo desenvolvedor Java sabe que Java envolve escrever um monte de código que as vezes pode ser encaixado como "clichê". Como por exemplo, criar um objeto de valor (ou "objeto de transferência de dados") e você pode ter um comportamento desse tipo pelo menos com uma dúzia de propriedades em uma classe. Essas doze declarações são a única coisa importante na classe. Depois que você criar uma centena de linhas de getters, setters (se não imutável), de equals/hashCode e um método toString, possivelmente todos gerados pela IDE.

Este é um processo sujeito a erros, mesmo quando gerado por uma IDE. Uma IDE não irá dizer se, por exemplo, você adicionar outro membro de dados e não se regenerarem seus métodos equals e hashCode.

O projeto Lombok visa reduzir muito a necessidade de tais "clichês" usando anotações para gerar tais métodos automaticamente.


Figura 1: Tela de instalação do projeto no Eclipse

O que o Projeto Lombok consegue fazer?

O Projeto Lombok tem sete annotations para minimizar o uso de código repetitivo. Confira os mesmos na Tabela 1.

Anotação Descrição Tabela 1:Tabela de Annotations disponíveis

ble>

Para se ter uma noção mais exata do efeito que esse framework pode trazer às classes de um projeto Java, veja a diferença entre uma classe entidade criada da forma antiga, ou seja, com todos os métodos originais citados (Listagem 1) e outra classe criada usando o Lombok (Listagem 2).

Listagem 1: Exemplo de classe comum Java com métodos "clichês"

import java.util.Arrays; public class POJOExemplo { private final String nome; private int idade; private double peso; private String[] tags; public POJOExemplo(String nome) { this.nome = nome; } public String getNome() { return nome; } void setIdade(int idade) { this.idade = idade; } public int getIdade() { return idade; } public void setPeso(double peso) { this.peso = peso; } public double getPeso() { return peso; } public String[] getTags() { return tags; } public void setTags(String[] tags) { this.tags = tags; } @Override public String toString() { return "POJOExemplo(" + nome + ", " + idade + ", " + peso + ", " + Arrays.deepToString(tags) + ")"; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != this.getClass()) return false; POJOExemplo other = (POJOExemplo) o; if (nome == null ? other.nome != null : !nome.equals(other.nome)) return false; if (idade != other.idade) return false; if (Double.compare(peso, other.peso) != 0) return false; if (!Arrays.deepEquals(tags, other.tags)) return false; return true; } @Override public int hashCode() { final int PRIME = 31; int result = 1; final long temp1 = Double.doubleToLongBits(peso); result = (result * PRIME) + (nome == null ? 0 : nome.hashCode()); result = (result * PRIME) + idade; result = (result * PRIME) + (int) (temp1 ^ (temp1 >>> 32)); result = (result * PRIME) + Arrays.deepHashCode(tags); return result; } public static class Exercicio<t> { private final String nome; private final T valor; private Exercicio(String nome, T valor) { this.nome = nome; this.valor = valor; } public static <t> Exercicio<t> of(String nome, T valor) { return new Exercicio<t>(nome, valor); } public String getnome() { return nome; } public T getvalor() { return valor; } @Override public String toString() { return "Exercicio(nome=" + nome + ", valor=" + valor + ")"; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != this.getClass()) return false; Exercicio<?> other = (Exercicio<?>) o; if (nome == null ? other.nome != null : !nome.equals(other.nome)) return false; if (valor == null ? other.valor != null : !valor.equals(other.valor)) return false; return true; } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = (result * PRIME) + (nome == null ? 0 : nome.hashCode()); result = (result * PRIME) + (valor == null ? 0 : valor.hashCode()); return result; } } }

Listagem 2: Mesma classe com métodos do Projeto Lombok

import lombok.AccessLevel; import lombok.Setter; import lombok.Data; import lombok.ToString; @Data public class POJOExemplo { private final String nome; @Setter(AccessLevel.PACKAGE) private int idade; private double peso; private String[] tags; @ToString(includeFieldNames = true) @Data(staticConstructor = "of") public static class Exercise<t> { private final String nome; private final T valor; } }

O Projeto Lombok faz uso de annotations. As anotações são muito famosas entre os desenvolvedores Java e são amplamente usadas para sobrescrever métodos (@Override), para desabilitar avisos da IDE (@SupressWarnings) ou quando se faz uso de APIs específicas como JPA, Spring, por exemplo. Se você não tem muitos conhecimentos sobre anotações, mesmo sendo fácil de usá-las, seria aconselhado que se faça uma pesquisa sobre o assunto.

O que o Lombok faz direito?

Em primeiro lugar, usar Lombok com Maven é fácil. Normalmente não é difícil encontrar as bibliotecas corretas usando o Maven, mas às vezes é. Além disso, a documentação não é super-extensa (como, por exemplo, a do Spring normalmente é), mas com certeza é melhor em alguns outros (por exemplo, projetos típicos do Apache). Pelo menos, há exemplos de todas as anotações.

Outra coisa interessante sobre isso é que o projeto gera os métodos toString(), hashCode() e equals() automaticamente, mas ao contrário de algumas bibliotecas do Apache Commons, ele não faz isso através da reflexão em tempo de execução.

Por fim, o Projeto Lombok é liberado sob a licença MIT altamente permissiva.

O que o Projeto Lombok poderia fazer melhor?

Atualmente, o Projeto Lombok só se integra (bem) com Eclipse. Netbeans e IntelliJ estão de fora do escopo do projeto e apoio para as duas IDEs parece que não vai acontecer tão cedo. As pessoas tendem a se sentir muito fortemente ligadas às suas IDE's preferidas, então o fato de não ter suporte às mesmas pode constituir um fator negativo e algo a ser melhorado.

Os plug-ins para IDEs como Netbeans e ItelliJ podem ser facilmente criados através dos recursos disponibilizados pelas próprias ferramentas.

Concluindo

O Projeto Lombok é leve, prático e não exibe o código na cara como muitos outros fazem. Particularmente, constitui um projeto interessante que merece ao mínimo uma chance e a efetuação de testes.

Casos de uso do projeto com outros frameworks como Hibernate, JPA e JSF comprovam que o mesmo foi bem recepcionado pela comunidade e pode ser aceito em projetos que você mesmo venha a trabalhar.

@Getter/@Setter Com estas anotações não se faz mais necessária a criação dos métodos de recuperação e configuração das propriedades das classes.
@ToString Não há mais necessidade de iniciar um debugger para ver os campos. Basta deixar que o lombok gere o toString()
@EqualsAndHashCode Método equals e hashCode são gerados automaticamente para os campos do objeto de forma fácil e simples
@Data Todos juntos agora: Um atalho para @ToString, @EqualsAndHashCode,@Getter em todos os campos, e @Setter em todos os campos não-finais. Você ainda pode obter um construtor livre para inicializar seus campos finals!
@Cleanup Gestão de recursos automática: Chame com segurança os métodos close()sem problemas.
@Synchronized synchronized’s corretos. Não exponha seus locks.
@SneakThrows Para lançar exceções onde antes não se era comum lançar.

Artigos relacionados