后端基础规范
后端基础规范
适用场景
任何 Java 源码、模型、服务、Maven 配置或后端目录结构变更时加载。
修改前必读
CANDIDATE_TASK.md。backend/src/main/java/com/shgalaxy/assessment/service/BookingReconciliationService.java及本次修改涉及的模型。backend/src/test/java/com/shgalaxy/assessment/service/BookingReconciliationServiceTest.java和所有相关调用方。- 修改构建时读取
backend/pom.xml;修改交付行为时读取根目录相关 Markdown 文档。
必须遵守
- 技术栈固定为 Java 17、Maven、Spring Boot 3、Spring MVC 和 JUnit 5,优先使用 Spring Boot 官方 starter 与 JDK 标准库。
- 当前
record表示不可变输入输出,enum表示有限状态和动作;没有明确收益不要替换这些模型。 - Controller 只负责协议适配、参数校验和响应映射;业务编排放在应用服务,核心规则放在领域服务。
BookingReconciliationService保持纯决策逻辑:输入当前快照和一次供应商结果,返回一个决策,不访问数据库、网络、消息队列、HttpServletRequest或 MDC。- 决策逻辑不调用
Instant.now();继续使用显式传入的now。其他确需当前时间的应用服务注入Clock,不隐藏读取系统时钟。 - 保留两个公开业务入口及其清晰职责,除非需求明确允许,否则不破坏现有构造器和访问器。
- Spring Bean 使用构造器注入;禁止字段注入和通过静态全局对象取 Bean。
- 文件名、包名、测试位置和代码风格沿用现有项目。
架构与包边界
backend/是当前唯一 Maven 模块,沿用 Maven 标准目录;不要把 Java 源码或测试重新放回仓库根目录。- 根包固定为
com.shgalaxy.assessment,包名全小写并与目录一致,不使用默认包。 - Spring Boot 启动类放在根包,保证默认组件扫描覆盖各业务包;不通过宽泛的额外扫描掩盖包结构错误。
controller放@RestController和协议映射,不包含业务规则、事务或持久化调用。dto放 HTTP 请求和响应模型;请求 DTO 使用 Bean Validation,Controller 不直接暴露持久化实体。service放@Service应用编排和领域决策入口;事务边界放在有写操作的应用服务方法,不放在 Controller。model放领域输入、输出、状态和值对象;不得依赖 Controller、DTO、Servlet API、持久化或供应商客户端。repository只在存在真实持久化需求时创建,负责数据访问,不承载业务判断。client只在存在真实外部调用时创建,负责供应商协议适配、超时与响应转换,不把供应商 DTO 泄漏到领域层。config只放必要的 Spring 配置;traceId 过滤器按07-spring-mvc-traceid.md放在职责明确的 Web/trace 包中。- 依赖方向固定为
controller -> service -> repository/client,领域模型不反向依赖外层;禁止 Controller 直接调用 Repository/Client、循环依赖或跨层静态访问。 - 测试包镜像被测类包名;测试资源放
backend/src/test/resources,不要在测试目录复制主代码实现。 - 新增类默认放入现有最接近职责的包。只有出现至少两个职责一致且需要独立边界的类时才新建子包。
- 没有对应职责时不创建空的
controller、dto、repository、client、config或impl包。 - 不创建
common、util、misc、base等无明确所有者的包;仅单处使用的帮助逻辑留作私有方法。 - 公开类型和方法保持最少;仅供包内协作的类型不扩大可见性,不为测试把私有实现改成
public。
Maven 依赖约束
- 所有后端依赖只在
backend/pom.xml声明;同一依赖版本集中使用现有 properties 管理方式。 - 使用 Spring Boot parent 或 BOM 统一管理 Spring 依赖版本,不为 starter 中已经管理的传递依赖单独锁版本。
- HTTP 接口使用
spring-boot-starter-web,Bean Validation 使用spring-boot-starter-validation,测试使用spring-boot-starter-test;按实际职责添加,不预装未使用 starter。 - 生产代码依赖使用默认编译范围;仅测试使用的依赖必须为
testscope。 - JDK 标准库可完成时不新增依赖;新增依赖必须对应当前需求并说明现有能力为何不足。
- 不引入 Lombok、状态机框架、通用工具包或多个功能重叠的库。
- 不手工修改 Maven 生成目录;
backend/target/不作为源码或交付文档存放位置。
最小实现原则
- 不为单一实现增加接口、工厂、仓储层或预留扩展点。
- 不采用“每层一个接口加一个
Impl”模板;只有多实现、框架代理或明确边界需要时才增加接口。 - 可用少量私有方法消除真实重复,例如统一构造重试、人工审核或
NOOP决策;不要拆成多层组件。 - 持久化、并发控制、事件去重和外部调用只按当前需求实现;不为未来生产化假设预建空层。