Code review in Java: what to check and how to give feedback
Code review is one of the most effective tools for improving software product quality and team professional growth. However, when it comes to Java, many developers (especially juniors) either are afraid to submit their code for review or don't know what to pay attention to when reviewing someone else's code. In this article, we will break down exactly what needs to be checked in Java code and how to formulate comments so as not to offend a colleague, but to help them become better.
1. What to check in Java code: technical checklist
The first thing that comes to mind is syntax and logic. But professional review goes far beyond these boundaries. Here are the key aspects worth checking in every pull request.
1.1. Architecture and design
Look at how well the new change fits into the existing architecture. Does it violate SOLID principles? For example, if you see a class that does too much (God Object), this is a reason to suggest splitting it.
- Single Responsibility Principle (SRP): Each class should have one reason to change.
- Dependency Inversion Principle (DIP): Depend on abstractions, not on concrete implementations.
- Patterns: The use of singletons, factories, or strategies should be justified, not applied "just in case".
// Bad: class knows about both logic and persistencepublic class UserService { public void registerUser(String name) { // validation // save to DB // send email }}
// Good: separation of concernspublic class UserService { private final UserRepository repository; private final EmailService emailService;
public void registerUser(String name) { User user = new User(name); repository.save(user); emailService.sendWelcome(user); }}1.2. Performance and memory management
Java is a language with automatic memory management, but this doesn't mean you can forget about optimization. Check:
- String concatenation in a loop: Use
StringBuilderorStringBuffer. - Unnecessary objects: Creating temporary objects in hot loops.
- Collections: Choosing the correct implementation (e.g.,
ArrayListvsLinkedList). - NullPointerException: Use
Optionalor null checks.
// Bad: millions of strings in memoryString result = "";for (String s : list) { result += s;}
// Good: StringBuilderStringBuilder sb = new StringBuilder();for (String s : list) { sb.append(s);}String result = sb.toString();1.3. Error and exception handling
An error in Java is not always a bug. Sometimes it's incorrect use of exceptions. Pay attention to:
- Empty catch blocks:
catch (Exception e) {}is evil. The error should at least be logged. - Too general exceptions: Catching
ExceptionorThrowableis bad practice. - Resource streams: Use try-with-resources for automatic closing.
// Bad: swallowing the exceptiontry { // some code} catch (Exception e) { // do nothing}
// Good: log and rethrowtry { // some code} catch (SQLException e) { log.error("Error working with the database", e); throw new ServiceException("Failed to perform the operation", e);}1.4. Tests and coverage
Code review without checking tests is a "half-baked" review. Make sure that: