Files
conti-backend/docs/README.md
Guangfei.ZhaoandClaude Code aca7487be2 feat: Kotlin 语法约束——只当语法糖用,不当新范式用
新增 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>
2026-09-30 16:01:22 +08:00

46 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端架构决策文档
Kotlin 2.4 + Spring Boot 4.1 + Java 21 + Gradle 多模块(模块化单体)的架构决策记录,按序号阅读。
**这些文档是本仓库代码的约束来源。** 代码和文档不一致时,以文档为准改代码——包括不要为了让代码通过而把
`architecture-test` 里的 ArchUnit 规则调松。骨架落地时对文档有意偏离的几处,都在对应代码的注释里注明了原因。
| 文档 | 内容 |
| --- | --- |
| [01-project-structure.md](./01-project-structure.md) | 工程结构 / 模块划分(模块化单体,`-contract` 契约模块,版本基线) |
| [02-layering.md](./02-layering.md) | 分层规范(api/application/domain/infrastructure,Entity 边界) |
| [03-persistence.md](./03-persistence.md) | 持久层方案(Spring Data JPA + Hibernate + MySQL,Flyway 多实例) |
| [04-security-auth.md](./04-security-auth.md) | 安全与认证(Spring Security + JWT,refresh 轮换,门店上下文与越权隔离) |
| [05-integration-layer.md](./05-integration-layer.md) | 集成层设计(同步 RestClient + Resilience4j,F6 Adapter / Mini 客户端) |
| [06-api-design.md](./06-api-design.md) | API 设计规范(统一响应、错误码、请求头、分页与序列化约定) |
| [07-config-governance.md](./07-config-governance.md) | 配置与服务治理(K8s ConfigMap/Secret、Key Vault、启动期校验) |
| [08-observability.md](./08-observability.md) | 可观测性(Micrometer Tracing、结构化日志与脱敏、指标与告警、审计) |
| [09-build-deploy.md](./09-build-deploy.md) | 构建与多环境部署(Docker、GitLab CI/CD、优雅停机、迁移与回滚协同) |
| [10-testing.md](./10-testing.md) | 测试策略(Testcontainers、WireMock、ArchUnit、覆盖率聚合) |
| [11-cross-domain-collaboration.md](./11-cross-domain-collaboration.md) | 跨域协作与聚合(契约模块、领域事件、并行 fan-out 与局部降级) |
| [12-concurrency-and-scheduling.md](./12-concurrency-and-scheduling.md) | 并发、事务与定时任务(事务边界、幂等、乐观锁、ShedLock、本地缓存) |
| [13-kotlin-style.md](./13-kotlin-style.md) | Kotlin 语法与编码约束(只当语法糖用不当新范式用;禁 `!!`/`lateinit`/协程,Entity 禁 data class) |
## 这份副本从哪来、怎么更新
原件在 **[`conti-docs`](../../conti-docs/backend/)** 仓库的 `backend/` 目录,那里是唯一事实来源。
这里是一份副本,目的是让在本仓库里干活的人(和 AI)不用切仓库就能查到约束。
代价是会漂移。**改文档去 `conti-docs` 改,然后同步过来**,不要只改这一边:
```bash
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/`](../../conti-retail-app/docs/)(Flutter,01-14)
- **架构图与 PRD**:[`conti-docs/Architecture-Diagram/`](../../conti-docs/Architecture-Diagram/)
- **未决阻塞项**(错误码表未定等):见 [`conti-docs/README.md`](../../conti-docs/README.md) 的「跨文档的阻塞项」