Java. Lombok: хорошее и плохое применение
https://t.me/javatgLombok — по-настоящему хороший инструмент, который помогает писать меньше кода и больше сосредотачиваться на реальной работе. Суть в том, как вы используете Lombok в проекте: есть как хорошие, так и плохие способы использования.
Что такое Lombok
Lombok — это библиотека Java, которая сокращает объем стандартного кода в классах. Вы добавляете аннотации, и Lombok генерирует код во время компиляции. Например, если аннотировать класс с помощью @Getter
, то Lombok сгенерирует методы-геттеры для всех переменных в классе.
Как работает Lombok
Начнем с того, как происходит процесс компиляции. В нем есть три основных этапа:
- разбор и ввод;
- обработка аннотаций;
- анализ и генерация.
На этапе разбора и ввода исходные файлы считываются в синтаксическое дерево (AST), и каждое дерево передается на ввод. Все обработчики аннотаций вызываются на этапе обработки аннотаций. Если обработчики аннотаций генерируют новые исходные файлы или файлы классов, процесс компиляции переходит к первым шагам и все запускается заново. Так повторяется до тех пор, пока не появятся новые исходные файлы или файлы классов, созданные обработчиками аннотаций. AST преобразуется в файл класса на этапе анализа и генерации.
Вся магия Lombok происходит на этапе обработки аннотаций. Задача процессора аннотаций заключается в создании новых исходных файлов или классов, но вместо этого Lombok изменяет существующие. Нигде в спецификации компилятора Java не утверждается, могут или не могут обработчики аннотаций изменять существующий исходный файл. Lombok использует эту лазейку в своих интересах. Мы можем изменить класс, который будет сгенерирован из исходного кода, изменив AST. Вот как работает Lombok.
Преимущества Lombok
Lombok упрощает написание кода, позволяя сосредоточиться только на том, что нужно реализовать, а именно — переводе бизнес-требований в код. Написание геттеров, сеттеров, конструкторов, методов equals
или реализация шаблона конструктора — это не то, на что мы должны тратить время.
Lombok позаботится об этом, просто нужно добавить подходящую аннотацию, и он сгенерирует код. Например, если нужно создать геттеры и сеттеры, достаточно аннотировать класс с помощью @Getter
и @Setter
.
Если у вас сложный объект со многими атрибутами, вы можете аннотировать класс с помощью @Builder
, и Lombok реализует шаблон builder
для этого класса.
Вот скомпилированный код вышеупомянутого класса:
Есть также множество дополнительных аннотаций, которыми можно воспользоваться в проектах, чтобы писать меньше кода, например @Cleanup
, @AllArgsConstructor
, @Data
и @Value
. Меньше кода означает меньше поводов к беспокойству. Однако Lombok добавляет код в проект во время компиляции — и иногда его оказывается больше, чем если бы вы писали самостоятельно.
Плохое применение Lombok
Иногда разработчики забывают, что Lombok генерирует код, потому что его не видно в исходном коде.
Прежде чем что-либо реализовать, многие добавляют аннотации Lombok в классы. Например, аннотируют классы DTO, используя аннотацию @Data
для создания геттеров и сеттеров. Но они забывают (или не знают), что Lombok генерирует дополнительные методы, такие как equals
, hashCode
, toString
и canEqual
. Иногда они просто не нужны, а в репозитории не должно быть ничего, что мы не используем.
У любого кода должна быть причина для существования, а если ее нет, его необходимо удалить. Ответственность за применение правильных аннотаций Lombok лежит на разработчиках. Наиболее очевидный способ исправить это — добавить аннотации @Getter
и @Setter
вместо аннотации @Data
.
Некоторые разработчики пользуются Lombok, чтобы скрывать нарушения Sonar, а не исправлять их (намеренно или непреднамеренно). Возьмите в качестве примера приведенный ниже код:
У этого конструктора — девять параметров, и это нарушение Sonar.
Класс может делать слишком много. Это должно быть исправлено путем внесения необходимых изменений в код. Разработчики берут @Requiredargsconstructor
для создания конструктора с требуемыми параметрами. Но когда они добавляют эту аннотацию, нарушение Sonar не подсвечивается.
Так не стоит справлять нарушение.
Кроме того, лучше не использовать какую-либо аннотацию Lombok, если она изменяет код. Если вы берете @Data
, @Getter
, @Setter
или @AllArgsConstructor
, то добавляете новый код в существующий без изменения написанного. Но если взять аннотацию @Utilityclass
, она изменит код. К примеру, вот утилитный класс ниже:
Аннотация @Utilityclass
преобразует существующий класс в утилитный, делая его окончательным и создавая приватный конструктор по умолчанию. Она также изменяет существующий метод и переменные, делая их статическими. Если вы проверите вышеуказанный класс, то не обнаружите никаких проблем. Нарушений Sonar также нет. Но при проверке скомпилированного кода вы увидите реальные проблемы:
Переменная value
является общедоступной статической конечной переменной, поэтому она должна соответствовать соглашению об именовании констант. Но когда мы проверяем исходный код, то видим, что это переменная экземпляра. Даже IDE не смогла идентифицировать ее как константу. Можно утверждать, что если знать, как работает аннотация @Utilityclass
, то понятно: переменная value
— константа. Такого рода модификации плохо влияют на читаемость. В первую очередь код должен быть удобочитаемым для человека. И на человеческий взгляд, это переменная экземпляра.
Еще одно, что стоит иметь в виду, — Lombok использует лазейку в спецификации компилятора Java. Если Java исправит это, мы, возможно, не сможем дальше пользоваться Lombok.
Заключение
Lombok — хороший и полезный инструмент. Но стоит использовать его разумно. Если не знать этого, то реальные преимущества Lombok останутся для нас недоступны.