Написание шаблонного кода или кода, который на самом деле не нужен, отнимает много времени. У языка Java есть большое сообщество, создавшее множество библиотек, которые помогут вам повысить производительность, избавив от необходимости писать шаблонный код или предоставляя утилиты для решения распространенных проблем. В этой статье мы рассмотрим некоторые из таких библиотек.
1. Проект Lombok
Устали от файлов, которые наполнены только шаблонными методами, такими как геттеры, сеттеры, конструкторы, переопределенные методы equals
и т.д.? Что ж, тогда ваш выбор — Lombok. Большинство IDE могут автоматически генерировать методы-геттеры и методы-сеттеры всего одним нажатием кнопки, но разница в том, что IDE генерирует эти методы в самом файле .java
, а Lombok генерирует все методы непосредственно в файле .class
. А кроме того, Lombok помогает нам удалять и другой шаблонный код. Лучше всего это понятно на нескольких примерах.
public class StudentServiceWithoutLombok implements IStudentService{
private static final Logger log = Logger.getLogger(StudentServiceWithLombok.class);
@Override
public void method1() {
log.info("In method1 ");
}}
Выше приведен код без Lombok, и теперь напишем тот же код, уже задействовав эту библиотеку.
@Log4j
public class StudentServiceWithLombok implements IStudentService{
@Override
public void method1() {
log.info("In method1 ");
}}
Теперь вы видите, что в файле не нужно инициализировать переменную логгера, и это всего лишь минус одна строка, но в больших проектах с тысячами файлов вам не придется писать одну и ту же строку снова и снова. Позвольте привести вам еще один пример. Ниже показан еще один класс без Lombok.
public class Student{
private Integer rollNumber;
private String name;
public Student(Integer rollNumber, String name)
{
super();
this.rollNumber = rollNumber;
this.name = name;
}
public Integer getRollNumber()
{
return rollNumber;
}
public void setRollNumber(Integer rollNumber)
{
this.rollNumber = rollNumber;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
public String toString()
{
return "Student ["
+ "rollNumber=" + rollNumber
+ ", name=" + name + ", "
+ "]";
}
}
Теперь, если мне придется написать тот же код с Lombok, это будет выглядеть так:
@AllArgsConstructor
@Data
public class Student{
private Integer rollNumber;
private String name;
}
Пример с Lombok не содержит шаблонного кода, и его гораздо легче читать.
Lombok удаляет большую часть вашего шаблонного кода и дает сосредоточиться на бизнес-логике, к тому же ваш код будет выглядеть аккуратнее. В Lombok есть гораздо больше, чем упомянуто в этой статье — вы можете познакомиться со всеми интересными функциями проекта Lombok на официальном сайте.
2.MapStruct
Применяете многоуровневую архитектуру в своем Java-проекте? Если да, то вам определенно следует подумать о MapStruct. При многоуровневой архитектуре уровни приложения слабо связаны, поэтому будут моменты, когда придется сопоставлять объект, находящийся на одном уровне, с объектом другого уровня. Распространенный пример — сопоставление сущностей, находящихся на уровне сохранения данных, с DTO на уровне приложения. Сопоставление простого POJO с другим POJO может потребовать большого количества шаблонного кода. Рассмотрим ниже два класса: класс сущности Student
и его DTO, которые нужно сопоставить.
@Entity
@Data
public class Student{
private Integer rollNumber;
private String name;
}
@Data
public class StudentDTO{
private Integer rollNumber;
private String name;
}
Если вам нужно сопоставить два класса, то, вероятно, вы напишете класс-конвертер, содержащий функцию, которая будет принимать Student
в качестве входных данных и возвращать StudentDTO
в качестве выходных данных, примерно как показано ниже:
public class StudenttoStudentDTOconvertor
{
public StudentDTO convert(Student student)
{
StudentDTO studentDTO = new StudenDTO();
studentDTO.setName(student.getName);
studentDTO.setRollNo(student.getRollNo());
return studentDTO;
}
Student
— простой класс всего с двумя полями, и видно, что нам нужно написать четыре строки кода. Если в этом классе будет больше полей, количество строк в коде конвертера также увеличится. Чтобы избежать написания этого простого шаблонного кода, есть MapStruct, который автоматически сгенерирует код. Теперь перепишем код класса конвертера с помощью MapStruct.
@Mapper
public interface StudenttoStudentDTOMapper
{
StudentDTO map(Student student);
}
Вам действительно не придется реализовывать этот интерфейс, MapStruct сделает это автоматически. В любом случае, если в будущем вы решите добавить еще одно новое поле, в класс сущностей, то вы можете добавить то же поле в DTO, и вам не придется вносить какие-либо изменения в класс-сопоставитель. Чтобы узнать больше о других интересных функциях MapStruct, пожалуйста, посетите их официальный сайт.
3.Guava
Я не могу объяснить Guava лучше, чем их собственный репозиторий на GitHub:
Guava — это набор основных библиотек Java от Google, который включает новые типы коллекций (такие как multimap и multiset), неизменяемые коллекции, библиотеку графов и утилиты для параллелизма, ввода-вывода, хеширования, кэширования, примитивов, строк и многого другого! Она широко используется в большинстве Java-проектов Google, а также многими другими компаниями.
В Guava есть утилиты, которые могут помочь решать не только простые задачи на Java, но и очень сложные. Разберемся на примере:
public void checkAge(int age) {
if(age<0)
{
throw new IllegalArgumentException(“age id invalid”);
}
}
Ту же программу с библиотекой Guava можно написать так:
public void checkAge(int age) {
Preconditions.checkArgument(age > 0, “Invalid Age”);
}
Обе программы выполняют одну и ту же работу, но код, использующий библиотеку Guava, более чистый. Может показаться, что это не так уж много, но есть и гораздо больше. Возьмем еще один пример:
public void example() {
// Инициализируем Guava LinkedHashMap Collection
Map<String, String> myMap = Maps.newLinkedHashMap();
myMap.put(“name”, “abc”);
myMap.put(“rollno”, “123”);
String delimiter = “&”;
String separator = “=”;
String result = Joiner.on(delimiter).withKeyValueSeperator(separator).join(myMap);
String expected = “name=abc&rollno=123”;
assertThat(result, expected);
}
Из приведенной выше программы видно, как легко с помощью Guava преобразовать карту в строку, и кроме того, если у вас возникли какие-либо проблемы в Java, будь то связанные с кэшированием, параллелизмом или любой другой областью, в большинстве случаев вы найдете решение в Guava. Чтобы узнать больше об этой библиотеке, не забудьте изучить их репозиторий на Github.
4. Feign
Если вы работаете Java-разработчиком, то определенно сталкивались с ситуациями, когда вам приходилось вызывать какой-либо REST API. Существует множество HTTP-клиентов, таких как OkHttpClient, которые можно использовать для вызова REST API, но обычно для них требуется много кода, который совершенно не соответствует потребностям бизнеса, и если вы вызываете несколько API, ваш код также будет дублироваться. Помимо клиентских библиотек HTTP, также есть библиотеки-оболочки, такие как RestTemplate, что немного облегчает жизнь. Пример кода, написанного с помощью OkHttpClient, будет выглядеть примерно так:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("https://127.0.0.1/posts/1")
.build();
Call call = okHttpClient.newCall(request);
try (Response response = call.execute();
ResponseBody body = response.body()) {
String string = body.string();
System.out.println(string);
} catch (IOException e) {
throw new RuntimeException(e);
}
Обратите внимание на необходимость добавлять обработку исключений. Также необходимо преобразовать ответ в объекты, чтобы его можно было использовать. Вам не кажется, что здесь слишком много кода для вызова простого REST API? Посмотрим, как будет выглядеть код с RestTemplate.
final String uri = "https://127.0.0.1/posts/1"
RestTemplate restTemplate = new RestTemplate();
PostDTO result = restTemplate.getForObject(uri,PostDTO.class);
Что ж, в RestTemplate все очень просто, и ваш ответ также преобразуется в объект, который используется в дальнейшем. Но все же, если мы вызываем несколько REST API, то в каждом из них нужно получить URL-адрес из свойств и вызвать API программно, и я даже не упомянул, что нам по-прежнему нужно обрабатывать ошибки. Есть два способа обработки ошибок. Первый — просто написать try-catch
, но тогда для каждого вызова должен быть написан одинаковый код. Другой вариант — обработчик исключений, но в обоих случаях нужно написать намного больше кода. Теперь посмотрим, как вызвать REST API с помощью Feign:
@FeignClient(name="content-service", url="127.0.0.1")
public interface ContentService {
@RequestLine("GET posts/{postNumber}")
String getDocumentByType(@Param("contentType") String postNumber);
}
Feign автоматически сгенерирует код для вызова REST API, и нам, разработчикам, не нужно будет ни о чем беспокоиться. Если необходимо добавить больше API, можно добавить методы и не переписывать код. У Feign гораздо больше функций — например, мы можем легко изменить URL-адрес, изменив конфигурацию, и если вы хотите повторить вызов какого-либо API в случае конкретной ошибки, Feign легко поможет вам это сделать. Feign также облегчает тестирование кода. Ознакомьтесь с более интересными функциями Feign в их репозитории GitHub.
5. Hibernate
Ненавидите писать SQL-запросы? Забываете закрыть соединение с базой данных после выполнения запроса? Тогда эта библиотека как раз для вас. Когда вы пытаетесь получить доступ к базе данных, задействовано много шаблонного кода: нужно открыть соединение, выполнить запрос, преобразовать набор результатов в сущности и закрыть соединение, и, кроме того, вам также необходимо писать эффективные запросы. Воспользовавшись Hibernate, вам не придется беспокоиться ни о чем из вышеперечисленного.
Вывод
В мире программирования всем хочется свести к минимуму шаблонный код у себя в приложении, а также не хочется снова изобретать велосипед, потому что по мере того, как вы пишете все больше и больше кода, возникает необходимость создавать тестовые случаи для проверки каждой отдельной строки, и всегда есть вероятность, что возникнет какая-то ошибка. В Java существует множество библиотек, которые помогают избавиться от шаблонного кода, а некоторые библиотеки предоставляют отличные готовые утилиты, так что изобретение велосипеда точно вам не грозит.
Читайте также:
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Abhishek Kapoor: Java libraries to increase your productivity