一句话: 协议处理函数里四个通道各有一个 case 分支,每个 30+ 行,逻辑完全一样只是通道号不同。修一个 bug 要改 4 个地方,修完还漏了一处。把这些 case 合并成参数化的一代码块,148 行缩到 55 行,修 bug 只改一处。
适合谁读:写过 switch-case、维护过重复代码的嵌入式开发者。
改之前的样子
四个通道,四个 case,逻辑几乎一样——只有通道号和系数不同:
switch (u8Cmd) { case 1: // 通道 0 if (bCalMode) { u16Dac = EEPROM_Read(EEPROM_CH0 + u16Idx); } else { u16Dac = (rxBuf[3] << 8) | rxBuf[4]; } DAC_Write(0, u16Dac); txBuf[2] = COEFF_SINGLE; txBuf[3] = (u16Dac >> 8) & 0xFF; txBuf[4] = u16Dac & 0xFF; break; case 2: // 通道 1 — 几乎一样 ... case 3: // 通道 2 — 又一样 ... case 4: // 通道 3 — 还是几乎一样,除了系数不同 ... }问题:
- 修一个 bug → 改 4 个地方 → 容易漏
- 新增通道 → 复制粘贴 → 又多了 30 行
- 扫一眼"四个 case 都一样" → 跳过,错过隐藏的差异
合并后
case 1: case 2: case 3: case 4: { uint8_t u8Ch = u8Cmd - 1; // 0/1/2/3 float fCoeff = (u8Ch < 3) ? COEFF_SINGLE : COEFF_DUAL; uint16_t u16Dac; if (bCalMode) { u16Dac = EEPROM_Read(g_au32EepromBase[u8Ch] + u16Idx); } else { u16Dac = (rxBuf[3] << 8) | rxBuf[4]; } DAC_Write(u8Ch, u16Dac); // 通道 3 是双路并联,写完主通道必须写副通道 if (u8Ch == 3) { DAC_Write(4, u16Dac); } txBuf[2] = (uint8_t)(fCoeff); txBuf[3] = (u16Dac >> 8) & 0xFF; txBuf[4] = u16Dac & 0xFF; break; }| 差异项 | 合并前 | 合并后 |
|---|---|---|
| 通道号 | 每个 case 硬编码 | u8Cmd - 1自动映射 |
| 系数 | 每个 case 不同值 | 三元表达式 |
| EEPROM 地址 | 每个 case 不同常量 | 用数组 |
| 双路并联 | case 4 单独一个 if | 块内一行if (u8Ch == 3) |
| 应答帧 | 四个 case 完全一样 | 块末尾统一处理 |
经验
复制粘贴超过 2 次时,停下来找参数化的方式。
四个通道 = 只是通道号不同。系数只有两种。地址用数组。剩下的逻辑完全一样——为什么要写四遍?
合并后:修 bug 只改一处。新增通道只需改数组。真正的差异(双路并联、系数不同)一眼能看到。
实测对比:4个case 148行: 修bug改4处,容易漏 | 1个块 55行: 修bug改1处,不可能漏
有用的话点个收藏,下次调试直接用。有问题欢迎评论区交流,看到了都会回。
下一篇:保姆级教程——状态机、编码规范、编译链接——每个嵌入式新人都要过的三道坎