Лучшие практики написания кода в Spring Boot

Spring Boot  —  это широко используемый и очень популярный высокопроизводительный фреймворк корпоративного уровня. Практики и советы, приведенные в этой статье, помогут улучшить приложение Spring Boot и сделать его более эффективным.

Применяйте надлежащий стиль упаковки

Надлежащая упаковка помогает легко понять код и поток приложения. Это позволяет успешно структурировать приложение.

Вы сможете распределить по отдельным пакетам все контроллеры, сервисы, утилитарные классы и т. д. Такой стиль очень удобен в небольших микросервисах.

При работе с огромной кодовой базой полезно использовать функционально-ориентированный подход. Вы можете принять решение в зависимости от требований проекта  —  на основе типов или на основе функций.

Используйте паттерны проектирования

Паттерны проектирования  —  безупречная практика. С проверенными шаблонами у вас не будет поводов для недовольства. Но вам необходимо определить место использования шаблонов.

Используйте стартеры Spring Boot

Стартеры (starters)  —  замечательная особенность Spring Boot. В этом фреймворке можно использовать зависимости стартеров, не добавляя отдельно одну за другой зависимости. Зависимости стартеров в Spring Boot предлагаются в комплекте с необходимыми зависимостями.

Например, если вы добавите зависимость spring-boot-starter-web, то по умолчанию она будет связана с зависимостями jackson, spring-core, spring-mvc и spring-boot-starter-tomcat. Поэтому вам не придется заботиться о добавлении зависимостей по отдельности. Кроме того, вы сможете избежать несоответствия версий.

Используйте соответствующие версии зависимостей

Рекомендуется всегда использовать новейшие стабильные GA-версии (GA, General availability  —  общедоступные). Иногда выбор версии зависимостей может определяться версией Java, версией сервера, типом приложения и т. д.

Не используйте разные версии одного и того же пакета. Всегда применяйте <properties> для указания версии, если есть несколько зависимостей.

Используйте Lombok

Будучи Java-разработчиком, вы наверняка слышали о проекте Lombok. Lombok  —  это Java-библиотека, которая позволяет сокращать код и делать его чище с помощью аннотаций.

