分类 技术志 下的文章

代码评审·CC2e·断言·其它

一口气读了七章"Code Complete 2nd(以下称CC2e)"中的内容,从第七章的"高质量的子程序"到第十三章的"不常见的数据类型"。之所以一口气读这么多,是因为被其中的内容吸引了。这两天的下午一直在做代码评审,所以晚上看CC2e的时候,思维不停的在项目代码和书中内容之间跳转。一直把"代码大全2nd"当作一门百科全书式的手册类图书,买回来后一直陈放在书架上没有问津。直到今天在考虑一个关于断言使用的问题时,才想起来去查查这本百科全书,想看看书中是如何阐述断言的。于是便拿起了这本书。

细致的看了2页后才发现,这本书真是很棒啊。其实我们在平时编码过程中遇到的问题在书中基本都覆盖到了,而且说的很到位。如果你能提前看看书中的陈述,想必你在开发过程中会少走很多弯路。这里列举几点,也是我们项目代码里处理得不到位的地方。

断言 vs.错误处理
在昨天评审代码时,发现一位同事在整个模块代码中对接口参数的防御性代码都很不得当;对于内部接口调用,他对可信赖的参数使用了错误处理的方式,如果参数值未按预期,代码直接返回此次调用的结果状态了。关于到底用断言还是用错误处理,估计很多人都很迷惑。'代码大全'里的总结是我见到的最清晰的了。对于来自系统外部数据(包括数据库、文件、网络等)的校验,我们采用错误处理的方式;对于内部接口之间的参数传递,断言更适合。另外对断言而言,断言失败意味着代码中的bug,你应该做的是停止程序,定位问题,重新编译、发布和启动程序。另外'代码大全'中引入了'Barricade'的概念。它建议你在代码中建立所谓的"安全区",安全区外的数据想通过安全区必须通过严格的合法性检查,当非法时给予敏锐的反应;安全区以内将假定数据都是干净的、安全的。而实际上这个"安全区"在项目里很有可能就是一组函数接口,这组接口采用错误处理的方式对待安全区外的数据,保证非法输入不流入内部系统。

断言是否放入产品代码
关于这个问题,更多人坚守的是"断言一定不能出现在发行版中",即一般的看法:断言只是在开发阶段帮助程序员定位bug的工具,Release阶段断言语句将从代码中自动去除。CC2e作者在书中似乎(也许是我没有看到?)并没有肯定的支持这种观点,只是在其"Guidelines for using assertions"一节中委婉的表达出了一个建议:在生成产品代码时,可以不把断言编译进目标代码里去,以免降低系统性能。在另一本大作"编程珠玑2nd"中,作者Jon Bentley间接引述了Tony Hoare的一个观点:"在测试时使用断言,而在产品发布时将断言关闭的程序员,就像是在岸上操练时穿着救生衣,而下海时将救生衣脱掉的水手",观点不言而明。在当今硬件设备性能已经很好的年代,断言产生的那些开销多数情况下已经"不足挂齿"。那什么才是决定断言是否继续留在产品代码中的最大影响因素呢?我觉得还是因产品而异。前面说过断言如果出现,就意味着程序里是存在bug的。那我们是尽快让产品bug暴露出来呢?还是在程序已经伤痕累累的情况下,继续让其前行呢?产品继续运行带来的后果是否是可忍受的呢?说来说去,还是一个评估和决策的过程。对于类似对癌症病人做化疗的控制软件来说,如果运行异常,想必及早关闭程序是最好的选择,这可是性命攸关的大事。那对于这类程序,断言是一个更好的辅助提前检查到bug的工具,加入Release版也无妨。在我所在的项目产品中,我们选择了将断言保留在产品代码中,我们希望bug能越早暴露越好,千万不能让系统带着缺陷持续运行下去,这样到后期系统将会出现莫名其妙的甚至无法跟踪定位的问题了,到那时可真就不好与客户交代了。当然断言失败后的处理方式也是多种多样的,做好适当记录,保留好现场轨迹,让子进程稳妥地崩溃退出,有时是可以接受的。

