Spring Boot Best Practices for Developers

        Spring Boot is a widely used and very popular enterprise-level high-performance framework. Here are some best practices and some tips you can use to improve your Spring Boot application and make it more efficient. This post is going to be a bit long and it will take some time to read through it in its entirety.

correct packaging style

  • Proper packaging will help to easily understand the code and flow of the application.
  • You can structure your application with meaningful wrappers.
  • You can have all controllers in separate packages, services in separate packages, util classes in separate packages...etc. This style is very convenient in small microservices.
  • If you're dealing with a huge codebase, you can use a feature-based approach. You can decide according to your requirements.

        organized by type 

 

         organized by function

 Using the Spring Boot starter

  • This is a cool feature of Spring Boot.
  • We can use start dependencies very easily without adding individual dependencies one by one. These starter dependencies are already bundled with the required dependencies.
  • For example, if we add the spring-boot-starter-web dependency , by default it will be bundled with the jackson, spring-core, spring-mvc and spring-boot-starter-tomcat dependencies .
  • So we don't need to care about adding dependencies separately.
  • It also helps us avoid version mismatches.

use the correct version of dependencies

  • It is always recommended to use the latest stable GA release.
  • Sometimes it may vary due to Java version, server version, application type, etc.
  • Don't use different versions of the same package, always use <properties> to specify versions if there are multiple dependencies.

 Lombok 

  • As a Java developer, you've probably heard of Project Lombok .
  • Lombok is a Java library that reduces code and allows you to write clean code using its annotations.
  • For example, you might have lots of getter and setter lines in some classes like entities, request/response objects, dtos, etc.
  • But if you use Lombok, it's just one line and you can use @Data, @Getter or @Setter according to your requirement .
  • You can also use Lombok logger annotations. Recommend @Slf4j.

Using constructor injection with Lombok 

  • When we talk about dependency injection, there are two types.
  • One is " constructor injection " and the other is "  setter injection ". Besides that, you can also do " field injection " using the very popular @Autowired annotation .
  • But we strongly recommend using constructor injection over other types. Because it allows the application to initialize all required dependencies at initialization time.
  • This is very useful for unit testing.
  • Importantly, we can use Lombok's @RequiredArgsConstructor annotation to use constructor injection.

Logging with slf4j 

  • Logging is very important.
  • If your application breaks in production  , logging is the only way to find the root cause.
  • Therefore, careful consideration should be given before adding loggers, log message types, logger levels, and logger messages.
  • Do not use System.out.print()
  • It is recommended to use Slf4j with logback, the default logging framework in Spring Boot.
  • Always use slf4j { } and avoid string interpolation in logger messages. Because string interpolation consumes more memory.
  • You can  create loggers very easily using the Lombok @Slf4j annotation.
  • If you are in a microservices environment, you can use the ELK stack.

Only use controllers for routing 

  • Controllers are dedicated to routing.
  • It is stateless and singleton .
  • DispatcherServlet will check for @RequestMapping on the controller
  • The controller is the final destination of the request, and the request will be handed over to and handled by the service layer.
  • Business logic should not reside in controllers.

Use services to implement business logic

  • Complete business logic including validation, caching, etc.
  • The service communicates with the persistence layer and receives the results.
  • Services are also singletons.

 Avoid Null Pointer Exceptions

  • To avoid NullPointerException you can use Optional from java.util package .
  • You can also use an empty security library. For example: Apache Commons StringUtils
  • Call the equals() and equalsIgnoreCase() methods on known objects.
  • Use valueOf() instead of toString()
  • Use IDE-based @NotNull and @Nullable annotations.

Best Practices for Using the Collections Framework

  • Use the appropriate collection for your dataset.
  • Use forEach with Java 8 features and avoid legacy for loops.
  • Use interface types instead of implementations.
  • Use isEmpty() instead of size() for better readability.
  • Don't return null, you can return an empty collection.
  • If you are using objects as data to be stored in a hash-based collection, you should override the equals() and hashCode() methods.

 use pagination

  • This will improve the performance of the application.
  • If you use Spring Data JPA , the PagingAndSortingRepository makes working with pagination very easy and almost effortless.

use cache

  • Caching is another important factor when talking about application performance.
  • By default, Spring Boot provides caching via ConcurrentHashMap , you can achieve this via @EnableCaching annotation.
  • If you are not satisfied with the default cache, you can use Redis , Hazelcast or any other distributed cache implementation.
  • Both Redis and Hazelcast are memcaching approaches. You can also use a database cache implementation.

 Using custom exception handlers and global exception handling

  • This is very important when working with large enterprise applications.
  • In addition to general exceptions, we may also have scenarios to identify some specific error conditions.
  • Exception advisors can be created using @ControllerAdvice where we can create individual exceptions with meaningful details.
  • It will make it easier to identify and debug errors in the future.

 Use a custom response object

  • A custom response object can be used to return an object that contains some specific data and satisfies HTTP status codes, API codes, messages, etc.
  • We can use the builder design pattern to create custom response objects with custom properties.

Remove unnecessary code, variables, methods and classes. 

  • Unused variable declarations will take up some memory.
  • Remove unused methods, classes, etc. as it affects the performance of the application.
  • Try to avoid nested loops. You can use a map instead.

usage notes

  • Don't abuse annotations. Don't comment all code. Instead, you write descriptive code using meaningful words like class, function, method, variable, etc.
  • Remove comment code, misleading comments and story comments.
  • You can use comments to warn and explain something that is hard to understand at first glance.

Use meaningful words for classes, methods, functions, variables, and other attributes

  • It seems simple, but the impact is huge.
  • Always use correct meaningful and searchable naming conventions with correct capitalization.
  • Usually, we use nouns or phrases when declaring classes , variables and constants . For example: string firstName, const isValid
  • You can use verbs and phrases with adjectives to refer to functions and methods . For example: readFile(), sendData()
  • Avoid abbreviated variable names and names that are intended to be revealing . For example: int i; string getExUsr;
  • If you use it meaningfully, you can reduce the declaration comment lines. Since it has a meaningful name, new developers can easily understand it by reading the code.

 Use correct capitalization for declarations

  • There are many different cases like uppercase, lowercase, camelCase, PascalCase, snakeCase, SCREAMING_SNAKE_CASE, dashCase, etc.
  • But we need to identify which case is dedicated to which variable.
  • Usually, I follow,

Class —  PascalCase

Methods and Variables - CamelCase

Constant —  SCREAMING_SNAKE_CASE

Database related fields —snake_case

  • This is just an example. It may differ from the standards you follow at your company.

 Simpler

  • Always try to write simple, readable code.
  • The same simple logic can be implemented in different ways, but it's hard to understand if it's not readable or understandable.
  • Sometimes complex logic consumes more memory.
  • Try to use KISS , DRY and SOLID principles when writing code .

Use a common code formatting style 

  • Formatting styles vary by developer. A change in coding style is also considered a change and can make code merging very difficult.
  • To avoid this, teams can adopt a common coding format.

Guess you like

Origin blog.csdn.net/bashendixie5/article/details/132228023