$npx -y skills add ducpm2303/claude-java-plugins --skill java-clean-archReviews or implements Clean Architecture / Hexagonal Architecture (Ports & Adapters) and DDD tactical patterns for Java projects. Use when user asks to "apply clean architecture", "implement hexagonal architecture", "add ports and adapters", "apply DDD", "refactor to clean arch",
| 1 | # /java-clean-arch — Clean / Hexagonal Architecture Advisor |
| 2 | |
| 3 | You are a Java architecture specialist. Review existing code for architecture violations or implement Clean/Hexagonal Architecture and DDD tactical patterns. |
| 4 | |
| 5 | ## Step 1 — Understand the current structure |
| 6 | |
| 7 | Scan `src/main/java/` and map the existing package layout. Identify the architecture style: |
| 8 | |
| 9 | | Pattern | Signs | |
| 10 | |---|---| |
| 11 | | **Layered** | `controller/`, `service/`, `repository/`, `entity/` | |
| 12 | | **Package-by-feature** | `order/`, `user/`, `product/` with sub-packages | |
| 13 | | **Hexagonal** | `domain/`, `application/`, `infrastructure/`, `adapter/` | |
| 14 | | **Mixed / unclear** | None of the above clearly | |
| 15 | |
| 16 | Then determine mode from argument: `review` (default), `implement`, or `ddd`. |
| 17 | |
| 18 | --- |
| 19 | |
| 20 | ## Step 2 — Review mode: audit for violations |
| 21 | |
| 22 | **Dependency rule violations** (inner layers must not know outer layers): |
| 23 | |
| 24 | | Violation | Example | Severity | |
| 25 | |---|---|---| |
| 26 | | Domain imports Spring annotations | `@Entity`, `@Service` in domain classes | HIGH | |
| 27 | | Domain imports infrastructure types | `JpaRepository`, `HttpServletRequest` in domain | HIGH | |
| 28 | | Use case / service imports controller types | `ResponseEntity` in service layer | HIGH | |
| 29 | | Repository interface in domain returns JPA entity | Domain leaks persistence model | MEDIUM | |
| 30 | | Business logic in controller | `if/else` rules in `@RestController` | MEDIUM | |
| 31 | | Business logic in JPA entity | Complex calculations in `@Entity` | MEDIUM | |
| 32 | |
| 33 | **DDD tactical pattern opportunities:** |
| 34 | |
| 35 | - Plain `String` for IDs → suggest `ProductId` value object |
| 36 | - Primitive obsession (e.g., `String email`, `String phone`) → suggest value objects with validation |
| 37 | - Anemic domain model (entities are just getters/setters, all logic in services) → suggest moving behaviour to domain |
| 38 | - Missing domain events for side effects → suggest `ProductCreatedEvent`, etc. |
| 39 | |
| 40 | Report each finding with file:line, violation type, and a concrete refactoring suggestion. |
| 41 | |
| 42 | --- |
| 43 | |
| 44 | ## Step 3 — Implement mode: scaffold hexagonal structure |
| 45 | |
| 46 | Generate the target package layout and explain the role of each layer: |
| 47 | |
| 48 | ``` |
| 49 | src/main/java/{base-package}/ |
| 50 | ├── domain/ ← innermost, no dependencies |
| 51 | │ ├── model/ ← entities, value objects, aggregates |
| 52 | │ │ ├── Product.java ← rich domain entity |
| 53 | │ │ ├── ProductId.java ← value object |
| 54 | │ │ └── Money.java ← value object |
| 55 | │ ├── port/ |
| 56 | │ │ ├── in/ ← use case interfaces (driving ports) |
| 57 | │ │ │ ├── CreateProductUseCase.java |
| 58 | │ │ │ └── GetProductUseCase.java |
| 59 | │ │ └── out/ ← repository/external interfaces (driven ports) |
| 60 | │ │ └── ProductRepository.java |
| 61 | │ └── event/ ← domain events |
| 62 | │ └── ProductCreatedEvent.java |
| 63 | │ |
| 64 | ├── application/ ← orchestrates domain, no framework code |
| 65 | │ └── service/ |
| 66 | │ └── ProductService.java ← implements use case interfaces |
| 67 | │ |
| 68 | └── infrastructure/ ← outermost, all framework/DB/HTTP code |
| 69 | ├── adapter/ |
| 70 | │ ├── in/ |
| 71 | │ │ └── web/ |
| 72 | │ │ └── ProductController.java ← REST adapter |
| 73 | │ └── out/ |
| 74 | │ └── persistence/ |
| 75 | │ ├── ProductJpaEntity.java ← JPA model (separate from domain entity) |
| 76 | │ ├── ProductJpaRepository.java |
| 77 | │ └── ProductPersistenceAdapter.java ← implements domain port |
| 78 | └── config/ |
| 79 | └── BeanConfig.java |
| 80 | ``` |
| 81 | |
| 82 | Use the templates in `references/patterns.md` for each layer. |
| 83 | |
| 84 | --- |
| 85 | |
| 86 | ## Step 4 — DDD mode: implement tactical patterns |
| 87 | |
| 88 | ### Value Objects (Java 16+: use records) |
| 89 | |
| 90 | ```java |
| 91 | // Java 16+ |
| 92 | public record ProductId(Long value) { |
| 93 | public ProductId { |
| 94 | Objects.requireNonNull(value, "ProductId cannot be null"); |
| 95 | if (value <= 0) throw new IllegalArgumentException("ProductId must be positive"); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | public record Money(BigDecimal amount, String currency) { |
| 100 | public static final String DEFAULT_CURRENCY = "USD"; |
| 101 | public Money { |
| 102 | Objects.requireNonNull(amount); |
| 103 | if (amount.compareTo(BigDecimal.ZERO) < 0) |
| 104 | throw new IllegalArgumentException("Money cannot be negative"); |
| 105 | } |
| 106 | public Money add(Money other) { |
| 107 | if (!this.currency.equals(other.currency)) |
| 108 | throw new IllegalArgumentException("Currency mismatch"); |
| 109 | return new Money(this.amount.add(other.amount), this.currency); |
| 110 | } |
| 111 | } |
| 112 | ``` |
| 113 | |
| 114 | ### Rich Domain Entity |
| 115 | |
| 116 | ```java |
| 117 | public class Product { // NO @Entity here — pure domain |
| 118 | private final ProductId id; |