Например, вы можете написать много строк кода для геттеров и сеттеров в некоторых классах (сущности, объекты запроса/ответа, DTO-объекты (DTO, Data Transfer Object  —  объект, передающий данные) и т. д.

Lombok позволит сократить длинный код до одной строки. Используйте @Data, @Getter и @Setter в соответствии с требованиями проекта.

Можно также воспользоваться аннотациями логгеров Lombok. Рекомендуется использовать @Slf4j.

Внедряйте зависимости через конструктор с помощью Lombok

Говоря о внедрении зависимостей, мы подразумеваем два типа. Один из них  —  “внедрение через конструктор” (“constructor injection”), другой  —  “внедрение через сеттер” (“setter injection”). Кроме того, вы можете использовать “внедрение через поле” (“field injection”) с помощью очень популярной аннотации @Autowired.

Тем не менее настоятельно рекомендуем использовать внедрение через конструктор. Это позволит приложению инициализировать все необходимые зависимости во время инициализации.

Внедрение через конструктор очень полезно для модульного тестирования.

Кроме того, можно воспользоваться аннотацией @RequiredArgsConstructor от Lombok для использования внедрения через конструктор.

Посмотрите этот пример контроллера для ознакомления.

Используйте логгинг в slf4j

Логгинг очень важен  —  это единственный способ выяснить первопричину проблем, возникающих во время работы приложения. Поэтому следует хорошо подумать, прежде чем добавлять логгеры (loggers), типы сообщений логгеров, уровни логгеров и сообщения логгеров.

Не используйте System.out.print().

Slf4j рекомендуется использовать вместе с logback, который является фреймворком логгирования по умолчанию в Spring Boot.

Всегда применяйте slf4j { } и избегайте использования интерполяции строк в сообщениях логгера. Интерполяция строк потребляет много памяти.

Ознакомьтесь с этим файлом, чтобы получить представление о реализации логгера.

Аннотация Lombok @Slf4j поможет легко создать логгер.

Работая в среде микросервисов, используйте стек ELK.

Применяйте контроллеры только для маршрутизации

Контроллеры занимаются маршрутизацией. Контроллер не имеет состояний и является синглтоном (существующим в приложении в одном экземпляре).

DispatcherServlet будет проверять @RequestMapping на контроллерах.

Контроллеры являются конечной целью запросов. Затем запросы передаются на сервисный уровень и там обрабатываются.

Бизнес-логика не должна находиться в контроллерах.

Используйте сервисы для бизнес-логики

Здесь находится вся бизнес-логика с проверками, кэшированием и т.д.

Сервисы взаимодействуют с уровнем сохранения и получают результаты. Они также являются синглтонами.

Избегайте NullPointerException

Избежать NullPointerException позволит Optional из пакета java.util.

Вы также можете использовать библиотеки с null-безопасностью, например, Apache Commons StringUtils.

Вызывайте методы equals() и equalsIgnoreCase() на известных объектах.

Применяйте valueOf() вместо toString().

Воспользуйтесь аннотациями @NotNull и @Nullable на основе IDE.

Применяйте лучшие практики для Java Collections Framework

Используйте подходящую коллекцию для своего набора данных.

Используйте forEach с возможностями Java 8 и избегайте применения устаревших циклов for.

Используйте тип interface (интерфейс) вместо типа implementation (имплементация).

Используйте isEmpty() вместо size() для лучшей читабельности.

Не стоит возвращать нулевые значения, но допустимо  —  пустую коллекцию.

Применяя объекты в качестве данных для хранения в хэш-коллекции, следует переопределить методы equals() и hashCode().

Используйте пагинацию

Это позволит повысить производительность приложения.

При использовании Spring Data JPA PagingAndSortingRepository позволяет применять пагинацию без особых усилий.

Используйте кэширование

Кэширование  —  еще один важный фактор производительности приложения. По умолчанию Spring Boot обеспечивает кэширование при содействии ConcurrentHashMap (вы можете добиться этого с помощью аннотации @EnableCaching).

Если вас не устраивает кэширование по умолчанию, используйте Redis, Hazelcast или любые другие реализации распределенного кэширования.

Redis и Hazelcast  —  это методы кэширования в оперативной памяти. Можно также использовать реализацию кэширования баз данных.

Используйте обработчик специальных исключений вместе с обработкой общих исключений

Это очень важно при работе с крупными приложениями корпоративного уровня.

Помимо общих исключений, могут быть некоторые сценарии для выявления специфических случаев ошибок.

С помощью @ControllerAdvice можно создать советника по исключениям. Мы можем создавать отдельные исключения с содержательными деталями.

Это значительно облегчит идентификацию и отладку ошибок в будущем.

Используйте пользовательский объект ответа

Пользовательский объект ответа используется для возврата объекта с определенными данными (требования могут включать в себя код состояния HTTP, код API, сообщение и т. д.).

Для создания пользовательского объекта ответа с предпочтительными атрибутами можно использовать паттерн проектирования builder.

Удаляйте ненужный код, переменные, методы и классы

Объявления неиспользуемых переменных будет занимать определенный объем памяти. Удаляйте неиспользуемые методы и классы, чтобы повысить производительность приложения.

Старайтесь избегать вложенных циклов. Вместо них используйте map.

Пишите разумные комментарии

Комментирование  —  хорошая практика, если только не злоупотреблять ею.

Не комментируйте все подряд. Создавайте описательный код, используя осмысленные слова для классов, функций, методов, переменных и т. д.

Удаляйте закомментированные фрагменты кода, вводящие в заблуждение комментарии и комментарии сюжетного типа.

Комментарии можно использовать для предупреждений и объяснения того, что трудно понять с первого взгляда.

Используйте осмысленные названия для классов, методов, функций, переменных и других атрибутов

Это кажется простой задачей, но имеет огромное значение. Всегда используйте удобные для понимания и поиска соглашения об именовании с соответствующим регистром.

Обычно при объявлении классов, переменных и констант используются существительные и короткие фразы. Например, String firstName, const isValid.

Для функций и методов можно использовать глаголы и короткие фразы с определениями. Например, readFile(), sendData().

Избегайте как сокращенных имен переменных, так и излишне развернутых именований. Например, int i; String getExUsr.

Осмысленный подход к именованию позволит сократить строки комментариев к объявлению. Если имена будут иметь смысл, другой разработчик сможет легко понять их, прочитав код.

Подбирайте соответствующий регистр для объявлений

Есть множество различных регистров, таких как UPPERCASE, lowercase, camelCase, PascalCase, snake_case, SCREAMING_SNAKE_CASE, kebab-case и т. д. Но вам нужно определиться с тем, какой регистр предназначен для какой переменной.

Обычно я придерживаюсь следующих регистров: для классов  —  PascalCase, для методов и переменных  —  camelCase, для констант  —  SCREAMING_SNAKE_CASE, для связанных с БД полей  —  snake_case.

Стремитесь к упрощению

Всегда старайтесь писать простой, хорошо читаемый код. Одна и та же простая логика может быть реализована разными способами, но ее трудно выявить, если код не читабелен или не понятен.

Иногда сложная логика потребляет больше памяти.

Старайтесь при написании кода следовать принципам: KISS (Не усложняй), DRY (Не повторяйся) и SOLID (Соблюдай принципы единственной ответственности, открытости-закрытости, подстановки Барбары Лисков, разделения интерфейсов и инверсии зависимостей).

Используйте единый стиль форматирования кода

Стили форматирования кода варьируются от разработчика к разработчику. Изменение стиля написания в каком-то фрагменте кода может сильно затруднить объединение кода всего проекта. Чтобы избежать этого, команда должна выработать единый формат написания кода.

Используйте SonarLint

Это IDE-расширение пригодится для выявления мелких багов и внедрения лучших практик, поскольку помогает избежать ненужных ошибок и проблем с качеством кода.

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

Читайте нас в TelegramVK и Дзен


Перевод статьи Kishore Karnatakapu: How to follow coding standards in Spring Boot

Предыдущая статьяСетевое программирование в Go
Следующая статьяНаше прохождение космического CTF от RUVDS и Positive Technologies