首页 / 资讯中心 / 文章详情

C/C++编码规范落地:规则建议分档、布局命名与可读性提升

C/C++编码规范落地:规则建议分档、布局命名与可读性提升 ★ FEATURED ARTICLE
简介《中兴通讯软件编程规范——C/C》是一份面向 C/C 开发工程师、代码评审人员及团队规范制定者的企业级编码标准可用于统一编程风格、提升源码可读性与可维护性也适合作为新人培训与代码走查的参考依据。文档围绕布局、注释、命名规则、变量常量与类型、表达式与语句、函数与过程等主题展开并进一步讨论可靠性、可测试性、断言与错误处理正文以规则、建议、说明、正例和反例组织便于对照落地。压缩包内为 1 个 doc 文件约 486KB包含规范正文及附录中的编程模板和规范检查表可直接用于项目编码约定或评审清单。目前已有 301 人学习适合需要建立 C/C 编码底线、减少常见缺陷并促进团队协作的开发与测试人员查阅。1. 一句话说清 C/C 编码规范为什么你的代码别人读着像天书C/C 编码规范说白了就是一份“代码该怎么写”的集体约定缩进几格、注释放哪、变量怎么起名、函数写到多长就该拆。它管的不是程序能不能跑通——那是语法和逻辑的事——而是另一个人接手时能不能在十分钟内看懂。打个比方语法规则决定了你会不会说这门语言编码规范决定的是一屋子人开会时能不能听懂彼此说话。很多人第一次听说“编码规范”会以为是给新手补语法课其实恰恰相反越是写过几年代码的人越容易被自己三个月前写的东西绊住。函数里那个i到底是循环下标还是索引缓存这段if为什么没加大括号全靠回忆。规范存在的意义就是把这类“回忆成本”提前消灭掉。2. 为什么规范要分“规则”和“建议”两档强制与弹性的边界一份动不动上百条的编码规范如果每条都写成“必须”用不了多久就会被集体绕过——写的人嫌烦审的人挑不完最后整份文档变成摆设。2003 年初某通信设备企业把自己内部对 C/C 的要求整理成了一份企业标准发布两天后即开始执行规定此后新写和修改的代码都要照办。它采用的办法不是一刀切而是给每条内容标上“档位”。2.1 五个关键词原则、规则、建议、说明、正例反例这套文档在术语部分就把话说死了一共五个词分工明确原则编程时应该坚持的指导思想。它是方向不是判据。规则编程时必须遵守的约定。违反了就是要改。建议编程时必须加以考虑的约定。考虑了可以不用但要有理由。说明对某条规则或建议的必要解释告诉你“为什么这么定”。正例 / 反例一对代码片段把抽象条文落成看得见的样子。别看只有五个词它解决的是一个很实际的问题评审时怎么吵架才算有效。没有这套档位两个人争论缩进几格只能拼嗓门有了档位一句“这一行违反规则 2-3-1改用 4 个空格”就把讨论收敛了。而遇到“建议”类条目双方也可以坦然地写下“本项目不采纳原因是历史代码量大”。配套的还有编号体系条目普遍写成【规则 2-1-2】【建议 2-3-1】这种形式第一位数字对应章节。编号看起来枯燥实际是这套规范能被引用的前提——口头说“你这里缩进不对”是主观意见说“违反规则 2-3-1”是可核查的结论。2.2 为什么必须分档一刀切的规范注定被绕过打个比方交通法规里“红灯停”和“建议保持安全车距”都写在同一个本子里但性质完全不同前者违反就是违法后者是你能动脑筋判断的余地。如果连“车距必须恰好五十米”都写成硬规则那所有人在堵车时都得违规。软件项目也是这个道理。同一条“函数不超过 80 行”在写设备驱动的模块里可能绰绰有余在写协议解析状态机的模块里可能处处受限。规范的制定者显然清楚这一点原文在适用范围里就写明考虑到不同产品和项目的实际开发特性规范分成规则性和建议性两种规则性要求所有开发人员严格执行建议性由各项目编程人员根据实际情况选择。这里藏着一个成熟团队的取舍把“底线”和“偏好”分开。底线部分不讨论讨论就是浪费时间偏好部分允许讨论但必须留下结论。反过来说如果你所在团队把一百多条全部当成硬规则结果往往是重要的几条没人记得边角的几条天天有人争——这就是很多团队推行规范翻车的原因他们把弹性当成了软弱又把强制用错了地方。2.3 八条基本原则整份规范的“宪法”文档在正文最前面列了八条原则后面所有的布局、注释、命名条款基本都能追溯到这八条里的某一条。理解了它们很多“为什么要这么规定”就不用死记。原则一首先是为人编写程序其次才是计算机。原文给出的理由是软件的生命周期贯穿开发、测试、生产、用户使用、版本升级和后期维护只有易读、易维护的代码才有生命力。翻译成大白话机器不挑食编译器什么样的代码都能吃下去但下一个维护的人会挑。代码被读的次数远多于被写的次数这个账要先算明白。原则二保持代码的简明清晰避免过分的编程技巧。原文用了四个字——“简单是最美”。这不是审美问题而是工程问题技巧型的代码作者自己一周后都未必看得懂而它换来的那点性能收益往往在整体性能里察觉不到。把i i i这种靠副作用顺序取巧的写法写进产品代码是典型的自找麻烦。原则三所有代码尽量遵循 ANSI C 标准。尽量不使用 ANSI C 未定义的、或编译器扩展的功能。这条在跨平台项目里是保命的某个编译器“好心”支持的扩展语法换一个编译环境就报错而这种错误往往在最不该出问题的时候冒出来。原则四编程时首先达到正确性其次考虑效率。原文的表述是先满足正确性、健壮性、可维护性、可移植性等质量因素最后才考虑程序的效率和资源占用。这条常被误解成“效率不重要”实际是“顺序不能反”。先让程序对再让它快先让它能被改再让它跑得省。倒过来做的结果通常是又快又错的代码。原则五避免或少用全局变量。理由写得很直接过多使用全局变量会导致模块间紧耦合违反模块化要求。全局变量的问题不在于“占内存”而在于它把模块之间原本清晰的边界搅浑了——任何一个函数都能改它于是没人知道它是在哪一刻变成现在这个值的。原则六尽量避免使用 GOTO 语句。注意是“尽量”。这四个字留了口子能靠结构改写的就改写实在改不动的地方至少把跳转收敛到一处。C 语言里“出错就跳到函数末尾统一清理”是一种常见写法/* 反例思路跳转分散在函数各处时路径一多就没人敢改 */ int DoWork(void) { int iRet 0; if (!Init()) { iRet -1; goto EXIT; /* 跳转到函数末尾统一清理 */ } if (!Prepare()) { iRet -2; goto EXIT; } iRet Run(); EXIT: CleanUp(); return iRet; }这段代码里goto的落点只有一处阅读时能一眼看到出口属于相对可控的用法真正麻烦的是跳转目标散落在函数各处、形成网状路径的写法。判断标准很简单你是不是得在脑子里画一张流程图才能读完这个函数。如果是那这段结构就该重写了。原则七尽可能重用、修正老的代码。原文说尽量选择可借用的代码对其修改优化以满足自身要求。这句话有点反直觉——重用老代码听起来保守但它省下的是重新踩一遍别人踩过的坑的成本。原则八尽量减少同样的错误出现的次数。原文很坦诚事实上无法完全消除错误但通过不懈努力可以减少同样的错误出现的次数。这条几乎是整份规范的元原则——规范不能让你不犯错但能让你不重复犯同一个错。3. 布局与注释最像“表面功夫”的部分恰恰最影响可读性一提到缩进、空格、空行很多人第一反应是“这不就是排版嘛编辑器一键格式化就完事”。但排版在代码里的作用跟排版在书里的作用一样它不改变内容它决定内容能不能被吸收。一份行距混乱、段落不分、注释全挤在角落的说明书哪怕技术内容再对读者也读不下去。3.1 布局管的是三件事分区、缩进、留白文档把布局拆成文件布局、基本格式、对齐、空行空格、断行五块。其中最容易被忽略但收益最大的是文件布局它规定了一个文件里各部分的固定先后顺序头文件和实现文件各有各的顺序。头文件的顺序是文件头注释、防止重复包含的宏、其它条件编译选项、#include、常量定义、全局宏、全局数据类型、类定义、模板、全局函数原型。实现文件的顺序是文件头注释、#include、常量定义、文件内部使用的宏、文件内部使用的数据类型、全局变量、本地变量静态全局变量、局部函数原型、类的实现、全局函数、局部函数。原文特别注明不需要的节可以省略但保留的节必须保持这个次序。/* 文件头模块名、创建日期、功能说明、修改记录由团队模板统一 */ #ifndef MODULE_NAME_H /* 文件名全大写加下划线防止重复包含 */ #define MODULE_NAME_H #include stdio.h /* 标准库头文件用尖括号 */ #include module_cfg.h /* 项目内头文件用双引号 */ #define MAX_BUF_SIZE 256 /* 常量定义区 */ typedef unsigned char BOOLEAN; /* 类型定义区 */ int DoSomething(void); /* 全局函数原型区 */ #endif这段示例对应的规则有三条头文件必须避免重复包含标准库头文件用尖括号、非标准库头文件用双引号多个节之间用注释块分隔。顺序固定的好处是可预测任何人打开一个陌生的头文件都知道常量在上面、函数原型在下面不需要每次都从头扫一遍。这就是“降低回忆成本”的具体形态。3.2 基本格式80 列、大括号、指针星号的位置三条基本格式规则条条都在解决具体的阅读障碍。第一一行的代码和注释不超过 80 列含空格。这条源自终端年代的限制在今天依然有用它逼着人把过长的表达式拆开而拆开的过程往往就是发现“这个条件怎么这么绕”的过程。打印、并排比对、代码评审的屏幕空间都受益于这个限制。第二if、else、else if、for、while、do等语句自占一行执行语句不得紧跟其后不论执行语句有多少都要加{}。原文给的理由是防止书写失误、便于阅读。这条的血泪经验在于“省略大括号”/* 反例执行语句紧跟 if 条件且没有大括号 */ if (variable1 variable2) variable1 variable2;看起来省了一行代价是后来的人往里加第二句时极易加错位置——尤其当代码被合并、被自动格式化、被某人手工调整缩进之后那句“新增的语句”可能悄悄跑到if外面去了。而编译器不会报错因为语法完全合法。第三定义指针类型变量时*放在变量前float *pfBuffer; /* 正例星号紧贴变量名 */ float* pfBuffer; /* 反例星号贴着类型容易误读成“float 指针类型” */这条纯属约定两种写法编译器一视同仁。但float* pfBuffer, pfOther;这种写法会诱导人误以为两个变量都是指针——实际上pfOther只是普通float。星号贴变量名等于时刻提醒“星号是修饰这个变量的”。3.3 缩进与对齐为什么禁用 TAB、为什么大括号独占一行缩进部分有三条硬规则。禁止使用 TAB 键必须使用空格缩进缩进量为 4 个空格分界符{和}各自独占一行、位于同一列并与引用它们的语句左对齐声明类时public、protected、private与分界符{}对齐这些部分的内容缩进。void Function(int iVar) { /* { 独占一行并与引用它的语句左对齐块内统一缩进 4 格 */ while (iVar 0) { DoSomething(); iVar--; } }禁用 TAB 的理由原文写得很实在消除不同编辑器对 TAB 处理的差异。TAB 到底是 4 格还是 8 格取决于看代码的那个人用什么工具、什么设置。同一份文件在两个人屏幕上呈现两种结构这在评审时是纯粹的噪声。有些编辑器可以设置“按 TAB 键输入空格”这是个实用的小开关。{}独占一行的规则本质是把“块的边界”变成视觉上可数的东西左边缘那一列竖着扫下去每个{都能找到对应的}。类声明的对齐规则同理public:和private:与{对齐是为了让“这段是接口、那段是实现细节”一眼可见。还有一些不那么显眼但很实用的对齐约定结构型数组、多维数组在定义时初始化按矩阵结构分行书写相关的连续赋值语句把等号对齐。后者看起来只是好看实际是让人能快速比对一串赋值的右值是同一量级还是天差地别。/* 按矩阵结构分行行列关系一眼可见 */ int aiNumbers[4][3] { 1, 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64 };另外switch语句里每一个case分支和default都要用{}括起来块内内容缩进。这在 C 里不是必须的但一旦某个分支里定义了局部变量缺大括号的写法在某些编译器下会直接翻车加上就没有这类悬念。3.4 空行、空格与断行细节里的可读性空行分隔的是逻辑块。原文明确不同逻辑程序块之间要使用空行分隔——两个函数的实现是两个逻辑块中间就该空一行。同类的还有关系较为紧密的代码尽可能相邻比如矩形的长和宽两个赋值放一起而不是被一句无关的标题字符串插在中间。空格规则按操作符的“目数”区分逻辑很统一一元操作符!、~、、--、取地址、指针*前后不加空格。.、-、[]这类操作符前后不加空格。多元操作符两侧至少留一个空格比如fTotal fValue。关键字if、for、while之后留一个空格再跟左括号以突出它是关键字函数名之后紧跟左括号不留空格以区分“这是函数调用”。左括号(向后紧跟)、,、;向前紧跟紧跟处不留空格,之后和作为分隔用的;之后要留空格。断行的规则更考验判断力长表达式超过 80 列要在低优先级操作符处拆分成新行操作符放在新行之首拆分出的新行做适当缩进使排版整齐。条件表达式的续行在第一个条件处对齐赋值语句的续行在赋值号处对齐。if ((iFormat CH_A_FORMAT_M) (iOfficeType CH_BSC_M)) /* 在 处断开操作符放行首 */ { DoSomething(); }操作符放行首而不是行尾是因为人读多行条件时是“竖着扫”的、||排在左边缘布尔结构立刻清晰如果放行尾它们会散落在各行的最右侧视线得来回横跳。3.5 注释写“为什么”而不是把代码翻译一遍文档对注释的要求只有一句核心判断有效的注释是指在代码的功能、意图层次上进行注释提供有用、额外的信息而不是代码表面意义的简单重复。换句话说iCount; // iCount 加一这种注释等于没写它没有给出任何代码里读不出来的东西。格式上也有硬规定C 语言注释符为/* … */C 中多行注释用/* … */单行注释用// …注释符与注释内容之间用一个空格分隔。最后这条看着琐碎但它和缩进是一个道理——统一了眼睛就不用每次重新校准。真正值钱的注释通常回答三类问题这段代码为什么这么写而不是别的方式、这个魔法数字从哪来、这个函数在什么前提下会被调用。文件头注释则承担另一件事让打开文件的人在三十秒内知道这个文件属于哪个模块、谁维护、改过几次。4. 命名、类型与表达式把“看得懂”落到每个标识符上如果说布局决定了代码的“长相”命名决定的则是代码的“词汇量”。一个函数里出现i、j、tmp、data、flag这五个变量你读它的时候要不停往回翻换成iRetryCount、pstConnInfo、bIsTimeout阅读就变成了顺读。4.1 命名名字是代码里被读次数最多的东西这套规范单列了一章讲命名规则覆盖变量、常量、函数、类、宏等各类标识符。从文档给出的示例里可以反推出它采用的是一套前缀表意的命名法——名字里前几个字母就交代了类型和身份。#define MAX_RETRY_COUNT 3 /* 宏全大写单词间下划线分隔 */ typedef unsigned char BOOLEAN; /* 类型定义全大写 */ class CCounter /* 类名以 C 开头后接名词 */ { public: CCounter(void); ~CCounter(void); int GetCount(void); /* 函数名动词开头首字母大写 */ void SetCount(int iCount); private: int m_iCount; /* 成员变量m_ 表示成员i 表示 int */ }; int iLength; /* i 前缀整型 */ char *pcName; /* pc 前缀指向字符的指针 */ float *pfBuffer; /* pf 前缀指向 float 的指针 */ char strCaption[32]; /* str 前缀字符串数组 */这套写法的好处在声明处就体现出来了看到m_iCount不用往回翻就知道它是成员变量、是整型看到pcName就知道它是个指针而不是数组。代价是名字变长且新人得先学一遍前缀表——这也是为什么前缀命名法在有些团队里被弃用转而用编辑器的高亮和类型提示来替代。这两种选择没有绝对对错关键是一个团队内部必须一致一半人用前缀一半人不用那才是最糟的状态。值得留意的是命名规则里隐含的一条原则名字要能读出用途而不是读出类型之外什么也没有。iData1、iData2这种命名虽然合乎前缀但信息量等于零iRetryCount才是合格的名字。4.2 变量、常量与类型能小不大能 const 不变变量、常量与类型这一章处理的是一类隐蔽的问题变量的作用域和生命周期比它的类型更容易出事。第一条思路是“就近声明、就近使用”。变量在离它第一次被使用最近的地方定义读者就不用在上百行之前去找它的来历也顺带消除了“这个变量在这个函数里到底有没有被改过”的猜疑。第二条思路是“初始化即定义”。定义变量时不给初值是 C/C 里最常见的错误来源之一栈上的局部变量内容不确定一旦某条分支忘了赋值就直接使用读到的是随机值症状表现为时灵时不灵的玄学 bug。第三条思路是“别用魔法数字”。代码里突然出现一个256读者无法判断它是缓冲区大小、超时毫秒数还是某个协议的字段上限。给它一个具名常量等于给这行代码加了一句解释。第四条思路是“能窄不宽、能无符号别乱转”。类型选择的优先级是够用就好别为了省事全用int同时尽量避免不必要的隐式类型转换因为转换发生的那一刻编译器可能一声不吭地截断了一个值。这些条款在各家规范里大同小异核心都是同一件事让变量的“有效范围”尽可能小让它的“取值”尽可能确定。4.3 表达式与语句运算符优先级不靠背靠括号运算符优先级表没人背得全包括写了很多年 C 的人。规范对此的态度很务实与其指望大家记住和谁先算不如用括号把意图写出来。加括号的成本是一个字符不加括号的成本是一次线上事故。同样务实的还有几条避免在表达式里塞副作用比如在判断条件里做自增switch的每个分支以break结束最后必须有default哪怕它是空的循环的边界条件写成一眼能看懂的形式别把和混着用却指望读者自己换算。/* 反例优先级靠记忆副作用混在判断里 */ if (iFlag 2 iOffset) { DoSomething(); } /* 正例括号写清意图自增单独成句 */ iValue iValue 1; if ((iFlag 2) iOffset) { DoSomething(); }这两段的行为在多数编译器下一致但第一段要求读代码的人在脑内跑一遍优先级表第二段不需要。规范想省下的就是这一秒钟。4.4 函数与过程一件事、一个出口、参数别太多函数这一章的核心是“职责单一”。一个函数只做一件事判断标准很朴素你能不能用一句不含“并且”的话说清它做了什么。说不清就该拆。参数也需要克制。参数越多调用点的可读性越差因为你会看到DoSomething(a, b, 1, 0, NULL)这种没人能看懂的调用——那个1和0分别代表什么规范里对应的做法是控制参数个数并把布尔型参数换成有名字的枚举或拆成两个函数。函数声明还有一条很具体的格式规则类型与名称不允许分行书写。函数调用和函数声明的续行要在第一个参数处对齐。/* 正例声明写在一行内续行参数与第一个参数对齐 */ BYTE ReportStatusCheckPara(HWND hWnd, BYTE ucCallNo, BYTE ucStatusReportNo);这里面hWnd是窗口句柄ucCallNo是呼叫编号ucStatusReportNo是状态上报编号——名字里的uc前缀表示无符号字符型。三行参数竖直对齐一眼就能数出有几个参数、分别是什么类型。5. 几个最容易搞混的地方规则、风格、可靠性与可测试性的区别这份文档里的概念密度不低初学者最容易在几个词之间打转。下面五组是我见过被混淆次数最多的。5.1 混淆点一编码规范 vs 代码风格易混点很多人把这两个词当同义词用“咱们定个编码规范”说出口实际上指的是“缩进用几个空格”。为什么混因为规范里最显眼的部分确实是缩进、空格、大括号位置这些看上去纯属审美。怎么区分风格是规范的一个子集只管“长什么样”规范还管“能不能被改”“出错了怎么办”“这段代码测不测得动”。打个比方风格是字体和字号规范是整本排版手册还包括章节编号、图表标注、引用格式。判断方法很简单把一段代码的缩进全部重排如果它仍然是好代码说明风格只是表层如果重排之后你就读不懂了那问题可能出在命名和结构上而不只是缩进。5.2 混淆点二规则 vs 建议易混点文档里明明分了“规则”和“建议”两档但执行时常常一视同仁——要么全都得改要么全都可以不改。为什么混两档在文档里的排版几乎一样都带编号、都配正例反例扫一眼看不出差别只有仔细读那个方括号里的字才发现不同。怎么区分看违反之后的动作。违反规则代码必须改违反建议需要留下一个理由可以是注释、可以是评审记录但不能什么都不说。这条区分线一旦模糊规范就失去了弹性而失去弹性的规范通常活不过两个版本。5.3 混淆点三断言 vs 错误处理易混点两者都表现为“如果某个条件不成立就做点什么”于是有人用断言代替错误处理或者反过来。为什么混代码形态太像了都是一句判断加一个分支。怎么区分看这条分支是给谁看的。断言是给开发自己看的——它表达的是“按设计这种情况绝不可能发生”一旦触发说明代码本身有 bug程序应该立刻停下来让问题在最接近源头的地方暴露而不是带着错误状态继续跑到几百行之后才崩。错误处理是给使用者看的——文件打不开、网络超时、参数越界这些是运行环境的常态程序要能优雅地降级、返回错误码、给出提示然后活下去。用一句话概括断言管“我不该错”错误处理管“世界会出错”。5.4 混淆点四可靠性 vs 可测试性易混点这两章在目录里挨着听起来都是“让代码更靠谱”很多人以为是一回事。为什么混目标确实相关——都是为了让软件少出问题。怎么区分可靠性是“少出错”可测试性是“容易发现错”。可靠性关注的是边界检查、资源释放、异常路径是否被覆盖可测试性关注的是这段代码能不能被单独拎出来验证比如它是否依赖全局状态、是否把 I/O 和计算搅在一起、是否能构造出确定的输入输出。打比方可靠性是把车造结实可测试性是给车留一个能接诊断仪的接口。一辆车可能很结实但完全没法检测也可能很好检测但本身毛病不少这是两个维度。一个具体的差别一段直接读全局配置、算完再写回全局变量的函数可靠性上可能没毛病但可测试性很差——你没法在不改动全局状态的前提下测它。把它改成“参数传入、返回结果”可靠性不变可测试性立刻提升。这也是为什么“避免或少用全局变量”这条原则同时也是一条第可测试性条款。5.5 混淆点五注释 vs 文档易混点文档里有一整章讲注释于是有人以为把注释写足就等于文档齐全。为什么混两者都是用文字解释代码。怎么区分注释解释“为什么”文档解释“怎么用”。注释贴在代码旁边读者是维护者关心的是“这行为什么要判空”“这个常量的 256 是哪来的”文档独立于代码读者是使用者关心的是“这个接口怎么调、参数什么范围、失败了返回什么”。注释写多了会随代码一起腐烂因为改代码的人未必改注释接口文档则该跟着接口一起维护。一个好的判据是把函数体全部删掉只留注释如果还能拼出一份接口说明那说明注释写得太“文档化”了反之如果接口文档里塞满了实现细节那说明文档写成了注释。6. 什么时候该照搬这套规范什么时候别硬套这套文档写于 2003 年面向的是 C/C 语言的产品代码正文覆盖基本原则、布局、注释、命名、变量常量与类型、表达式与语句、函数与过程、可靠性、可测试性、断言与错误处理最后还附了编程模板和规范检查表。它的形态是“标准 附录工具”也就是说它不只告诉你该怎么做还给了你一张能照着检查的表。先说该用的时候。团队超过五个人、代码寿命超过三年、或者需要多人交替维护同一批文件这三条里占两条就值得把规范认真过一遍。人多意味着风格必然分裂寿命长意味着今天省下的一分钟会在三年后变成一小时交替维护意味着“作者本人还记得”这个前提不成立。更进一步如果代码要通过外部评审或交付给第三方一份成文规范还能省掉大量解释工作——它本身就是一种质量证据。此外接手历史遗留代码时这套东西的价值会突然变得极高你不需要喜欢它的每一条你只需要一个统一的尺子去丈量“哪里最该先改”。再说别硬套的时候。两三个人的短期项目把上百条全部执行时间成本会吞掉收益。这种情况下我的建议是只抓三件事命名能读懂、关键处有注释、大括号不省。教学或个人练手也不必逐条背诵挑布局和命名练手就够了因为这两块带来的手感最直接。跨语言项目要特别注意这套规范明确是针对 C/C 的其它语言可以参照但不能照抄——比如命名里的类型前缀在带类型推导的语言里基本是负担。场景建议的力度老代码库改造满屏 TAB 和历史命名新代码全执行改动的行随手指带对齐不做全量重排三到五人的新项目半年周期规则类执行建议类留档说明评审只看规则三十人以上、代码要活十年全量执行配合附录里的检查表做定期抽查跨语言项目只借用布局、注释、函数职责这些语言无关的部分个人学习练布局和命名别背条款还有一条常被忽视的边界规范解决不了设计问题。一段架构上就该拆成三个模块却挤在一个文件里的代码缩进得再标准也救不回来反过来设计清楚但风格混乱的代码至少还能靠格式化工具抢救。所以推行规范的顺序应该是先有设计评审再有编码规范反过来做等于给一栋歪楼刷墙。我自己的习惯是每次开新文件前先把文件头注释模板贴上去把模块名、创建日期、功能说明三行填完再动手写第一行代码每次合并前跑一遍格式检查把 TAB 和超过 80 列的行挑出来。这两件事花不了几分钟但它们把“以后再说”变成了“现在就顺手”的默认动作。规范真正的价值不在文档里那些条文而在于它能不能变成这种默认动作——文档只是把默认动作写清楚剩下的靠每一次提交去落实。这份规范连同附录里的编程模板和检查表放在下面需要的时候拿它当尺子量一量就好希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站