函数 vs.过程
说到这个话题,不免会有些"钻牛角尖"的感觉。使用C/C++的人已经习惯了"函数"的这个称谓,少有人去特意区分函数与过程的差异,或者在工作中花心思去考虑到底应该用函数还是过程。在C/C++甚至很多其他现代语言中,函数与过程没有语法上的差异,如果说有什么不同,那就要从纯语义上去区分。我们从小就开始学数学,大约在初中(有些地区在小学的高年级,有否?)开始了函数的学习。回忆一下数学上的函数是什么样子的,多亏手头上有一本"什么是数学",翻看了一下,数学上的函数大致是这样定义的:"对于变量X的任何一个值,都存在另一个变量U的确定的值与它相联系,这时U就称作是X的函数,记为U = F(X),其中X是自变量,U是因变量"。数学上有很多著名且常见的函数,诸如sin(x)、cos(x)等。按照数学上对函数的理解,一个函数有输入变量(参数),有唯一的因变量(返回值),函数名字根据返回值的含义而命名,如sin(x)。对比一下我们平时在编码中设计的函数,发现似乎不那么一样。因为我们没有严格按照数学上理解的函数去定义我们的函数原型。但在我们开发过程中也不乏符合数学上理解的函数,如标准库中math.h中,诸如:
double sin (double x);
double cos (double x);
double tan (double x);

与函数不同,严格意义上的过程应该是一个没有返回值,但接受任意数量输入、修改和输出参数的。这样综合起来,其实我们在平时更多的是在使用纯意义上函数和过程的综合体 — 带返回值的过程,且命名偏向过程。比如strtol。以下应该是我们常见的两种代码里routine的使用方式,第二种则是一个标准的过程的调用。
invoke_status = sub_routine(var_1, var_2, …, var_n);
sub_routine(var_1, var_2, …, var_n, &invoke_status);  

使用以上哪一种是见仁见智的事情,估计也和组织的编码风格有关系。

分布式编译让你的工作更高效

随着工程代码量的增加,往往完整的编译一次Proj消耗的时间可能足够你喝两杯咖啡了,我现在build一次我所在proj的代码需要5分多钟,这是很痛苦的,颇让人懊恼的。为了解决这个工作中的别扭事儿,我在网上搜寻了一番,找到了distcc这个分布式编译工具。

先看看distcc能帮助我节省多少时间吧。我在公司的一台Sun SPARC Solaris9主机下对整个项目源代码按照以前的编译方式进行了一次build,这次build用了5分多钟;同样我使用distcc编译(安装了两个节点,都是Sun SPARC Solaris9主机),居然只用了1分多钟,试想如何有更多的服务器作为distcc的守候进程主机节点的话,势必编译性能还会有提升。

有了"惊人"结果后,我们来看看distcc的原理,distcc本身是gcc的一个wrapper,也可用作本地编译,但是更多的是其分布式编译的强大功能,简单来说:就是将gcc的编译任务分布到各个其他主机上去,然后再传回来整合。它提高的是gcc -c阶段的速度,链接阶段的速度由于肯定要在本地实施,所以distcc无能为力。另外distcc推荐分布的不同主机上安装的编译器版本最好要一致,否则可能会有意想不到的错误。

distcc的安装和使用方法甚是简单,我安装的是distcc-2.13-sol9-sparc-local,直接在root下pkgadd即可。然后在各个distcc节点启动后台守候进程:distccd –daemon –allow x.x.x.x/16,以普通用户启动即可。

客户端使用方法:
1、在自己的用户下,添加环境变量(如果你用的是C shell):setenv DISTCC_HOSTS 'localhost x.x.x.x',代表本机和x.x.x.x上安装并启动了distccd
2、将你的makefile 中的CC=gcc改为CC=distcc gcc
3、make即可 。同样你还可以在make的-j参数选项,如make -j 12,这样在单机上进行多任务并行编译,使速度更快。
4、如果你想观察各节点上distcc的工作状态,可使用distccmon-text 2 命令查看distcc在各台主机上的任务快照。参数2代表:每隔2秒刷新一次。

Distcc理论上是可以部署在不同平台上辅助进行分布式编译的,但是在异构平台上分布需要一段时间设置和调试,我推荐还是尽量部署在同一类型平台上吧。有了distcc,我们的服务器的计算能力得到了充分的发挥,个人工作效率也会有所提高的,不知道长此下去喝咖啡的机会会不会被剥夺了:)

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats