Skip to content

软件工程与开发流程 ​

S4-001选修进阶约 60 分钟JDK 21企业开发进阶 · 软件工程与设计模式

1. 本节定位 ​

从 S0 到 S3,我们一直在写代码;本节抬头看**"代码是怎么被组织成产品的"**:

text
个人写代码:能跑就行
团队做产品:能跑 + 能改 + 能协作 + 能上线 + 能回滚

★ S4 之后的六节(本节 + SOLID + 三种设计模式 + Spring 中的应用)讲"设计"; 再往后的 Redis、MQ、微服务讲"技术选型" ✓

2. 学习目标 ​

  • 说出软件工程要驯服的三样东西(复杂度、变化、沟通)★★★;
  • 能说出瀑布 / 敏捷 / DevOps 各自解决什么问题 ★★;
  • 知道"需求 → 上线"这条链上每个环节的实践要点 ★★★;
  • 知道代码评审与提交规范的真正作用 ★★★;
  • 能说出"技术债"的两种形态与处理原则 ★★。

3. 前置知识检查 ​

4. 为什么需要这个知识 ​

先看三个"技术很好但项目失败"的典型 ✗:

现象真正的病因
功能都实现了,但改一个需求要两周 ✗复杂度失控(没有边界、没有抽象)
上线前一周天天加班,上线后天天修 bug ✗流程缺失(没测试、没灰度、没回滚)
三个人改同一个文件,每次合并都冲突 ✗协作问题(没有模块边界与接口约定)

★ 这三个都不是"技术问题",但都会以技术问题的形式暴露 ✓✓

软件工程的核心命题 ✓:

让"更多人、更长时间"地维护一份代码,仍然保持可控 ✓

5. 核心概念 ​

5.1 要驯服的三样东西 ★★★ ​

#敌人表现主要手段
①复杂度 ★★★改一处崩三处;新人上手要一个月模块化、抽象、分层(《SOLID 原则》 ~ 《设计模式在 Spring 中的应用》)✓
②变化 ★★★需求总在变,代码改不动开闭原则、扩展点、配置化 ✓
③沟通 ★★接口对不齐、重复劳动、互相等待接口先行、文档、评审 ✓

★ 一条重要认识 ✓✓:

代码的"可维护性"不是审美,而是经济性** ——** 它决定了"下一次改需求要花多少钱" ✓

SOLID 与设计模式的价值,全部在这个账本里 ✓✓

5.2 流程演进:从瀑布到 DevOps ★★ ​

阶段核心特点解决的问题遗留的问题
瀑布 ✗需求 → 设计 → 开发 → 测试 → 上线,逐阶段推进有章法、可计划 ✓反馈太晚(上线才知道错)✗✗
敏捷 ★★小步快跑、两周一个迭代、持续反馈缩短反馈周期 ✓✓工程实践容易跟不上(只学了"站会")⚠️
DevOps ★★★开发与运维一体化 + 自动化流水线把"交付"也变成自动化 ✓✓需要文化与工具支撑 ⚠️

★ "敏捷"最容易被误解的一点 ✓✓:

敏捷不是"不写文档、不做设计、随时改需求" ✗✗

它恰恰要求"工程实践更严格" —— 因为迭代快,所以必须靠"自动化测试 + 持续集成"来接住 ✓✓

★ 本项目的形态就是一个"微型 DevOps" ✓:

text
写代码 → 本地流水线(L1 校验 / L2 快测试 / L3 慢测试)→ 构建站点 → 提交打标签
        ↑ 每一步都是自动化的,且"失败即停"

5.3 从需求到上线:每个环节的实践要点 ★★★ ​

环节关键实践常见坑
需求 ★★明确"不做什么"、可验收的验收标准需求模糊 → 反复返工 ✗
设计 ★★★接口先行(先定契约,再并行开发)一个人拍脑袋定接口,别人被动适配 ✗
开发 ★★小步提交、提交信息规范、分支短命一个分支活两周 → 合并地狱 ✗✗
评审 ★★★看设计而非格式、控制在 400 行内1000 行的 PR 没人认真看 ✗
测试 ★★★测试分层(单元多、UI 少)全靠手工回归 → 越到后面越不敢发 ✗
发布 ★★★灰度 + 可回滚 + 可观测一次性全量发 ✗✗
运维 ★★告警 + 日志 + 指标(《日志框架与日志规范》)出问题只能靠用户反馈 ✗

★ 其中"接口先行"与"小步提交"的收益最直接 ✓✓:

