architecture-review
3
总安装量
3
周安装量
#57161
全站排名
安装命令
npx skills add https://github.com/decebals/claude-code-java --skill architecture-review
Agent 安装分布
qoder
3
gemini-cli
3
claude-code
3
github-copilot
3
roo
3
codex
3
Skill 文档
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
// â Domain depends on infrastructure
package com.example.domain.model;
import org.springframework.data.jpa.repository.JpaRepository; // Framework leak!
import javax.persistence.Entity; // JPA in domain!
@Entity
public class User {
// Domain polluted with persistence concerns
}
// â Domain depends on adapter
package com.example.domain.service;
import com.example.adapter.out.persistence.UserJpaRepository; // Wrong direction!
// â
Domain defines port, adapter implements
package com.example.domain.port.out;
public interface UserRepository { // Pure interface, no JPA
User findById(UserId id);
void save(User user);
}
Architecture Review Checklist
1. Package Structure
- Clear organization strategy (by-layer, by-feature, or hexagonal)
- Consistent naming across modules
- No
util/orcommon/packages growing unbounded - Feature packages are cohesive (related code together)
2. Dependency Direction
- Domain has ZERO framework imports (Spring, JPA, Jackson)
- Adapters depend on domain, not vice versa
- No circular dependencies between packages
- Clear dependency hierarchy
3. Layer Boundaries
- Controllers don’t contain business logic
- Services don’t know about HTTP (no HttpServletRequest)
- Repositories don’t leak into controllers
- DTOs at boundaries, domain objects inside
4. Module Boundaries
- Each module has clear public API
- Internal classes are package-private
- Cross-module communication through interfaces
- No “reaching across” modules for internals
5. Scalability Indicators
- Could extract a feature to separate service? (microservice-ready)
- Are boundaries enforced or just conventional?
- Does adding a feature require touching many packages?
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
// Domain object is just data
public class Order {
private Long id;
private List<OrderLine> lines;
private BigDecimal total;
// Only getters/setters, no behavior
}
// All logic in "service"
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 // JPA
@Data // Lombok
@JsonIgnoreProperties(ignoreUnknown = true) // Jackson
public class User {
@Id @GeneratedValue
private Long id;
@NotBlank // Validation
private String email;
}
Fix: Separate domain model from persistence/API models
Analysis Commands
When reviewing architecture, examine:
# Package structure overview
find src/main/java -type d | head -30
# Largest packages (potential god packages)
find src/main/java -name "*.java" | xargs dirname | sort | uniq -c | sort -rn | head -10
# Check for framework imports in domain
grep -r "import org.springframework" src/main/java/*/domain/ 2>/dev/null
grep -r "import javax.persistence" src/main/java/*/domain/ 2>/dev/null
# Find circular dependencies (look for bidirectional imports)
# Check if package A imports from B and B imports from A
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
findto understand structure - Check only domain package for framework imports
- Sample 2-3 features for pattern analysis
- Don’t read every file – look for patterns