Skills for creating, testing, reviewing, migrating and guarding Spring Boot 4 projects with Java 25: project scaffolding with architecture patterns, Boot 4 test templates, code review, Boot 3 to 4 migration, and a team harness of build gates and agent hooks.
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
| Criteria | Layered | Package-by-Module | Modulith | Tomato | DDD+Hex |
|---|---|---|---|---|---|
| Team Size | 1-3 | 3-10 | 5-15 | 5-15 | 10+ |
| Lifespan | Months | 1-2 yrs | 2-5 yrs | 3-5 yrs | 5+ yrs |
| Type Safety | Low | Low | Low | High | High |
| Learning Curve | ⭐ | ⭐⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
com.example.app/
├── controller/
├── service/
├── repository/
└── domain/When to use: Simple CRUD applications, prototypes, MVPs, single developer projects.
com.example.app/
├── products/
│ ├── domain/
│ └── rest/
├── orders/
│ ├── domain/
│ └── rest/
└── shared/When to use: 3-5 distinct features, medium-sized applications, need feature isolation.
com.example.app/
├── products/
│ ├── internal/ ← Package-private implementations
│ ├── ProductsAPI.java ← Public module API
│ └── domain/
├── orders/
│ ├── internal/
│ ├── OrdersAPI.java
│ └── domain/
└── shared/When to use: Need enforced module boundaries, want to test module independence, planning potential microservices extraction.
com.example.app/
├── products/
│ ├── domain/
│ │ ├── vo/
│ │ │ ├── ProductSKU.java
│ │ │ ├── Price.java
│ │ │ └── Quantity.java
│ │ ├── ProductEntity.java
│ │ ├── ProductService.java
│ │ └── ProductQueryService.java
│ └── rest/
│ ├── ProductController.java
│ └── converters/
│ └── StringToProductSKUConverter.java
└── shared/
└── vo/
├── Money.java
└── Email.javaWhen to use: Rich domain models, need type safety, financial/healthcare domains, experiencing validation bugs from primitive types.
com.example.app/
├── products/
│ ├── application/
│ │ ├── command/
│ │ │ ├── CreateProductHandler.java
│ │ │ └── UpdateProductHandler.java
│ │ └── query/
│ │ └── ProductQueryService.java
│ ├── domain/
│ │ ├── model/
│ │ │ ├── ProductAggregate.java
│ │ │ └── ProductFactory.java
│ │ ├── vo/
│ │ │ ├── ProductSKU.java
│ │ │ └── Price.java
│ │ └── ports/
│ │ └── ProductRepository.java (interface)
│ ├── infra/
│ │ └── persistence/
│ │ └── JpaProductRepository.java (impl)
│ └── interfaces/
│ └── rest/
│ └── ProductController.java
└── shared/
└── domain/When to use: Complex business domains, CQRS needed, infrastructure independence required, 10+ team members, 5+ year lifespan.
| Type | Pattern | Example | Package |
|---|---|---|---|
| Entity | *Entity | ProductEntity | domain/model/ |
| Aggregate Root | *Aggregate | OrderAggregate | domain/model/ |
| Value Object | Domain name | ProductSKU, Price, Email | domain/vo/ |
| Command | *Cmd | CreateProductCmd | application/command/ |
| Command Handler | *Handler | CreateProductHandler | application/command/ |
| View Model | *VM | ProductVM | domain/models/ or interfaces/rest/dto/ |
| Write Service | *Service | ProductService | domain/ |
| Read Service | *QueryService | ProductQueryService | application/query/ |
| Repository Interface | *Repository | ProductRepository | domain/ports/ (DDD) or domain/ |
| Repository Impl | Jpa*Repository | JpaProductRepository | infra/persistence/ |
| Module API | *API | ProductsAPI | Package root |
| Converter | StringTo*Converter | StringToProductSKUConverter | rest/converters/ |
products/ not product/of() factory method| Don't | Do | Why |
|---|---|---|
| Jump to implementation | Ask assessment questions first | Prevents over-engineering or under-engineering |
| Use DDD for simple CRUD | Use Layered or Package-by-Module | DDD adds complexity without benefit for simple cases |
| Use Layered for complex domain | Use Tomato or DDD+Hexagonal | Layered architecture leads to anemic domain models |
| Skip infrastructure | Always include Flyway, Testcontainers, Docker | Production readiness requires proper infrastructure |
| Copy templates blindly | Read template comments, adapt to domain | Templates are starting points, not solutions |
| Primitive obsession | Use Value Objects for domain concepts | Type safety prevents bugs, makes intent explicit |
| Anemic domain model | Put business logic in entities/aggregates | Domain-Driven Design principle |
| God services | Split by command/query responsibility | CQRS improves maintainability |
| Shared mutable state | Use immutable Value Objects | Thread-safety and predictability |
| From | To | Trigger | Effort |
|---|---|---|---|
| Layered | Package-by-Module | 3+ features, team grows to 3+ | Low |
| Package-by-Module | Modular Monolith | Need enforced boundaries, testing independence | Medium |
| Modular Monolith | Tomato | Type confusion bugs, validation scattered across layers | Medium |
| Tomato | DDD+Hexagonal | Need infrastructure independence, CQRS, complex business rules | High |
Layered → Package-by-Module:
Package-by-Module → Modular Monolith:
*API.java interfaces for each module@ApplicationModuleTest for module verificationmodularity-test.java templateModular Monolith → Tomato:
Tomato → DDD+Hexagonal:
Layered:
Package-by-Module:
Modular Monolith:
Tomato: