跳转到内容

Module 19: 项目实战技能

Module 0-18 教你”设计和理解系统”,这个模块教你”把系统做出来”。覆盖日常开发中每天都会用到的基础技能:Git、终端、测试、Scrum、代码审查、源码阅读、AI辅助开发。


定义:Git 是分布式版本控制系统,记录代码的每一次变更,支持多人协作。不只是”保存”,而是让你能回溯历史、并行开发、安全合并。

为什么重要:所有团队协作的基础。不会Git = 不能参与任何正式项目。

日常必备命令

Terminal window
# 基础流程
git clone <url> # 克隆仓库
git status # 查看当前状态
git add <file> # 暂存变更
git commit -m "message" # 提交
git push # 推送到远端
git pull # 拉取远端变更
# 分支操作
git branch feature-x # 创建分支
git checkout feature-x # 切换分支(或 git switch feature-x)
git merge main # 合并main到当前分支
git branch -d feature-x # 删除分支
# 常用场景
git log --oneline -10 # 查看最近10条提交
git diff # 查看未暂存的修改
git stash # 临时保存未提交的修改
git stash pop # 恢复临时保存
git reset HEAD~1 # 撤回最近一次提交(保留修改)
git cherry-pick <hash> # 把某个提交搬到当前分支

常见场景处理

