Quarkus BCE 后端工作流
范围与目录边界
- 严格边界: 仅操作
backend/内部。绝不触碰frontend/中的文件。 - 架构: 严格的 Adam Bien BCE 模式(
com.app.<domain>.{boundary, control, entity})。 - 技术栈: Quarkus,Jakarta EE(仅
jakarta.*——绝不使用javax.*或org.springframework.*)。
两阶段执行门控
阶段一:契约与骨架(暂停等待人工审核)
entity: 在..<domain>.entity内创建/更新不可变的 Javarecord负载(包含@NotNull、@NotBlank、@Schema)以及 JPA/Panache 实体。零依赖control或boundary。boundary: 在..<domain>.boundary内创建/更新 JAX-RS@Path资源签名(@Transactional、@RolesAllowed、@Operation)。- 测试: 在
backend/src/test/java/..<domain>/boundary/内创建/更新失败的 JUnit@QuarkusTest或单元测试桩。 - 暂停: 向用户展示
entity、boundary和测试的差异。等待批准后再编写control实现。
阶段二:实现与架构导出
control: 在..<domain>.control内实现业务逻辑(@ApplicationScoped)。绝不能直接调用其他领域的control;始终通过其boundary调用。- 验证并导出契约: 在
backend/内运行:./mvnw test
Java 25 LTS 语言与 JVM 规则(强制性)
目标为 Java 25 LTS 专属(<maven.compiler.release>25</maven.compiler.release>)。绝不编写遗留的 Java 8/11/17 样板代码:
- 穷尽 Switch 与记录解构(
control和entity):- 使用
sealed interface+record实现,在entity中建模领域结果和状态机。 - 在
control中,使用穷尽switch表达式,结合记录模式解构和带守卫的when子句(例如case PaidOrder(var id, var total) when total > 1000 -> ...)。 - 绝不能在
sealed interface的 switch 中包含default分支,以便 Java 25 编译器在添加新状态时强制穷尽性。
- 使用
- 灵活构造函数体(JEP 513):
- 直接在构造函数内、在调用
super(...)或this(...)之前执行快速失败验证和数据归一化,而不是创建膨胀的静态辅助方法。
- 直接在构造函数内、在调用
- 未命名变量(
_):- 对于未使用的 lambda 参数、被忽略的异常变量或未使用的解构记录组件,始终使用
_(例如case Order(var id, _, _))。
- 对于未使用的 lambda 参数、被忽略的异常变量或未使用的解构记录组件,始终使用
- 虚拟线程与作用域值(JEP 506):
- 对于 Quarkus
boundary中的阻塞 I/O 端点,除非需要流式处理,否则优先使用@RunOnVirtualThread而非响应式Uni<T>链。 - 绝不使用
ThreadLocal;如果在线程作用域内传递上下文状态,始终使用 Java 25 的ScopedValue<T>。
- 对于 Quarkus
- 现代集合与流收集器(JEP 485):
- 使用
SequencedCollection方法(.getFirst()、.getLast()、.reversed())代替索引计算list.get(list.size() - 1)。 - 使用
Stream.gather(Gatherers.windowFixed(...))代替手动分块循环。
- 使用
- 除非明确要求,否则不使用预览标志:
- 坚持使用已最终确定的 Java 25 LTS 功能(除非明确要求,否则不要为 JEP 507 原始模式或 JEP 505 结构化并发启用
--enable-preview)。
- 坚持使用已最终确定的 Java 25 LTS 功能(除非明确要求,否则不要为 JEP 507 原始模式或 JEP 505 结构化并发启用