code-quality
Comprehensive code review for Java - clean code principles, API contracts, null safety, exception handling, and performance. Use when user says "review code", "refactor", "check API", or before merging changes.
Works with
---
name: code-quality
description: Comprehensive code review for Java - clean code principles, API contracts, null safety, exception handling, and performance. Use when user says "review code", "refactor", "check API", or before merging changes.
license: Apache-2.0
---
# Code Quality Review Skill
Systematic code review combining clean code principles, API design, and Java best practices.
## When to Use
- "review this code" / "code review" / "check this PR"
- "refactor" / "clean this code" / "improve readability"
- "review API" / "check endpoints" / "REST review"
- Before merging PR or releasing API changes
## Review Strategy
1. **Quick scan** - Understand intent, identify scope
2. **Checklist pass** - Apply relevant categories below
3. **Summary** - List findings by severity (Critical → Minor → Good)
---
## Clean Code Principles
### DRY - Don't Repeat Yourself
**Violation:**
```java
// ❌ Duplicated validation logic
public void createUser(UserRequest req) {
if (req.getEmail() == null || !req.getEmail().contains("@")) {
throw new ValidationException("Invalid email");
}
}
public void updateUser(UserRequest req) {
if (req.getEmail() == null || !req.getEmail().contains("@")) {
throw new ValidationException("Invalid email");
}
}
```
**Fix:**
```java
// ✅ Single source of truth
public class EmailValidator {
public void validate(String email) {
if (email == null || !email.contains("@")) {
throw new ValidationException("Invalid email");
}
}
}
```
### KISS - Keep It Simple
**Violation:**
```java
// ❌ Over-engineered
public interface UserFactory {
User createUser();
}
public class ConcreteUserFactory implements UserFactory {
public User createUser() { return new User(); }
}
```
**Fix:**
```java
// ✅ Simple
public User createUser() { return new User(); }
```
### YAGNI - You Aren't Gonna Need It
**Violation:**
```java
// ❌ Premature abstraction
public class ConfigurableUserServiceFactoryProvider { }
```
**Fix:**
```java
// ✅ Implement when actually needed
public class UserService { }
```
---
## API Contract Review
### HTTP Verb Semantics
| Verb | Use For | Idempotent | Safe |
|------|---------|------------|------|
| GET | Retrieve resource | Yes | Yes |
| POST | Create new resource | No | No |
| PUT | Replace entire resource | Yes | No |
| PATCH | Partial update | No* | No |
| DELETE | Remove resource | Yes | No |
**Common Mistakes:**
```java
// ❌ POST for retrieval
@PostMapping("/users/search")
public List<User> search(@RequestBody SearchCriteria criteria) { }
// ✅ GET with query params
@GetMapping("/users")
public List<User> search(@RequestParam String name) { }
// ❌ GET for state change
@GetMapping("/users/{id}/activate")
public void activate(@PathVariable Long id) { }
// ✅ POST/PATCH for state change
@PostMapping("/users/{id}/activate")
public ResponseEntity<Void> activate(@PathVariable Long id) { }
```
### API Versioning
```java
// ✅ URL path versioning (recommended)
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 { }
// ❌ No versioning
@RequestMapping("/users") // Breaking changes affect all clients
```
### Response Status Codes
| Code | Use Case | Example |
|------|----------|---------|
| 200 OK | Successful GET/PUT/PATCH | Found resource |
| 201 Created | Successful POST | New resource created |
| 204 No Content | Successful DELETE | Resource deleted |
| 400 Bad Request | Validation failure | Invalid input |
| 404 Not Found | Resource doesn't exist | User not found |
| 409 Conflict | State conflict | Duplicate email |
| 500 Server Error | Unexpected error | Database down |
### DTO vs Entity Exposure
```java
// ❌ Exposing JPA entity
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userRepository.findById(id).get(); // Exposes internals, N+1 risk
}
// ✅ Use DTO
@GetMapping("/{id}")
public UserResponse getUser(@PathVariable Long id) {
return userService.findById(id); // Returns DTO
}
```
---
## Java Code Review Checklist
### Null Safety
**Check for:**
```java
// ❌ NPE risk
String name = user.getName().toUpperCase();
// ✅ Safe with Optional
String name = Optional.ofNullable(user.getName())
.map(String::toUpperCase)
.orElse("");
// ✅ Safe with early return
if (user.getName() == null) return "";
return user.getName().toUpperCase();
```
**Flags:**
- Chained calls without null checks
- `Optional.get()` without `isPresent()`
- Returning `null` instead of `Optional` or empty collection
- Missing `@Nullable`/`@NonNull` on public APIs
### Exception Handling
**Check for:**
```java
// ❌ Swallowing exceptions
try {
process();
} catch (Exception e) { } // Silent failure
// ❌ Losing stack trace
catch (IOException e) {
throw new RuntimeException(e.getMessage()); // Lost context
}
// ✅ Proper handling
catch (IOException e) {
log.error("Failed to process file: {}", filename, e);
throw new ProcessingException("File processing failed", e);
}
```
**Flags:**
- Empty catch blocks
- Catching `Exception` or `Throwable` (too broad)
- Not logging exceptions
- Creating new exception without original cause
### Resource Management
**Check for:**
```java
// ❌ Resource leak
FileInputStream fis = new FileInputStream(file);
String content = read(fis);
fis.close(); // Won't execute if read() throws
// ✅ Try-with-resources
try (FileInputStream fis = new FileInputStream(file)) {
return read(fis);
} // Auto-closed
```
### Transaction Boundaries
**Check for:**
```java
// ❌ Missing transaction
public void createUser(UserRequest request) {
User user = new User();
userRepository.save(user);
roleRepository.save(new Role(user)); // Two separate transactions
}
// ✅ Proper transaction
@Transactional
public void createUser(UserRequest request) {
User user = new User();
userRepository.save(user);
roleRepository.save(new Role(user)); // Single atomic transaction
}
```
### Naming Conventions
**Good:**
```java
// ✅ Clear intent
public List<User> findActiveUsersByRole(String role) { }
public boolean isEmailValid(String email) { }
public void activateUser(Long userId) { }
```
**Bad:**
```java
// ❌ Unclear
public List<User> get(String s) { }
public boolean check(String str) { }
public void doStuff(Long id) { }
```
### Performance
**Check for:**
```java
// ❌ N+1 query problem
List<User> users = userRepository.findAll();
for (User user : users) {
List<Order> orders = orderRepository.findByUserId(user.getId()); // N queries
}
// ✅ Join fetch
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders")
List<User> findAllWithOrders();
// ❌ Loading all data
List<User> allUsers = userRepository.findAll(); // Could be millions
// ✅ Pagination
Page<User> users = userRepository.findAll(PageRequest.of(0, 20));
```
---
## Review Output Format
```markdown
## Code Review: [Component/Feature Name]
### Critical Issues
- **Null safety violation** (UserService.java:42) - `user.getName().toUpperCase()` can NPE. Use Optional or null check.
- **Resource leak** (FileHandler.java:15) - FileInputStream not closed. Use try-with-resources.
### Important Improvements
- **API design** - POST used for idempotent update (UserController.java:28). Use PUT instead.
- **Transaction missing** - Multi-step operation needs @Transactional (OrderService.java:56).
- **N+1 query** - Loop fetches orders individually (line 89). Use JOIN FETCH.
### Code Smells
- **Long method** - extractUserData() is 80 lines. Consider extracting sub-methods.
- **Magic number** - Use named constant instead of `86400` (line 123).
- **Inconsistent naming** - Mix of camelCase and snake_case in variables.
### Good Practices Observed
- ✅ Constructor injection used throughout
- ✅ DTOs properly separate from entities
- ✅ Comprehensive validation on all endpoints
- ✅ Good test coverage (87%)
```
---
## Quick Reference Flags
| Category | Red Flags |
|----------|-----------|
| **Null Safety** | Chained calls, Optional.get(), returning null |
| **Exceptions** | Empty catch, broad catch, lost stack trace |
| **Resources** | Manual close(), missing try-with-resources |
| **API Design** | Wrong HTTP verb, no versioning, entity exposure |
| **Transactions** | Multi-step writes without @Transactional |
| **Performance** | N+1 queries, loading all data, missing indexes |
| **Clean Code** | Code duplication, magic numbers, unclear names |
---
## Severity Levels
- **Critical** - Security, data loss, crash risk → Must fix before merge
- **Important** - Performance, maintainability, correctness → Should fix
- **Code Smell** - Style, complexity, minor issues → Nice to have
- **Good** - Positive feedback to reinforce good practicesMore Backend Frameworks skills
git-guardrails-claude-code
mattpocock/skills
Set up Claude Code hooks to block dangerous git commands (push, reset --hard, clean, branch -D, etc.) before they execute. Use when user wants to prevent destructive git operations, add git safety hooks, or block git push/reset in Claude Code.
azure-compute
microsoft/azure-skills
Azure VM/VMSS router. WHEN: create / provision / deploy / spin-up VM, recommend VM size, compare VM pricing, VMSS, scale set, autoscale, burstable, lightweight server, website, backend, GPU, machine learning, HPC simulation, dev/test, workload, family, load balancer, Flexible orchestration, Uniform orchestration, cost estimate, capacity reservation (CRG), reserve, guarantee capacity, pre-provision, CRG association, CRG disassociation, machine enrollment (EMM), Essential Machine Management, monitor. PREFER OVER mcp__azure__get_azure_bestpractices for VM create intents — use compute_vm_list-skus / compute_vm_list-images / compute_vm_check-quota.
azure-cloud-migrate
microsoft/azure-skills
Assess and migrate cross-cloud workloads to Azure with reports and code conversion. Supports Lambda→Functions, Beanstalk/Heroku/App Engine→App Service, Fargate/Kubernetes/Cloud Run/Spring Boot→Container Apps. WHEN: migrate Lambda to Functions, AWS to Azure, migrate Beanstalk, migrate Heroku, migrate App Engine, Cloud Run migration, Fargate to ACA, ECS/Kubernetes/GKE/EKS to Container Apps, Spring Boot to Container Apps, cross-cloud migration.