场景命令
提交了不该提交的文件git reset HEAD~1(撤回提交)→ 修改 .gitignore → 重新提交
合并冲突打开冲突文件 → 手动解决 <<< === >>> 标记 → git addgit commit
想在另一个分支上的改动git stashgit checkout other-branchgit stash pop
提交信息写错了git commit --amend -m "正确的信息"
把main的更新同步到feature分支git checkout featuregit rebase main(或 git merge main
需要回退到某个版本git log 找到hash → git checkout <hash> 查看 → 确认后 git revert <hash>

Commit Message 规范

<type>: <简短描述>
type 常用值:
feat: 新功能
fix: 修复bug
refactor: 重构(不改变功能)
docs: 文档
test: 测试
chore: 构建/工具/依赖变更
示例:
feat: add user login with JWT
fix: prevent double booking in reservation
refactor: extract payment logic to separate service

先想一想 🤔 你在feature分支开发了3天,main分支上有其他人的5个新提交。你用 git merge main 还是 git rebase main?各自有什么效果?

点击查看解析
  • git merge main:创建一个合并提交,保留完整的分支历史。历史图会有分叉和合并。
  • git rebase main:把你的3天提交”搬”到main最新的后面,历史线性清晰,但改写了提交hash。
  • 选择:个人分支用rebase(历史干净),公共分支用merge(安全不改写历史)。

定义:终端(Terminal)是与操作系统交互的文字界面。掌握基础命令是开发者的必备技能。

为什么重要:服务器没有图形界面,部署、调试、运维都依赖命令行。很多开发工具(Git、Docker、npm)本质是命令行工具。

必备命令

Terminal window
# 文件与目录
ls -la # 列出文件(含隐藏文件)
cd /path/to/dir # 切换目录
mkdir -p a/b/c # 创建嵌套目录
cp -r src dst # 复制目录
mv old new # 移动/重命名
rm -rf dir # 删除目录(谨慎!)
find . -name "*.go" # 搜索文件
grep -r "TODO" . # 搜索内容
# 查看与编辑
cat file.txt # 查看文件
head -20 file.txt # 查看前20行
tail -f log.txt # 实时跟踪日志
vim file.txt # 编辑(i进入编辑, Esc退出编辑, :wq保存退出)
# 网络
curl -X GET url # 发HTTP请求
curl -X POST -d '{}' -H 'Content-Type: application/json' url
ping google.com # 测试网络连通
ssh user@host # 远程登录
# 进程
ps aux | grep node # 查找进程
kill <pid> # 终止进程
top / htop # 系统资源监控
# 实用技巧
command1 | command2 # 管道:把前一个命令的输出作为后一个的输入
command > file.txt # 输出重定向到文件
command >> file.txt # 追加到文件
Ctrl+C # 终止当前命令
Ctrl+R # 搜索历史命令
!! # 重复上一条命令

先想一想 🤔 服务器上的应用突然变慢,你需要快速排查。依次用什么命令?

点击查看解析
  1. top — 看CPU和内存占用最高的进程
  2. df -h — 看磁盘空间是否满了
  3. free -h — 看内存使用情况
  4. tail -100 /var/log/app.log — 看最近的应用日志
  5. netstat -tlnp — 看端口占用和连接数
  6. curl localhost:8080/health — 检查应用健康状态

定义:Module 16.1-16.2 介绍了 Docker 的概念,这里补充日常开发中的实操命令和调试技巧。

日常命令

Terminal window
# 镜像操作
docker build -t myapp:v1 . # 从Dockerfile构建镜像
docker images # 列出本地镜像
docker pull postgres:16 # 拉取镜像
docker rmi <image_id> # 删除镜像
# 容器操作
docker run -d -p 8080:8080 --name myapp myapp:v1 # 后台运行
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器(含已停止)
docker logs -f myapp # 实时查看日志
docker exec -it myapp /bin/sh # 进入容器内部
docker stop myapp # 停止容器
docker rm myapp # 删除容器
# Docker Compose
docker compose up -d # 启动所有服务
docker compose down # 停止并删除
docker compose logs -f api # 查看某个服务的日志
docker compose exec api sh # 进入某个服务
docker compose ps # 查看服务状态
docker compose restart api # 重启某个服务
# 调试
docker logs myapp 2>&1 | grep "error" # 搜索错误日志
docker inspect myapp # 查看容器详细信息
docker stats # 实时资源使用
docker compose config # 验证compose文件语法

常见问题排查

问题排查方法
容器启动就退出docker logs <name> 看报错
端口访问不通docker ps 检查端口映射;确认应用监听的是 0.0.0.0 不是 localhost
容器间无法通信确认在同一 docker network;用服务名而非localhost作为主机名
磁盘空间不足docker system prune 清理无用镜像/容器/网络
修改代码后不生效确认用了 volume 挂载本地目录(开发模式)或重新 build 镜像

先想一想 🤔 docker-compose.yml 里,API 服务要连接 PostgreSQL。连接字符串里的 host 应该写什么?

点击查看解析

写 Docker Compose 里定义的服务名(如 postgresdb),不是 localhost。 Docker Compose 会自动创建网络,服务名会被解析为对应容器的IP。 例:DATABASE_URL=postgres://user:pass@db:5432/mydb


定义:通过自动化代码验证系统行为是否符合预期。测试分多个层次:单元测试(测函数)、集成测试(测模块交互)、端到端测试(测完整用户流程)。

为什么重要:没有测试 = 每次改代码都在赌”没改坏其他地方”。测试是你的安全网。

测试金字塔

/ \
/ E2E \ ← 少量:模拟真实用户操作(Playwright/Cypress)
/-------\
/ 集成测试 \ ← 适量:测试模块间交互(API测试、数据库交互)
/-----------\
/ 单元测试 \ ← 大量:测试单个函数/方法(快、多、便宜)
/_______________\

各层次示例(以 Hotel Reservation 为例):

// 单元测试:测试价格计算函数
func TestCalculatePrice(t *testing.T) {
// 3晚 × 每晚200 = 600
price := CalculatePrice(200, 3)
assert.Equal(t, 600, price)
}
// 集成测试:测试预订API + 数据库
func TestBookingAPI(t *testing.T) {
// 准备:数据库里有库存
// 动作:调用POST /api/bookings
// 验证:返回201,库存减少,订单创建
}
// E2E测试:完整预订流程
// 搜索酒店 → 选房型 → 填信息 → 支付 → 确认

什么时候写测试

场景建议
核心业务逻辑(如库存扣减)必须有单元+集成测试
API接口集成测试覆盖主流程+边界
复杂算法单元测试覆盖各种输入
UI交互关键流程E2E测试
工具函数单元测试
简单CRUD按需,不必追求100%覆盖率

给AI的测试指令

请为以下函数写单元测试,覆盖:
1. 正常情况
2. 边界值(0、负数、最大值)
3. 异常情况(参数为nil、空字符串)
用表驱动测试(table-driven test)的方式组织

先想一想 🤔 Hotel Reservation 的库存扣减逻辑,你会写什么测试用例?

点击查看解析
  1. 正常预订:库存5,预订1,库存变4 ✓
  2. 最后一间:库存1,预订1,库存变0 ✓
  3. 库存不足:库存0,预订1 → 报错 ✓
  4. 并发预订:库存1,两人同时预订 → 只有一人成功 ✓
  5. 取消恢复:预订后取消,库存恢复 ✓
  6. 跨日期:预订3晚,每晚库存都扣减 ✓

定义:Scrum 是最流行的敏捷开发框架。核心思想:把大项目拆成小迭代(Sprint),每个Sprint(通常2周)交付可工作的功能,快速反馈、快速调整。

为什么重要:瀑布模式(需求→设计→开发→测试→上线)的问题是周期太长,上线时需求可能已经变了。Scrum让你每2周就能交付价值,及时调整方向。

核心角色

角色职责
Product Owner (PO)决定做什么、优先级。维护 Product Backlog
Scrum Master (SM)保障流程运作,移除障碍
开发团队决定怎么做,自组织完成Sprint目标

核心仪式

仪式时间做什么
Sprint PlanningSprint开始从Backlog选取本Sprint要做的任务,评估工作量
Daily Standup每天15分钟每人说:昨天做了什么/今天做什么/有什么阻碍
Sprint ReviewSprint结束演示成果,收集反馈
Sprint RetroSprint结束回顾:什么做得好/什么要改进/下步行动

核心概念

  • Product Backlog:所有待做事项的优先级列表(PO维护)
  • Sprint Backlog:本Sprint承诺要完成的任务子集
  • User Story作为<角色>,我想要<功能>,以便<价值>
  • Story Points:工作量的相对估算(斐波那契:1, 2, 3, 5, 8, 13)
  • Velocity:团队每个Sprint平均完成多少Story Points
  • Definition of Done:什么算”完成”(代码写完+测试通过+代码审查+部署到staging)

User Story 示例(Hotel Reservation):

作为旅客,我想要按城市和日期搜索可用酒店,以便找到合适的住处。
验收标准:
- [ ] 输入城市+入住/退房日期,返回有库存的酒店列表
- [ ] 按价格排序
- [ ] 显示每晚最低价
- [ ] 无结果时显示提示信息

看板(Kanban)

┌──────────┬──────────┬──────────┬──────────┐
│ To Do │ In │ In │ Done │
│ │ Progress │ Review │ │
├──────────┼──────────┼──────────┼──────────┤
│ 支付集成 │ 搜索API │ 预订API │ 登录功能 │
│ 邮件通知 │ │ │ 数据模型 │
│ 取消预订 │ │ │ │
└──────────┴──────────┴──────────┴──────────┘

先想一想 🤔 一个 User Story 估了13个Story Points,这意味着什么?应该怎么处理?

点击查看解析

13 points 说明这个故事太大了,复杂度高,不确定性大。应该拆分成多个更小的故事(每个3-5 points)。 例:“支付集成”可以拆成:1) 创建支付意图 (3pt) 2) 支付回调处理 (5pt) 3) 退款 (3pt) 如果不能拆,说明需求还没想清楚,先做Spike(技术调研)。


定义:在代码合并到主分支之前,由其他开发者审查代码质量、逻辑正确性、安全性的过程。通常通过 Pull Request (PR) / Merge Request (MR) 进行。

为什么重要:发现bug最便宜的时机是在合并之前。同时也是团队知识分享的重要渠道。

审查清单

功能正确性
- [ ] 代码是否实现了需求描述的功能?
- [ ] 边界情况是否处理?
- [ ] 错误处理是否合理?
代码质量
- [ ] 命名是否清晰?(变量/函数/文件名)
- [ ] 有没有重复代码可以提取?
- [ ] 函数是否过长?(>50行考虑拆分)
- [ ] 是否有不必要的复杂度?
安全性(→ Module 14)
- [ ] 用户输入是否校验?
- [ ] SQL是否参数化?
- [ ] 有没有敏感信息硬编码?
性能
- [ ] 有N+1查询吗?
- [ ] 有不必要的循环/重复计算吗?
测试
- [ ] 关键逻辑有测试覆盖吗?
- [ ] 测试是否能真正验证功能?

提PR的最佳实践

## PR标题
feat: 添加酒店搜索API
## 变更说明
- 新增 GET /api/hotels/search 接口
- 支持按城市+日期范围搜索
- 搜索结果按价格排序,支持分页
## 测试
- [x] 单元测试:搜索逻辑
- [x] 集成测试:API端到端
- [ ] 手动测试:用Postman跑通
## 截图/录屏(如有UI变更)
...

