CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
软件设计与架构入门/课时/综合架构练习
RawBlame
课时目录12 节

软件设计与架构入门

  1. 01整洁代码
  2. 02设计原则
  3. 03面向对象
  4. 04编程范式
  5. 05设计模式
  6. 06架构原则
  7. 07架构风格
  8. 08架构模式
  9. 09领域驱动设计
  10. 10企业模式
  11. 11综合架构练习
  12. 12路线图对照复习

综合架构练习

C4 图与 ADR 小项目。

40 分钟

综合架构练习:C4 模型 + ADR 实战

这一课你将能做到

  1. 用 C4 模型的四个层级(系统上下文、容器、组件、代码)画出判题平台架构图
  2. 用 ADR(架构决策记录)格式记录"为什么选六边形架构而不是分层"
  3. 把前面 10 课的知识整合成一个可落地的架构方案

为什么要学

前面学了整洁代码、设计原则、OOP、范式、模式、架构原则、架构风格、架构模式、DDD、企业模式,这一课要把它们串起来。C4 模型是"怎么画架构图",ADR 是"怎么记录决策"。两者结合,让架构不再是"脑子里的想法",而是"可评审、可追溯、可传承"的文档。

先建立图像

C4 四层
─────────
L1 系统上下文:判题平台在用户、判题引擎、DB 之间的位置
L2 容器:Web 应用、判题服务、数据库、消息队列
L3 组件:Web 应用内的 Controller、Service、Repository
L4 代码:具体类和方法(可选,一般用 IDE 生成)

ADR 格式
─────────
标题:选择六边形架构
状态:已接受
上下文:判题平台需要支持多语言判题和多种存储
决策:采用六边形架构,核心领域不依赖框架
后果:代码量 +20%,但测试和框架迁移成本降低

跟着做

步骤 1:C4 L1——系统上下文图

判题平台在整体生态中的位置:

┌─────────┐     ┌─────────────┐     ┌─────────┐
│  用户    │────→│  判题平台    │────→│ 判题引擎 │
│ (Web)   │     │ (Spring Boot)│     │ (Docker)│
└─────────┘     └─────────────┘     └─────────┘
                      │
                      ↓
                ┌─────────────┐
                │   MySQL     │
                │  Redis/MQ   │
                └─────────────┘

判题平台是中心,上游是用户,下游是判题引擎和存储。

步骤 2:C4 L2——容器图

┌─────────────────────────────────────┐
│           判题平台系统               │
├─────────┐  ┌─────────┐  ┌─────────┐│
│ Web 应用 │  │ 判题服务 │  │ 通知服务 ││
│(Spring) │  │(Spring) │  │(Spring) ││
│  :8080  │  │  :8081  │  │  :8082  ││
└────┬────┘  └────┬────┘  └────┬────┘│
     │            │            │      │
     └────────────┴────────────┘      │
                  │                   │
           ┌─────────────┐            │
           │  RabbitMQ   │            │
           │  (事件总线)  │            │
           └─────────────┘            │
                  │                   │
           ┌─────────────┐            │
           │    MySQL    │            │
           │   Redis     │            │
           └─────────────┘            │
└─────────────────────────────────────┘

Web 应用接收提交,发事件到 MQ;判题服务消费事件,执行判题;通知服务消费结果事件,推送 WebSocket。

步骤 3:C4 L3——组件图(Web 应用内部)

┌─────────────────────────────┐
│         Web 应用            │
├─────────┐  ┌─────────────┐  │
│Controller│  │  Service    │  │
│Submission│→│  Submission │  │
│Controller│  │  Service    │  │
└─────────┘  └──────┬──────┘  │
                    │         │
             ┌─────────────┐  │
             │  Domain     │  │
             │  Submission │  │
             │  Aggregate  │  │
             └─────────────┘  │
                    │         │
             ┌─────────────┐  │
             │ Repository  │  │
             │  Interface  │  │
             └─────────────┘  │
└─────────────────────────────┘

Controller → Service → Domain → Repository,依赖方向向内,符合六边形架构。

步骤 4:ADR 实战——为什么选六边形架构

# ADR-001: 采用六边形架构而非传统分层

## 状态
已接受 (2025-01-15)

## 上下文
判题平台需要支持:
- 多语言判题(Java/Python/C++),未来可能加 Rust/Go
- 多种存储(MySQL 主库,Redis 缓存,ES 搜索)
- 高并发判题回调(WebSocket 推送)
- 单元测试不依赖 Spring 容器

## 决策
采用六边形架构(端口适配器),核心领域层不依赖任何框架。

## 理由
1. **可测试性**:领域层纯 POJO,不启动 Spring 就能测试
2. **框架无关**:换 Spring → Quarkus 或 Micronaut,核心业务不动
3. **端口隔离**:判题引擎、存储、通知都通过端口接入,可插拔

## 后果
- 正面:测试速度提升 3 倍,框架迁移成本降低
- 负面:代码量增加 20%,需要维护更多接口
- 缓解:用 Spring 的 `List<Port>` 自动注入,减少手动装配

## 备选方案
- 传统分层架构:简单但框架耦合,测试慢
-  clean architecture:与六边形类似,但层次更多,复杂度更高

讲清楚要点

  1. C4 模型:L1 系统上下文 → L2 容器 → L3 组件 → L4 代码,层层递进。
  2. ADR:标题、状态、上下文、决策、理由、后果,让决策可追溯。
  3. 架构图不是艺术品:是给团队看的沟通工具,重点是"谁调谁、谁依赖谁"。
  4. ADR 不是马后炮:是决策时的记录,包括备选方案和后果。
  5. 综合应用:整洁代码 + 设计原则 + 模式 + DDD + PoEAA,最终体现在 C4 图和 ADR 里。

你可能会懵的地方

  • C4 和 UML 什么关系? C4 是 UML 的简化版,专为架构设计。不学 UML 也能画 C4,重点是"分层抽象"。
  • ADR 要写多少? 关键决策写,显而易见的不用写。判题平台里"选六边形"是关键决策,"用 Lombok"不是。
  • L4 代码层要不要画? 一般不画,IDE 可以生成。关键算法或复杂流程可以画时序图补充。
  • C4 图和代码不同步怎么办? 用工具(如 Structurizr)从代码生成 C4 图,或者定期评审更新。图是文档,不是一次性产物。

错法对照

错法问题正解
画一个巨大的类图信息过载,没人看C4 分层,每层聚焦一个抽象级别
ADR 只写"选了 A"无法追溯为什么写清上下文、备选、后果
架构图和代码脱节图是艺术,代码是现实从代码生成图,或定期评审更新
所有决策都写 ADR文档爆炸只写关键、有争议、影响大的决策
C4 图用错箭头方向依赖方向反了上层指向下层,或外部指向端口

卡点急救

  1. C4 图不知道从哪层开始:先画 L1 系统上下文,确定系统边界;再画 L2 容器,确定技术选型;最后画 L3 组件,确定代码结构。
  2. ADR 写不出来:问自己"这个决策有备选吗?为什么选这个不选那个?"有备选就值得写。
  3. 架构评审没准备:把 C4 图和关键 ADR 打印出来,逐层讲解,重点讲"为什么这样设计"。

面试常问

  • C4 模型四个层级分别是什么? 答:L1 系统上下文(系统在生态中的位置)、L2 容器(技术选型,如 Web 应用、数据库)、L3 组件(代码结构,如 Controller、Service)、L4 代码(具体类,一般用 IDE 生成)。
  • ADR 的核心要素? 答:标题、状态、上下文、决策、理由、后果、备选方案。判题平台"选六边形架构"的 ADR 要写明"为什么选、放弃了什么、有什么代价"。
  • 怎么把 DDD、设计模式、架构风格整合到一个项目里? 答:DDD 提供领域模型(实体、值对象、聚合),设计模式提供协作方式(策略、观察者、工厂),架构风格提供骨架(六边形),C4 提供文档,ADR 提供决策记录。判题平台就是这套组合。

自测三问

  1. 画出判题平台的 C4 L2 容器图,标出每个容器的技术选型。
  2. 写一个"为什么选 RabbitMQ 而不是 Kafka"的 ADR。
  3. 判题平台的 Submission 聚合根包含哪些对象?为什么 JudgeResult 不能是聚合根?

小结一句话

C4 让架构可视化,ADR 让决策可追溯;两者结合,让架构从"脑子里的想法"变成"团队可评审的方案"。

延伸

  • 《架构整洁之道》Robert C. Martin,第 22-24 章
  • C4 模型官网
  • ADR 模板 - Michael Nygard
  • 下一课:路线图对照复习——与 software-architect-essentials 的分工对照。
加载本节练习…
← 上一课企业模式下一课 →路线图对照复习