新增 docs/13-kotlin-style.md,并把它落成可执行的构建门禁,而不是一份只能靠
自觉遵守的建议。两条准入标准:只当语法糖(不引入新的思维模型)、每条规则必须
说得出它挡住的具体故障。
- KotlinSyntaxScanTest(源码扫描):禁 !! / lateinit / suspend / kotlinx.coroutines
/ RxJava / Reactor / data class Entity。走源码文本而非 ArchUnit,是因为这些在
字节码上看不出来——!! 编译成 Intrinsics.checkNotNull(...) 调用,和其他 null
检查混在一起。
- ArchitectureRulesTest 加「禁止工具类」:只禁 Utils/Util/Helper/Common 四个
后缀,不禁 XxxManager——Spring 自身大量使用这个命名,一刀切会误伤。
- PersistedEntity + requiredId:把「从 repository 读出来的实体必有 id」变成
一个有名字的类型,替掉 AuthAppService / LocalSeedDataConfig 里 7 处 .id!!。
- 5 个 Entity 实现 PersistedEntity。
两条故意不自动强制的写进了文档:companion object 靠 review 判断(现存 14 处
用法均合法,硬规则只会误伤);Entity 可被 Hibernate 代理目前没守住——未 apply
kotlin("plugin.jpa"),Entity 是 final 类,fetch = LAZY 会静默降级为 eager,现
因为零懒加载关联而未暴露。
docs/01-project-structure.md 顺带补了 Gradle 版本行的双向约束说明;README 修正
了 12 篇→13 篇文档、10 条→11 条规则,并补上工具类禁名。
验证:./gradlew build -PexcludeIntegration 通过。ArchitectureRulesTest 11 项、
KotlinSyntaxScanTest、NativeQueryScanTest 全绿;两条新规则均以「植入一个故意
违规、确认它变红」的方式验证过不是空转。
Co-Authored-By: Claude Code <noreply@anthropic.com>
3.5 KiB
3.5 KiB
后端架构决策文档
Kotlin 2.4 + Spring Boot 4.1 + Java 21 + Gradle 多模块(模块化单体)的架构决策记录,按序号阅读。
这些文档是本仓库代码的约束来源。 代码和文档不一致时,以文档为准改代码——包括不要为了让代码通过而把
architecture-test 里的 ArchUnit 规则调松。骨架落地时对文档有意偏离的几处,都在对应代码的注释里注明了原因。
| 文档 | 内容 |
|---|---|
| 01-project-structure.md | 工程结构 / 模块划分(模块化单体,-contract 契约模块,版本基线) |
| 02-layering.md | 分层规范(api/application/domain/infrastructure,Entity 边界) |
| 03-persistence.md | 持久层方案(Spring Data JPA + Hibernate + MySQL,Flyway 多实例) |
| 04-security-auth.md | 安全与认证(Spring Security + JWT,refresh 轮换,门店上下文与越权隔离) |
| 05-integration-layer.md | 集成层设计(同步 RestClient + Resilience4j,F6 Adapter / Mini 客户端) |
| 06-api-design.md | API 设计规范(统一响应、错误码、请求头、分页与序列化约定) |
| 07-config-governance.md | 配置与服务治理(K8s ConfigMap/Secret、Key Vault、启动期校验) |
| 08-observability.md | 可观测性(Micrometer Tracing、结构化日志与脱敏、指标与告警、审计) |
| 09-build-deploy.md | 构建与多环境部署(Docker、GitLab CI/CD、优雅停机、迁移与回滚协同) |
| 10-testing.md | 测试策略(Testcontainers、WireMock、ArchUnit、覆盖率聚合) |
| 11-cross-domain-collaboration.md | 跨域协作与聚合(契约模块、领域事件、并行 fan-out 与局部降级) |
| 12-concurrency-and-scheduling.md | 并发、事务与定时任务(事务边界、幂等、乐观锁、ShedLock、本地缓存) |
| 13-kotlin-style.md | Kotlin 语法与编码约束(只当语法糖用不当新范式用;禁 !!/lateinit/协程,Entity 禁 data class) |
这份副本从哪来、怎么更新
原件在 conti-docs 仓库的 backend/ 目录,那里是唯一事实来源。
这里是一份副本,目的是让在本仓库里干活的人(和 AI)不用切仓库就能查到约束。
代价是会漂移。改文档去 conti-docs 改,然后同步过来,不要只改这一边:
cp ../../conti-docs/backend/[0-9][0-9]-*.md ./
# 复制完把跨仓链接改回来(原件里是 ../Architecture-Diagram/ 和 ../0X-*.md)
sed -i 's|](\.\./Architecture-Diagram/|](../../conti-docs/Architecture-Diagram/|g' ./[0-9][0-9]-*.md
sed -i 's|](\.\./\([0-9][0-9]-[^)]*\.md\)|](../../conti-retail-app/docs/\1|g' ./[0-9][0-9]-*.md
跨仓链接(架构图、App 侧文档)按 Continental-App/ 下三个仓库平级摆放来写相对路径。
换了目录结构这些链接就断了,重跑一次上面的 sed 即可。
相关
- App 侧架构决策:
conti-retail-app/docs/(Flutter,01-14) - 架构图与 PRD:
conti-docs/Architecture-Diagram/ - 未决阻塞项(错误码表未定等):见
conti-docs/README.md的「跨文档的阻塞项」