实践收益
接口先行 ★★★前后端/上下游可以并行开发(不用互相等)✓✓
小步提交 ★★每次改动小 → 评审快、回滚容易、冲突少 ✓✓

★ 反面案例(很常见) ✗:

text
一个分支开发两周 → 攒了 80 个文件改动 → 评审只能"看着差不多就合" → 出事 → 回滚要回滚两周的量 ✗✗

★ 所以有一条硬建议 ✓✓:

一个 PR 一件事,改动控制在几百行以内 ✓

做不到就说明"任务拆得不够细" ✓

5.4 代码评审:到底该看什么 ★★★ ​

评审的注意力分配(按重要性) ✓✓:

优先级看什么例子
①正确性 ★★★边界条件、空值、并发、事务边界
②设计与抽象 ★★★这段逻辑该放这里吗?依赖方向对吗?
③可测试性 ★★能不能不连数据库就测?
④可读性 ★★命名、注释(解释"为什么"而非"做了什么")
⑤格式 ⚠️交给工具(Spotless / Checkstyle),不要靠人眼 ✗

★ 最后一条特别重要 ✓✓:

格式问题应该由工具自动检查并自动修复 ✓

让人在评审里讨论缩进和空格,是在浪费两份薪水 ✗✗

★ 评审的另一个隐性收益 ✓:

它是团队知识扩散的主要渠道 —— 比"写文档让人看"有效得多 ✓✓

5.5 技术债:借与还 ★★ ​

技术债的两种形态 ✓:

形态特征处理
有意借的 ★为了赶上线先简化,且记了 TODO 与偿还计划可接受,但要排期偿还 ✓
无意欠的 ✗✗因为不懂而写错(如把配置写死、没做隔离)必须还 ——它会持续产生利息 ✓✓

★ "利息"长什么样 ✓:

text
一处硬编码的连接串 → 每次换环境都要改代码 → 每次发布多 30 分钟
一个没抽接口的依赖  → 想加单元测试却发现必须连数据库 → 测试永远写不起来

★ 一条务实的判断 ✓✓:

技术债的偿还优先级 = "它阻碍了多少后续工作" ✓

不阻碍的债可以放着;阻碍所有人每天工作的债要立刻还 ✓✓

5.6 与本项目已有内容的呼应 ★ ​

本项目其实已经把工程实践都跑过一遍了 ✓ ——只是之前分散在各处:

实践本项目在哪讲过
Git 分支与提交规范《Git 基础与 cherry-pick》 ✓
Maven 依赖与模块化《事务与隔离级别》 ✓
单元 / 切片 / 集成 / UI 测试分层T1-016、T1-017、T2-012 ✓
CI 分层执行与报告归档T2-004、T2-017 ✓
接口设计与文档《Spring MVC 请求映射与参数绑定》、《接口文档与前后端联调》 ✓
日志、指标、traceId《日志框架与日志规范》 ✓
部署与进程管理《Linux 服务部署与运维》 ✓

★ 本节的作用是把这些串起来 ✓ ——它们不是零散技巧,而是同一套工程方法 ✓✓

6. 递进示例 ​

6.1 最小示例:一个规范的提交 ​

text
feat: 新增订单导出接口
                                 ← 空行分隔标题与正文
- 支持按时间范围筛选
- 导出为 CSV,单次上限 1 万条(超出提示分批)
- 补充接口文档与 3 个单元测试

★ 三行正文回答了"改了什么、边界在哪、怎么验证" ✓

6.2 业务示例:一个可并行的任务拆分 ​

text
✗ 一个人做完"订单模块"再做"用户模块" → 串行,且合并时冲突多 ✗
✓ 先定接口(OrderService / UserService 的方法签名)→ 两人并行开发 → 各自提交 ✓✓

6.3 反例:把"紧急"当作跳过流程的理由 ​

text
"这次太急,就不写测试了、直接发到生产"
→ 出问题 → 只能靠回滚 → 更慢 ✗✗

7. 完整可运行代码与实测 ​

本节无新增代码 ——它的"实测"就是本项目自己的流水线数据 ✓

实测数据(来自 T2-004、T2-017):

text
===== 流水线结果 =====
L1 登记表与结构校验        2.3 秒   通过
L2 快速单元测试(13 个模块) 25 秒    通过
L3 慢测试(Spring 模块)    34.5 秒  通过
合计                     61.8 秒

★ 这 61.8 秒换来了什么 ✓:

收益说明
每次改动都被自动验证 ★★不用靠人记得"跑一遍测试" ✓
失败即停早失败早发现,不浪费时间 ✓
报告归档出问题能回溯到具体是哪个类的哪个方法 ✓

