Написание шаблонного кода или кода, который на самом деле не нужен, отнимает много времени. У языка 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 существует множество библиотек, которые помогают избавиться от шаблонного кода, а некоторые библиотеки предоставляют отличные готовые утилиты, так что изобретение велосипеда точно вам не грозит.

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Abhishek Kapoor: Java libraries to increase your productivity

Предыдущая статья7 наиболее полезных расширений VS Code, представленных в 2021 году
Следующая статьяПроектирование базы кода API GraphQL в Node.js