Review 反馈原则

  • 对代码提意见,不对人
  • 用建议而非命令(“考虑用X替代Y?” 而非 “改成X”)
  • 重要问题阻塞合并,风格偏好建议但不阻塞

定义:阅读和理解他人编写的代码库。这是进入任何项目、学习最佳实践、排查问题的核心能力。

为什么重要:开发者80%的时间在读代码,20%在写代码。能快速理解一个陌生代码库 = 生产力的核心。

阅读策略(由外到内)

第1步:全局视角(5分钟)
├── README.md — 项目做什么?怎么跑起来?
├── 目录结构 — 代码怎么组织的?
├── package.json / go.mod — 用了什么依赖?
└── 入口文件 — 程序从哪里开始?
第2步:数据流(15分钟)
├── 数据模型 — 有哪些实体?关系如何?
├── API路由 — 有哪些接口?
└── 挑一个API — 从路由→handler→service→数据库走一遍
第3步:关键流程(30分钟)
├── 找到核心业务逻辑
├── 画出调用链
└── 标注不理解的地方

用 AI 辅助读源码

# 让AI解释整体架构
"请阅读这个项目的目录结构和核心文件,概括:
1. 这个项目做什么?
2. 技术栈是什么?
3. 代码是怎么组织的?
4. 核心业务流程有哪些?"
# 让AI解释具体代码
"请解释这个函数的逻辑,重点说明:
1. 输入和输出是什么?
2. 核心算法/逻辑是什么?
3. 有什么边界情况的处理?"
# 让AI画调用链
"从 POST /api/bookings 开始,追踪完整的调用链,
列出经过的每个函数和文件"

先想一想 🤔 你接手一个完全陌生的Go+React项目,第一个小时你会怎么做?

点击查看解析
  1. 读README(5分钟)— 了解项目是什么、怎么跑
  2. ls 看目录结构(2分钟)— 了解代码组织
  3. 跑起来(10分钟)— docker compose up 或按README步骤
  4. 用浏览器/Postman体验功能(10分钟)— 建立直觉
  5. 看数据模型(10分钟)— models/目录,了解核心实体
  6. 看路由/API(5分钟)— 有哪些接口
  7. 挑一个核心API从头追到尾(15分钟)
  8. 用AI问不理解的部分(剩余时间)

定义:使用 AI 工具(Claude Code、Cursor、Copilot等)提高开发效率的实践方法。

为什么重要:AI 不会取代开发者,但会用 AI 的开发者会取代不会用的。关键是知道 AI 擅长什么、不擅长什么。

AI 擅长 vs 不擅长

AI 擅长AI 不擅长
写重复性代码(CRUD、API)架构设计(选什么技术、怎么拆分)
写测试用例理解业务背景和需求优先级
代码转换(一种语言→另一种)判断需求是否合理
解释代码、找bug决定”不做什么”(克制)
生成样板代码跨系统的一致性保证
重构和优化生产环境的运维决策

高效 Prompt 模式

模式1: 明确需求 + 约束条件
"用Go+Gin写一个限流中间件,使用令牌桶算法,
支持按IP限流,每分钟100次,用Redis存储计数器"
模式2: 给上下文 + 要求扩展
"这是现有的用户模型(附代码),请添加OAuth登录功能,
要求:支持GitHub和Google,用JWT返回token"
模式3: 给出问题 + 要求排查
"这个API在并发请求时偶尔返回错误的库存数。
请检查代码中的并发问题并修复"
模式4: 分步实现
第1步: "先创建数据模型和数据库表"
第2步: "基于数据模型实现CRUD API"
第3步: "添加认证中间件"
第4步: "添加测试"
(不要一次要求太多,分步迭代质量更高)

Vibe Coding 工作流