★ 对比"没有流水线"的代价 ✓ —— 本项目在 T2-004 实测过: 一次漏测的改动(pom 里少一行 parent)让 L2 直接失败,而流水线在 22 秒内就报了出来 ✓✓

8. Debug 观察点 ​

  1. 看自己项目的提交历史:如果有一堆"fix bug"、"update"、巨型提交 → 说明流程缺失 ✗;
  2. 统计一个 PR 的改动行数:超过 500 行就要警惕 ⚠️;
  3. 问自己"新人上手要多久":这是复杂度最直接的度量 ✓;
  4. 看有没有"没人敢改的代码":那是技术债的重灾区 ✗;
  5. 看回滚一次要多久:超过 10 分钟就说明发布流程有问题 ✗。

9. 常见错误 ​

#错误说明
1把"敏捷"理解为"不做设计" ✗✗敏捷要求更严格的工程实践(5.2)✗
2一个 PR 攒两周的改动 ✗✗无法认真评审、无法安全回滚 ✓
3在评审里讨论格式 ✗应该交给工具 ✓
4接口不定就开工 ✗✗上线前才发现对不齐 ✓
5技术债只借不还 ✗✗利息会越滚越大 ✓
6"紧急"成为跳过测试的常态 ✗✗越紧急越要自动化 ✓✓
7没有回滚方案就上线 ✗✗出事只能靠改代码救火 ✓

10. 动手实验 ​

目标:用"可度量"的方式检查一个项目的工程健康度。

步骤:

  1. 统计最近 20 次提交:平均每次改几个文件、多少行 ✓;
  2. 统计从"提交"到"合并"的平均时间:超过 3 天说明流程有阻塞 ⚠️;
  3. 看有没有自动化验证:没有就补一个最简单的(如编译 + 单元测试) ★★;
  4. 找出一处"硬编码"(连接串、开关、URL),把它外置成配置 ✓;
  5. 挑一个最长的类,试着按 SRP 拆一次(《SOLID 原则》 会讲)✓。

验收方式:能说出"你这个项目最该先还的那笔技术债是什么"。

扩展任务:给项目设计一条最小可用的流水线:

  • L1 静态检查(编译 + 格式)✓;
  • L2 单元测试 ✓;
  • L3 构建产物 ✓;
  • 每层都要"失败即停"并输出耗时 ✓;
  • 说明:为什么"顺序"是"从快到慢"而不是"从重要到次要"(提示:反馈速度)★★

11. 练习题 ​

  1. 判断:敏捷开发意味着不需要写文档和做设计。(对 / 错)
  2. 填空:软件工程要驯服的三样东西是 、、______。
  3. 简答:为什么"格式问题不该在代码评审里讨论"?
  4. (代码阅读)
text
提交历史:
    a1b2c3  fix
    d4e5f6  update
    g7h8i9  提交本次所有改动(含 87 个文件)

这样的历史有什么问题? 5. (设计)给"订单导出"这个需求写一份接口先行的契约(方法签名 + 入参校验规则 + 返回结构 + 错误码)。

参考答案(要点)
  1. 错。敏捷要求更严格的工程实践(自动化测试、持续集成)✓★
  2. 复杂度、变化、沟通 ✓
  3. 因为格式可以(也应该)由工具自动检查与修复 ✗ ——让人讨论格式是浪费两份薪水 ✓★
  4. ① 提交信息没有信息量(看不出改了什么、为什么)✗; ② 87 个文件的巨型提交无法评审、无法安全回滚 ✗✗; ③ 出问题时无法定位到具体改动 ✗
  5. 要点:方法签名 + 参数校验(时间范围上限、单次条数上限)+ 返回(文件流/任务ID)+ 错误码(参数错/条数超限/无权限) ✓

12. 掌握标准 ​

  • [ ] 能说出软件工程要驯服的三样东西 ★★★;
  • [ ] 知道敏捷与 DevOps 各自解决什么问题,以及"敏捷不是不设计" ★★★;
  • [ ] 能说出"接口先行"与"小步提交"的收益 ★★★;
  • [ ] 知道代码评审该看什么、不该看什么 ★★★;
  • [ ] 能区分"有意借的技术债"与"无意欠的技术债" ★★;
  • [ ] 知道"发布必须能回滚" ★★★。

13. 扩展资源 ​

14. 下一步学习 ​

《SOLID 原则》:把"可维护性"变成五条可执行的设计规则。

前置知识

无,可直接开始

后续知识

暂无

进度只保存在本机浏览器,可随时清除

个人学习项目:AI 生成内容均经人工复核,第三方资源仅作索引