說明
New features should be organised by feature/domain, not by technical layer. Each feature module contains its own controller, service, repository, and model classes.
Acceptable package patterns:
com.example.order/ ← feature module
OrderController.java
OrderService.java
OrderRepository.java
Order.java
com.example.inventory/ ← another feature module
InventoryController.java
InventoryService.java
為什麼重要
- High cohesion — related code lives together
- Low coupling — features communicate through well-defined interfaces
- Team autonomy — different teams can own different feature modules
Enforcement
@ArchTest
static final ArchRule packageStructureRule = noClasses()
.that().resideInAPackage("..controller..")
.should().accessClassesThat().resideInAPackage("..repository..")
.because("Controllers should only access their own feature's service layer");
正例
// com.example.order.OrderController
@RestController
public class OrderController {
private final OrderService orderService; // ✅ same feature module
}
反例
// com.example.order.OrderController
@RestController
public class OrderController {
private final InventoryService inventoryService; // ❌ cross-feature dependency
}