# 02 | 编码阶段能做什么:秀出好的code style 你好,我是Chrono。 上节课我介绍了C++程序的生命周期和编程范式,今天我就接着展开来讲,看看在编码阶段我们能做哪些事情。 在编码阶段,我们的核心任务就是写出在预处理、编译和运行等不同阶段里执行的代码,还记得那句编程格言吗: “**任何人都能写出机器能看懂的代码,但只有优秀的程序员才能写出人能看懂的代码。**” 所以,我们在编码阶段的首要目标,不是实现功能,而是要写出清晰易读的代码,也就是要有好的code style。 怎么样才能写出human readable的好代码呢? 这就需要有一些明确的、经过实践验证的规则来指导,只要自觉遵守、合理运用这些规则,想把代码写“烂”都很难。 在此,我强烈推荐一份非常棒的[指南](http://openresty.org/cn/c-coding-style-guide.html),它来自OpenResty的作者章亦春,代码风格参照的是顶级开源产品Nginx,内容非常详细完善。 不过有一点要注意,这份指南描述的是C语言,但对于C++仍然有很好的指导意义,所以接下来我就以它为基础,加上我的工作体会,从**代码格式**、**标识符命名**和**注释**三个方面,讲一下怎么“秀出好的code style”。 ## 空格与空行 当我们拿到一份编码风格指南的时候,不论它是公司内部的还是外部的,通常第一感觉就是“头大”,几十个、上百个的条款罗列在一起,规则甚至细致到了标点符号,再配上干巴巴的说明和示例,不花个半天功夫是绝对看不完的。而且,最大的可能是半途而废,成了“从入门到放弃”。 我写了很多年代码,也看过不少这样的文档,我从中总结出了一条最基本、最关键的规则,只要掌握了这条规则,就可以把你code style的“颜值”起码提高80%。 这条“神奇”的规则是什么呢? 认真听,只有五个字:**留白的艺术**。 再多说一点,就是像“写诗”一样去写代码,**恰当地运用空格和空行**。不要为了“节省篇幅”和“紧凑”而把很多语句挤在一起,而是要多用空格分隔开变量与操作符,用空行分隔开代码块,保持适当的阅读节奏。 你可以看看下面的这个示例,这是我从某个实际的项目中摘出来的真实代码(当然,我隐去了一些敏感信息): ``` if(!value.contains("xxx")){ LOGIT(WARNING,"value is incomplete.\n") return; } char suffix[16]="xxx"; int data_len = 100; if(!value.empty()&&value.contains("tom")){ const char* name=value.c_str(); for(int i=0;i int get_value(const T& v); ``` 代码很简单,但可用的信息太少了,你就可以给它加上作者、功能说明、调用注意事项、可能的返回值,等等,这样看起来就会舒服得多: ``` // author : chrono // date : 2020-xx-xx // purpose : get inner counter value of generic T // notice : T must have xxx member // notice : return value maybe -1, means xxx, you should xxx template int get_value(const T& v); ``` 你可能注意到了,在注释里我都用的是英文,因为英文(ASCII,或者说是UTF-8)的“兼容性”最好,不会由于操作系统、编码的问题变成无法阅读的乱码,而且还能够锻炼自己的英语表达能力。 不过,用英文写注释的同时也对你提出了更高的要求,最基本的是**不要出现低级的语法、拼写错误**。别笑,我就经常见到有人英文水平不佳,或者是“敷衍了事”,写出的都是“Chinglish”,看了让人哭笑不得。 写注释最好也要有一些标准的格式,比如用统一的“标签”来标记作者、参数说明什么的。这方面我觉得你可以参考Javadoc,它算是一个不错的工程化实践。 对于C++来说,也有一个类似的工具叫Doxgen,用好它甚至可以直接从源码生成完整的API文档。不过我个人觉得,Doxgen的格式有些过于“死板”,很难严格执行,是否采用就在于你自己了。 除了给代码、函数、类写注释,我还建议**最好在文件的开头写上本文件的注释**,里面有文件的版权声明、更新历史、功能描述,等等。 下面这个就是我比较常用的一个文件头注释,简单明了,你可以参考一下。 ``` // Copyright (c) 2020 by Chrono // // file : xxx.cpp // since : 2020-xx-xx // desc : ... ``` 另外,注释还有一个很有用的功能就是todo,作为功能的占位符,提醒将来的代码维护者(也许就是你),比如: ``` // TODO: change it to unordered_map // XXX: fixme later ``` 总的来说,要写好注释,你要时刻“换位思考”,设身处地去想别人怎么看你的代码,这样的话,上面的那些细则也就不难实施了。 ## 小结 在编码阶段,拥有一个良好的编程习惯和态度是非常重要的(我见过太多对此漫不经心的“老”程序员)。今天,我只介绍了三个最基本的部分,再来“敲黑板”画个重点: 1. 用好空格和空行,多留白,让写代码就像写诗一样; 2. 给变量、函数、类起个好名字,你的代码就成功了一半; 3. 给变量、函数、类再加上注释,让代码自带文档,就成了“人能够看懂的代码”。 有了这个基础,你还可以更进一步,使用其他高级规则写出更好的代码,比如函数体不能太长、入口参数不宜过多,避免使用else/switch导致层次太深(圈复杂度),等等,这些虽然也很有用但比较琐碎,暂时就不细说了。 对了,还有一招“必杀技”:善用code review,和你周围的同事互相审查代码,可以迅速改善自己的code style。 ## 课下作业 最后是课下作业时间,给你留两个思考题: 1. 你用过哪些好的code style,你最喜欢今天介绍的哪几条? 2. 注释在代码里通常的作用是“说明文档”,但它还有另外一个重要的用法,你知道吗? 欢迎你在留言区写下你的思考和答案,如果觉得对你有所帮助,也欢迎分享给你的朋友,我们下节课见。 ![](https://static001.geekbang.org/resource/image/3a/41/3a5325510a8c10a318f82f9ac2696941.jpg)