1. 用5层框架分析需求(自己做)
2. 用 vibe-coding-recipes.md 找到对应配方
3. 填入具体需求,给AI生成MVP代码
4. 跑起来验证基本功能
5. 用 review-checklist.md 审查代码
6. 逐步迭代:加认证 → 加缓存 → 加测试 → 加监控

定义:帮助团队跟踪任务进度、管理需求、协作沟通的工具。

常用工具对比

工具特点适合
GitHub Issues + Projects和代码仓库深度集成,Kanban视图开源项目、小团队
Linear简洁快速,键盘操作友好初创公司、技术团队
Jira功能最全,高度可定制中大型企业
Notion灵活的文档+数据库,可当轻量看板个人/小团队
Trello简单直观的Kanban非技术团队、简单项目

GitHub Issues 实践

# Issue 标题
feat: 添加酒店搜索功能
# 描述
## 用户故事
作为旅客,我想要按城市和日期搜索可用酒店。
## 验收标准
- [ ] GET /api/hotels/search?city=&check_in=&check_out=
- [ ] 返回有库存的酒店列表
- [ ] 按价格排序
- [ ] 分页(cursor-based)
## 技术说明
- 搜索结果缓存30秒(Redis)
- 使用PostGIS进行位置筛选
## 标签
enhancement, backend, priority: high

定义:技术文档是代码之外最重要的产出。好的文档让别人(包括未来的自己)能快速理解和使用项目。

必写的文档

文档内容什么时候写
README.md项目介绍、如何运行、技术栈、目录结构项目创建时
API文档接口列表、请求/响应格式、认证方式API开发完成时
ADR (Architecture Decision Record)重要技术决策的记录(选了什么、为什么、考虑过什么替代方案)做重要决策时
CHANGELOG版本变更记录每次发版时

README 模板

# 项目名
一句话描述这个项目做什么。
## 技术栈
- 后端:Go + Gin + PostgreSQL
- 前端:React + Vite + Tailwind
- 缓存:Redis
- 部署:Docker
## 快速开始
### 前置要求
- Docker + Docker Compose
- Go 1.22+
- Node.js 20+
### 运行
git clone <url>
cp .env.example .env
docker compose up -d
cd server && go run .
cd web && npm install && npm run dev
### 访问
- 前端: http://localhost:5173
- API: http://localhost:8080
- API文档: http://localhost:8080/swagger
## 目录结构
server/ # Go后端
handlers/ # API处理器
models/ # 数据模型
middleware/ # 中间件
web/ # React前端
src/pages/ # 页面
src/api/ # API客户端
## 环境变量
| 变量 | 说明 | 示例 |
|------|------|------|
| DATABASE_URL | 数据库连接 | postgres://... |
| JWT_SECRET | JWT密钥 | random-string |

ADR 模板

# ADR-001: 使用PostgreSQL而非MongoDB
## 状态
已采纳 (2024-01-15)
## 背景
需要选择主数据库,数据模型有明确的关系(酒店-房型-库存-订单)。
## 决策
选择 PostgreSQL。
## 理由
- 数据模型有明确关系,外键和事务是核心需求
- 库存扣减需要ACID事务保证
- PostGIS扩展支持位置搜索
- 团队熟悉SQL
## 考虑过的替代方案
- MongoDB:schema灵活但缺少事务,不适合库存场景
- MySQL:可行但PostgreSQL的JSON和GIS支持更好
## 影响
- ORM使用GORM
- 需要编写migration管理schema变更

  1. 创建一个新仓库
  2. 创建 feature/search 分支,提交3次
  3. 回到 main,故意修改同一个文件,提交
  4. 合并 feature/searchmain,解决冲突
  5. git log --graph --oneline 查看历史

模拟从零开始一个项目:

  1. 用 Scrum 的方式写 3 个 User Story(以 Hotel Reservation 为例)
  2. 估算 Story Points
  3. 创建 GitHub 仓库 + README
  4. 用 Docker Compose 搭建开发环境(Go + PostgreSQL + Redis)
  5. 创建第一个 PR,互相 Code Review
  1. 选一个开源项目(如 gin-gonic/gin
  2. 用”由外到内”策略,在1小时内理解它的核心架构
  3. 写一段200字的总结:这个项目做什么?怎么组织的?核心设计决策是什么?