模块化编程中的代码规范:命名规范、格式化工具与审查清单

说实话,代码规范这事儿,我年轻时觉得是「形式主义」。那时候我写代码,变量名能省则省,什么 abtmp 满天飞。直到有一次,一个项目交接给同事维护,对方看了三天代码,最后打电话问我:「老兄,你这个 p 到底是 pointer 还是 parameter?」——嗯,从那以后,我再也不敢乱起名字了。

今天咱们聊聊模块化编程里的三个硬功夫:命名规范格式化工具代码审查清单。这三样东西,说白了就是让你的代码「能读、能改、能交接」。

一、命名规范:两种主流流派

命名这件事,没有绝对的对错。但团队里必须统一。我见过最惨的案例是:一个项目里同时用了匈牙利命名法、下划线命名法、驼峰命名法,结果一个函数里变量名风格就换了三次。你想想看,这代码还怎么维护?

1. 匈牙利命名法

匈牙利命名法,核心思想是「变量名要体现类型信息」。比如:

int     iCount;      // i 表示 int
char   *szName;      // sz 表示 zero-terminated string
BOOL    bIsReady;    // b 表示 BOOL
HANDLE  hFile;       // h 表示 handle

我个人习惯在 Windows 驱动开发中用这套。为什么?因为驱动里类型转换频繁,看一眼变量名前缀,就知道它是什么类型,能避免不少低级错误。

我的经验:匈牙利命名法适合「类型敏感」的场景,比如底层驱动、协议栈。但在应用层,我建议慎用——因为现代 IDE 都能直接显示类型,前缀反而显得冗余。

2. 下划线命名法

下划线命名法,也叫「蛇形命名法」。Linux 内核、很多嵌入式 RTOS 都用这套。风格是:全小写,单词间用下划线分隔

int     buffer_size;
void    uart_send_data(uint8_t *data, uint32_t len);
#define MAX_BUFFER_LEN  1024

我在做 STM32 项目时,团队就统一用下划线命名法。为什么?因为嵌入式代码里宏定义、枚举、函数名混在一起,下划线风格一眼就能看出「这是变量还是函数还是宏」。

注意:下划线命名法有个坑——不要用双下划线开头(如 __private_var),因为 C 标准保留给编译器内部使用。我曾经在 GCC 下踩过这个雷,编译报错查了半天,结果就是双下划线惹的祸。

3. 我推荐的混合策略

实际项目中,我建议这样组合:

元素 命名风格 示例
局部变量 下划线命名法 int temp_value;
全局变量 加前缀 g_ int g_system_tick;
函数名 模块名_动作 uart_send_data()
宏定义 全大写 + 下划线 #define UART_BAUD_115200
类型定义 加 _t 后缀 typedef struct {...} uart_config_t;

这套规则我用了十年,团队里新人也容易上手。说白了,命名规范不是为了炫技,而是为了降低沟通成本。

二、代码格式化工具:clang-format

手动对齐代码?那是上个世纪的事了。我见过最夸张的团队,代码审查时一半时间在争论「大括号要不要换行」。后来我强制引入 clang-format,从此天下太平。

1. 什么是 clang-format

clang-format 是 LLVM 项目下的代码格式化工具。它可以根据配置文件,自动调整缩进、空格、换行、大括号位置等。说白了,你写完代码,一键格式化,风格就统一了。

2. 我的 .clang-format 配置

这是我个人项目里常用的配置,你可以直接拿去用:

BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
BreakBeforeBraces: Allman
AllowShortFunctionsOnASingleLine: None
ColumnLimit: 100
PointerAlignment: Left
SpaceAfterCStyleCast: true

解释几个关键点:

  • IndentWidth: 4 —— 缩进用 4 个空格。嵌入式代码嵌套深,4 空格比 2 空格更清晰。
  • BreakBeforeBraces: Allman —— 大括号换行。我个人偏好这种风格,因为左括号单独一行,容易配对。
  • ColumnLimit: 100 —— 每行最多 100 字符。太长了在屏幕上要滚动,太短了又容易断行。
小技巧:在项目根目录放一个 .clang-format 文件,然后配置 Git 的 pre-commit 钩子,每次提交前自动格式化。这样团队里谁都不用操心格式问题。

3. 集成到编辑器

我常用的集成方式:

  • VS Code:安装 C/C++ 扩展,设置 editor.formatOnSave: true
  • CLion:内置 clang-format 支持,直接配置路径即可
  • Vim:用 vim-clang-format 插件,一键 :ClangFormat

你想想看,如果团队里每个人都用同一套格式化规则,代码审查时还会有人纠结「这里多了一个空格」吗?不会。大家只关注逻辑,效率翻倍。

三、代码审查清单:从「看代码」到「审代码」

代码审查不是走过场。我见过太多团队,审查就是「LGTM」(Looks Good To Me)三个字母。结果呢?上线后 bug 频出。真正的审查,应该有一份清单,逐项检查。

1. 我的审查清单模板

这是我多年积累的清单,分享给你:

类别 检查项 说明
命名规范 变量名是否体现用途? 避免 abtmp 等无意义命名
命名规范 宏定义是否全大写? #define BUFFER_SIZE 256
内存安全 指针使用前是否判空? 尤其是函数参数和 malloc 返回值
内存安全 数组访问是否越界? 检查循环边界条件
模块化 函数是否超过 50 行? 超过则考虑拆分
模块化 全局变量是否过多? 尽量用局部变量或参数传递
错误处理 函数返回值是否检查? 尤其是系统调用和库函数
错误处理 是否有未处理的错误路径? 如 switch 的 default 分支
可移植性 是否使用了平台相关代码? 如有,是否用宏隔离?
可移植性 字节序处理是否正确? 网络通信中常见问题

2. 审查流程建议

我建议的流程是:

  1. 自审:提交前,开发者自己对照清单过一遍
  2. 互审:至少一位同事审查,重点关注逻辑和安全性
  3. 终审:架构师或技术负责人审查,关注整体设计
避坑指南:我曾经在一个项目里,审查时发现一个函数有 200 行。审查者说「逻辑没问题」,就放过了。结果后来这个函数成了 bug 重灾区。所以,我建议审查时如果发现函数超过 50 行,直接打回重构。别心软。

四、知识体系总览

下面这张图,帮你把今天的内容串起来:

模块化编程代码规范知识体系 命名规范 格式化工具 审查清单 匈牙利命名法 下划线命名法 混合策略(推荐) clang-format 配置 编辑器集成 Git pre-commit 钩子 命名与内存安全 模块化与错误处理 可移植性检查 目标:可读、可维护、可交接

你看,这三个方面其实是环环相扣的。命名规范让代码「看得懂」,格式化工具让代码「长得像」,审查清单让代码「靠得住」。缺一个,模块化编程就容易走样。

最后说一句:规范不是束缚,而是解放。当你不用再纠结「这个变量叫什么名字」时,你才能把精力真正放在「这个逻辑该怎么设计」上。嗯,这就是我这么多年最大的体会。


公众号:蓝海资料掘金营,微信 deep3321