Loading...
Loading...
Analyzes Java code against industry best practices and evaluates design principles including SOLID, exception handling, thread safety, and resource management. Reviews naming conventions, Stream API usage, Optional patterns, and general code quality. Use when reviewing Java files, checking code quality, evaluating exception handling, or auditing resource management.
npx skill4agent add dawiddutoit/custom-claude java-best-practices-code-review# Review a single file
Review src/main/java/com/example/UserService.java
# Review all Java files in a package
Review all Java files in src/main/java/com/example/service/**/*.java # All Java files
src/main/java/**/*Service.java # All service classespublic class UserService {
private UserRepository userRepository = new UserRepository();
public User getUser(String id) {
User user = userRepository.findById(id);
if (user == null) {
return null;
}
return user;
}
}CRITICAL Issues:
- Line 2: Dependency Inversion violation - direct instantiation of UserRepository
Fix: Inject UserRepository via constructor
HIGH Issues:
- Line 7: Returns null instead of Optional<User>
Fix: Return Optional.ofNullable(user)
MEDIUM Issues:
- Class lacks @Service annotation (assuming Spring)
- No logging for diagnostic purposes
Recommended Refactoring:
```java
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private static final Logger log = LoggerFactory.getLogger(UserService.class);
public Optional<User> getUser(String id) {
log.debug("Fetching user with id: {}", id);
return Optional.ofNullable(userRepository.findById(id));
}
}
### Example 2: Review Controller with Multiple Issues
**Input:**
```java
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable String id) {
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db", "root", "password");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE id = " + id);
if (rs.next()) {
return new User(rs.getString("name"), rs.getString("email"));
}
} catch (Exception e) {
// ignore
}
return null;
}
}CRITICAL Issues:
1. Line 7: SQL Injection vulnerability - concatenating user input into query
Fix: Use PreparedStatement with parameters
2. Line 5: Hardcoded database credentials in code
Fix: Externalize to application.properties and use Spring's DataSource
3. Lines 5-10: Resource leak - Connection, Statement, ResultSet not closed
Fix: Use try-with-resources or Spring JdbcTemplate
4. Line 11-13: Empty catch block silently swallows exceptions
Fix: Log exception and throw appropriate response exception
HIGH Issues:
5. Architecture violation: Controller directly accessing database
Fix: Use Service layer and Repository pattern
6. Line 14: Returns null instead of proper HTTP 404
Fix: Throw ResponseStatusException or return ResponseEntity
MEDIUM Issues:
7. Missing @RestController annotation
8. No input validation on id parameter
9. No API documentation (@Operation, @ApiResponse)
Recommended Architecture:
```java
@RestController
@RequiredArgsConstructor
@Validated
public class UserController {
private final UserService userService;
@GetMapping("/users/{id}")
@Operation(summary = "Get user by ID")
public ResponseEntity<User> getUser(
@PathVariable @NotBlank String id) {
return userService.getUser(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
}
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
public Optional<User> getUser(String id) {
return userRepository.findById(id);
}
}
@Repository
public interface UserRepository extends JpaRepository<User, String> {
}
### Example 3: Review Stream API Usage
**Input:**
```java
List<String> activeUserNames = new ArrayList<>();
for (User user : users) {
if (user.isActive()) {
activeUserNames.add(user.getName());
}
}
Collections.sort(activeUserNames);MEDIUM Issues:
- Lines 1-6: Imperative loop should use Stream API for clarity
- Line 7: Mutating list instead of using sorted stream
Recommended Refactoring:
```java
List<String> activeUserNames = users.stream()
.filter(User::isActive)
.map(User::getName)
.sorted()
.toList();
## Requirements
- Java 8+ knowledge for Stream API, Optional, lambda expressions
- Java 11+ awareness for var, String methods, Collection.toArray()
- Java 14+ familiarity with records, switch expressions, text blocks
- Java 17+ understanding of sealed classes, pattern matching
- Understanding of SOLID principles and design patterns
- Familiarity with Spring Framework conventions (if reviewing Spring code)
- Knowledge of common security vulnerabilities (OWASP Top 10)
## Review Checklist
Use this checklist to ensure comprehensive coverage:
**Design & Architecture:**
- [ ] SOLID principles followed
- [ ] Proper layer separation (Controller/Service/Repository)
- [ ] Dependency injection used correctly
- [ ] Interfaces used for abstraction
- [ ] Design patterns applied appropriately
**Code Quality:**
- [ ] Methods are focused and under 50 lines
- [ ] No code duplication (DRY)
- [ ] Clear, descriptive naming
- [ ] No magic numbers or strings
- [ ] Proper visibility modifiers (private, protected, public)
**Error Handling:**
- [ ] Appropriate exception types used
- [ ] No empty catch blocks
- [ ] Meaningful error messages
- [ ] Exception chaining preserved
- [ ] Resources cleaned up in finally or try-with-resources
**Modern Java:**
- [ ] Stream API used where appropriate
- [ ] Optional used instead of null returns
- [ ] Records used for DTOs (Java 14+)
- [ ] Switch expressions used (Java 14+)
- [ ] Text blocks for multi-line strings (Java 15+)
**Thread Safety:**
- [ ] Shared mutable state identified
- [ ] Proper synchronization if needed
- [ ] Immutable objects preferred
- [ ] Thread-safe collections used
**Security:**
- [ ] No hardcoded credentials
- [ ] Input validation present
- [ ] SQL injection prevention (PreparedStatement)
- [ ] No path traversal vulnerabilities
- [ ] Sensitive data not logged
**Performance:**
- [ ] No premature optimization
- [ ] Efficient algorithms used
- [ ] Proper use of collections
- [ ] Stream operations optimized
- [ ] Database N+1 queries avoided
## Output Format
Always structure review output as:
```markdown
# Java Code Review: [ClassName or Package]
## Summary
- Files reviewed: X
- Critical issues: X
- High priority issues: X
- Medium priority issues: X
- Low priority issues: X
## Critical Issues (Fix Immediately)
[List with file:line, description, fix]
## High Priority Issues (Fix Soon)
[List with file:line, description, fix]
## Medium Priority Issues (Improve When Possible)
[List with file:line, description, fix]
## Low Priority Issues (Nice to Have)
[List with file:line, description, fix]
## Positive Findings
[Call out well-written code and good practices]
## Overall Assessment
[Summary paragraph with key recommendations]