| name | architecture-review |
| description | Analyze Java project architecture at macro level - package structure, module boundaries, dependency direction, and layering. Use when user asks "review architecture", "check structure", "package organization", or when evaluating if a codebase follows clean architecture principles. |
Architecture Review Skill
Analyze project structure at the macro level - packages, modules, layers, and boundaries.
When to Use
- User asks "review the architecture" / "check project structure"
- Evaluating package organization
- Checking dependency direction between layers
- Identifying architectural violations
- Assessing clean/hexagonal architecture compliance
Quick Reference: Architecture Smells
| Smell | Symptom | Impact |
|---|
| Package-by-layer bloat | service/ with 50+ classes | Hard to find related code |
| Domain ā Infra dependency | Entity imports @Repository | Core logic tied to framework |
| Circular dependencies | A ā B ā C ā A | Untestable, fragile |
| God package | util/ or common/ growing | Dump for misplaced code |
| Leaky abstractions | Controller knows SQL | Layer boundaries violated |
Package Organization Strategies
Package-by-Layer (Traditional)
com.example.app/
āāā controller/
ā āāā UserController.java
ā āāā OrderController.java
ā āāā ProductController.java
āāā service/
ā āāā UserService.java
ā āāā OrderService.java
ā āāā ProductService.java
āāā repository/
ā āāā UserRepository.java
ā āāā OrderRepository.java
ā āāā ProductRepository.java
āāā model/
āāā User.java
āāā Order.java
āāā Product.java
Pros: Familiar, simple for small projects
Cons: Scatters related code, doesn't scale, hard to extract modules
Package-by-Feature (Recommended)
com.example.app/
āāā user/
ā āāā UserController.java
ā āāā UserService.java
ā āāā UserRepository.java
ā āāā User.java
āāā order/
ā āāā OrderController.java
ā āāā OrderService.java
ā āāā OrderRepository.java
ā āāā Order.java
āāā product/
āāā ProductController.java
āāā ProductService.java
āāā ProductRepository.java
āāā Product.java
Pros: Related code together, easy to extract, clear boundaries
Cons: May need shared kernel for cross-cutting concerns
Hexagonal/Clean Architecture
com.example.app/
āāā domain/ # Pure business logic (no framework imports)
ā āāā model/
ā ā āāā User.java
ā āāā port/
ā ā āāā in/ # Use cases (driven)
ā ā ā āāā CreateUserUseCase.java
ā ā āāā out/ # Repositories (driving)
ā ā āāā UserRepository.java
ā āāā service/
ā āāā UserDomainService.java
āāā application/ # Use case implementations
ā āāā CreateUserService.java
āāā adapter/
ā āāā in/
ā ā āāā web/
ā ā āāā UserController.java
ā āāā out/
ā āāā persistence/
ā āāā UserJpaRepository.java
ā āāā UserEntity.java
āāā config/
āāā BeanConfiguration.java
Key rule: Dependencies point inward (adapters ā application ā domain)
Dependency Direction Rules
The Golden Rule
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Frameworks ā ā Outer (volatile)
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā Adapters (Web, DB) ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā Application Services ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā Domain (Core Logic) ā ā Inner (stable)
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Dependencies MUST point inward only.
Inner layers MUST NOT know about outer layers.
Violations to Flag
package com.example.domain.model;
import org.springframework.data.jpa.repository.JpaRepository;
import javax.persistence.Entity;
@Entity
public class User {
}
package com.example.domain.service;
import com.example.adapter.out.persistence.UserJpaRepository;
package com.example.domain.port.out;
public interface UserRepository {
User findById(UserId id);
void save(User user);
}
Architecture Review Checklist
1. Package Structure
2. Dependency Direction
3. Layer Boundaries
4. Module Boundaries
5. Scalability Indicators
Common Anti-Patterns
1. The Big Ball of Mud
src/main/java/com/example/
āāā app/
āāā User.java
āāā UserController.java
āāā UserService.java
āāā UserRepository.java
āāā Order.java
āāā OrderController.java
āāā ... (100+ files in one package)
Fix: Introduce package structure (start with by-feature)
2. The Util Dumping Ground
util/
āāā StringUtils.java
āāā DateUtils.java
āāā ValidationUtils.java
āāā SecurityUtils.java
āāā EmailUtils.java # Should be in notification module
āāā OrderCalculator.java # Should be in order domain
āāā UserHelper.java # Should be in user domain
Fix: Move domain logic to appropriate modules, keep only truly generic utils
3. Anemic Domain Model
public class Order {
private Long id;
private List<OrderLine> lines;
private BigDecimal total;
}
public class OrderService {
public void addLine(Order order, Product product, int qty) { ... }
public void calculateTotal(Order order) { ... }
public void applyDiscount(Order order, Discount discount) { ... }
}
Fix: Move behavior to domain objects (rich domain model)
4. Framework Coupling in Domain
package com.example.domain;
@Entity
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
@Id @GeneratedValue
private Long id;
@NotBlank
private String email;
}
Fix: Separate domain model from persistence/API models
Analysis Commands
When reviewing architecture, examine:
find src/main/java -type d | head -30
find src/main/java -name "*.java" | xargs dirname | sort | uniq -c | sort -rn | head -10
grep -r "import org.springframework" src/main/java/*/domain/ 2>/dev/null
grep -r "import javax.persistence" src/main/java/*/domain/ 2>/dev/null
Recommendations Format
When reporting findings:
## Architecture Review: [Project Name]
### Structure Assessment
- **Organization**: Package-by-layer / Package-by-feature / Hexagonal
- **Clarity**: Clear / Mixed / Unclear
### Findings
| Severity | Issue | Location | Recommendation |
|----------|-------|----------|----------------|
| High | Domain imports Spring | `domain/model/User.java` | Extract pure domain model |
| Medium | God package | `util/` (23 classes) | Distribute to feature modules |
| Low | Inconsistent naming | `service/` vs `services/` | Standardize to `service/` |
### Dependency Analysis
[Describe dependency flow, violations found]
### Recommendations
1. [Highest priority fix]
2. [Second priority]
3. [Nice to have]
Token Optimization
For large codebases:
- Start with
find to understand structure
- Check only domain package for framework imports
- Sample 2-3 features for pattern analysis
- Don't read every file - look for patterns