代码质量与工程实践

用 Code Review、Git 规范和自动化测试守住代码质量的底线

前置知识:第01章 CI/CD 流水线 + 基本的编程能力


阅读指南(初学者必看)

为什么你需要学习代码质量实践?

你可能觉得"我的代码能跑就行",但在团队协作中:

  • 你改了一行代码,三个功能出了问题——因为你不知道影响范围
  • 同事写的代码你不敢改——因为没有测试保护
  • 上线后出 Bug,花了 2 小时才定位——因为日志不够、错误没处理

代码质量实践不是"额外工作",而是"节省时间"。 Code Review 防止问题混入,自动化测试确保改代码不出新问题,Git 规范让团队协作不混乱。

学完本章,你能回答:

  • Git 分支怎么管?Commit 怎么写才规范?
  • Code Review 应该检查什么?游戏项目有什么特殊关注点?
  • 单元测试、集成测试、性能测试分别怎么写?
  • 怎么用测试覆盖率来衡量代码质量?
  • 前端工程化(Webpack/Vite)怎么优化构建?

本文结构

第一部分:Git 规范与分支策略(协作基础)
第二部分:Code Review 最佳实践(团队协作)
第三部分:测试体系(单元/集成/性能测试)
第四部分:前端工程化与构建优化

一、Git 规范与分支策略

分支类型(Git Flow)

分支 说明
master/main 线上环境!稳定!只能合入,不能直接提交!
develop 开发环境!最新的开发代码!
feature/xxx 功能分支!从 develop 切!开发完合回 develop!
release/xxx 发布分支!从 develop 切!发布前测试!测完合 master+develop!
hotfix/xxx 紧急修复!从 master 切!修完合 master+develop!
# 开发新功能
git checkout develop
git checkout -b feature/add-shop
# ... 开发 ...
git checkout develop
git merge feature/add-shop

# 紧急修复
git checkout master
git checkout -b hotfix/fix-login-bug
# ... 修复 ...
git checkout master
git merge hotfix/fix-login-bug
git tag 1.0.1
git checkout develop
git merge hotfix/fix-login-bug

Commit Message 规范(Conventional Commits)

格式:

<type>(<scope>): <subject>

<body>

Type:

Type 说明
feat 新功能
fix 修复 bug
docs 文档
style 代码格式(不影响功能)
refactor 重构
test 测试
chore 构建/工具链

例子:

feat(shop): 新增商店功能
- 商店列表展示
- 购买道具逻辑

fix(login): 修复登录失败问题
- 修复 Token 过期未刷新

模块化开发原则

高内聚:相关的代码放一起!比如商店逻辑放一个模块!
低耦合:模块之间依赖少!改A模块尽量不影响B模块!

H5 游戏目录结构示例:

src/
  ├─ components/       # 组件
  │   ├─ Shop/        # 商店组件
  │   ├─ Player/      # 玩家组件
  │   └─ ...
  ├─ scenes/          # 场景
  │   ├─ HomeScene/
  │   ├─ GameScene/
  │   └─ ...
  ├─ net/             # 网络
  │   ├─ ws.ts
  │   └─ protocol.ts
  ├─ store/           # 状态
  │   ├─ player.ts
  │   └─ shop.ts
  └─ utils/           # 工具
      ├─ math.ts
      └─ ...

二、Code Review 最佳实践

Code Review 检查清单:

功能性:
- [ ] 代码是否实现了需求?
- [ ] 边界条件是否处理?
- [ ] 错误处理是否完善?

性能:
- [ ] 是否有不必要的循环?
- [ ] 内存使用是否合理?
- [ ] 数据库查询是否优化?

安全:
- [ ] 用户输入是否验证?
- [ ] SQL 是否参数化?
- [ ] 敏感信息是否脱敏?

可维护性:
- [ ] 命名是否清晰?
- [ ] 函数是否过长(>50行需拆分)?
- [ ] 是否有重复代码?

游戏特殊:
- [ ] 协议是否兼容老版本?
- [ ] 内存泄漏风险?
- [ ] 是否影响帧率?

Code Review 角度与优先级

优先级 检查维度 常见问题 游戏特有
P0 正确性 逻辑错误、空指针 协议不兼容、数值错误
P0 安全性 SQL注入、XSS 充值漏洞、物品复制
P1 性能 N+1查询、内存泄漏 帧率下降、GC卡顿
P1 可维护性 魔法数字、超长函数 状态机混乱、耦合严重
P2 风格 命名不规范、注释缺失 日志格式不统一

三、测试体系

单元测试(JUnit + Mockito)

// Java 测试示例

// 单元测试(JUnit + Mockito)
@SpringBootTest
class RoomServiceTest {
  @Mock
  private RoomRepository roomRepository;
  
  @InjectMocks
  private RoomService roomService;
  
  @Test
  void createRoom_success() {
    // Given
    Player player = new Player(1L, "test");
    when(roomRepository.save(any())).thenReturn(new Room());
    
    // When
    Room room = roomService.createRoom(player, 4);
    
    // Then
    assertNotNull(room);
    assertEquals(1, room.getPlayers().size());
    verify(roomRepository).save(any());
  }
  
  @Test
  void joinRoom_roomFull_throwsException() {
    Room fullRoom = createFullRoom();
    when(roomRepository.findById(1L)).thenReturn(Optional.of(fullRoom));
    
    assertThrows(RoomFullException.class, () -> {
      roomService.joinRoom(1L, new Player(5L, "new"));
    });
  }
}

集成测试(Testcontainers)

// 集成测试(Testcontainers)
@Testcontainers
class GameRepositoryIT {
  @Container
  static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0");
  
  @Test
  void saveAndFindPlayer() {
    // 使用真实数据库测试
  }
}

性能测试(JMH)

// 性能测试(JMH)
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
class DamageCalculatorBenchmark {
  private DamageCalculator calc;
  
  @Setup
  void setup() { calc = new DamageCalculator(); }
  
  @Benchmark
  long calculateDamage() {
    return calc.calculate(100, 50, 1.5);
  }
}

测试金字塔

           /  E2E测试  \          少量,验证完整流程
          /  集成测试    \        适量,验证模块交互
         /  单元测试      \      大量,验证单个函数
测试类型 范围 速度 数量 游戏场景
单元测试 单个函数 毫秒 大量 伤害计算、匹配算法
集成测试 模块交互 秒级 适量 数据库操作、服务调用
E2E 测试 完整流程 分钟 少量 登录→匹配→战斗→结算
性能测试 性能指标 分钟 关键路径 伤害计算耗时、GC暂停

四、前端工程化与构建优化

为什么游戏前端需要工程化?

H5 游戏的前端代码量越来越大:

  • 代码需要打包压缩才能上线
  • 资源需要按需加载减少首屏时间
  • 代码需要 Tree Shaking 移除未使用代码
  • SourceMap 需要管理以便线上调试

Webpack/Vite 核心优化

优化项 Webpack 配置 Vite 配置 效果
代码分割 splitChunks 内置 减少首屏加载
Tree Shaking usedExports 内置 移除死代码
懒加载 import() import() 按需加载场景
压缩 TerserPlugin 内置 减少体积
SourceMap devtool build.sourcemap 调试支持

游戏前端构建特殊考虑

1. 资源管理
   - 图片/音频自动压缩
   - 大资源分片加载
   - CDN 域名分离

2. 多平台构建
   - Web 版:标准 HTML5
   - 微信小游戏:适配 wx API
   - 抖音小游戏:适配 tt API

3. 版本管理
   - 资源文件名加 hash
   - 缓存策略配置
   - 热更新支持

自问自答

Q:单元测试和集成测试有什么区别? A:单元测试只测一个函数/类,所有外部依赖用 Mock 替代(如 Mock 数据库)。集成测试用真实的依赖(如 Testcontainers 启动真实 MySQL),验证模块之间的交互是否正确。

Q:代码覆盖率多少合适? A:核心逻辑(伤害计算、支付、匹配)争取 80%+,辅助代码(日志、配置)50%+ 即可。追求 100% 覆盖率性价比很低,但关键路径一定要覆盖。

Q:游戏项目有什么特殊的 Code Review 关注点? A:1)协议兼容性——改了协议是否影响老版本客户端;2)内存泄漏——事件监听是否解绑、对象是否回收;3)帧率影响——是否在主循环里做了重操作;4)充值安全——是否有物品复制漏洞。

Q:什么时候写测试,什么时候不写? A:核心逻辑(计算、校验、业务规则)必须写测试,UI 展示和胶水代码可以不写。原则:如果这段代码出 Bug 会造成严重后果(充值错误、数据丢失),就必须写测试。

Q:Git Flow 太复杂,有简单版吗? A:GitHub Flow!只有 main + feature 分支!更简单!适合 CI/CD!10 人以下团队推荐。

Q:怎么防止代码变"屎山"? A:模块化!高内聚低耦合!定期重构!Code Review!写测试!


实践任务

  • 任务1:为游戏核心逻辑(伤害计算/匹配算法)编写单元测试,覆盖正常和异常场景
  • 任务2:使用 Testcontainers 编写集成测试,验证数据库操作的正确性
  • 任务3:配置 SonarQube 代码质量扫描,在 CI/CD 中集成质量门禁
  • 任务4:制定团队的 Code Review 规范,编写检查清单模板
  • 任务5:用 JMH 为性能关键路径编写基准测试,记录基准数据
  • 任务6:优化前端构建配置(代码分割 + Tree Shaking + 懒加载)

与其他章节的关联

本章内容 关联章节 关联点
自动化测试 第01章 CI/CD 流水线 CI 流水线自动运行测试
UI 自动化测试 第05章 游戏自动化测试 本章的测试是代码级,第05章是 UI 级
性能测试 第06章 游戏性能监控 性能测试建立基准,监控发现偏离
测试与发布 第09章 版本管理与灰度发布 测试通过是灰度发布的前提
Git 规范 第01章 CI/CD 流水线 分支策略触发 CI/CD

上一章:03-Kubernetes编排 | 下一章:05-游戏自动化测试