当东楼撞上西门 “野路子”程序员写的山寨C++的书 《0 bug——C/C++商用工程之道》

当东楼撞上西门

1       “野路子”程序员写的山寨C++的书

2       值得翻阅的地方和不足

3       0bug的卖弄

4       书中的瑕疵和bug

5       别把自己太当回事

 

本人声明,本文的目的就是帮肖先生炒作,以及骗取点击数量,旗帜鲜明参与骂战。但点穴就要点到点子上,一次足够了,没兴趣对战,当然我也给肖先生机会骂回来。

1               “野路子”程序员写的山寨C++的书

本来很早买了这本书《0 bug——C/C++商用工程之道》,大概因为china-pub上推荐(最后买于dangdang,china-pub发货太慢,担心过年收不到),也不知道是否是当时论战导致的推荐。但第一眼没有吸引我,所以先放在了一边。

上上上上上周六无意浏览到了CSDN一贴,大约看完了两边的精彩论战,看着挺逗的,于是熬夜用2天初读了肖先生的书。最后我把部分评价贴给了肖先生,结果当然还是删贴,既然肖先生和我不是同道中人,他有删贴的权利,我也有言论的自由和发帖的地方。我骨子里也是一个好凑热闹骗点击率的人。所以干脆干到底,完整的写出书评来,帮肖先生炒作一下。

 

看完书的感觉是,肖先生强烈质疑的评价,“强烈建议初学者不要买这本书,以免被毒害。这是一位“野路子”程序员写的山寨C++书。”还是非常中肯的,因为本书不严谨(甚至可以说非常不严谨),这种不严谨会非常严重的伤害新手,但是作为反面,老手拿来反刍还可以,因为很多地方老手会会心一笑。野路子和山寨都不是贬义,位字更是尊称了,本书也的确不是学术类型的书籍。这个无比准确的评价,却被肖先生列为罪证,有点可笑也有点可悲。

2               值得翻阅的地方和不足

本着厚道的原则,还是先写值得翻阅的地方,本书的是一个老程序员的总结,虽然我认为作者其实多余OO和C++的理解都有很多瑕疵,但作者毕竟是一个有总结的,在编程规范,debug,统计方式辅助调试,跨平台,安全编程,有过总结。有些观点是可以看看。比如作者文章中间没有涉及无锁技术,但是已经在考虑无锁的优势。有比如作者对为什么要用线程,总结混乱,但在任务池一节已经开始考虑使用状态机的方式避免过多的线程导致不必要的线程消耗;“行为锁”和“资源锁”的比较;设计之中也已经开始考虑。作者的一些总结之话也有精彩的地方,比如”如果你的程序写的不够简单,就已经写错了”,“一个好的习惯,解决整整一个方面的bug”。

本书最大问题是打着C/C++的旗号,本书却很难体现其在OO设计,泛型编程,设计模式方面有什么造诣,说是0Bug,但是书中不严谨和错误地方,涉及了跨平台,但是却对操作系统知识却有很多误解,列举了很多编程准则,却有很多观点经不起推敲。另外,书的排版和章节设置问题也很多。占据大量篇幅的7,8,9章节里面的设计,以及实例代码很难谈得上值得阅读。

3               0bug的卖弄

我声明我不反对这个标题,写书不是标题党也难。但是我反对的是肖先生关于他自己工程中间0bug的炫耀式的举例,比如15万行的代码,最后发现的bug才多少个。其中C/C++才多少个。这种统计,纯属大忽悠,代码的质量是看测试的bug数量是和代码修改量比较才有实际意义。如果你有15W行代码,上个版本测试通过,这个版本改动200行,测试出10多个bug,那是丢脸的事情。不值得炫耀。

另外,肖先生关于的他代码bug统计方法也有意思。70%是内存的bug。我其实挺好奇的,就是初级菜鸟的bug也不会70%问题是内存问题吧,真不知道肖先生开发的业务逻辑是不是都是i++类型的。或者说肖先生的bug极少,所以我等常人无法理解。

小弟财蔬学浅,和肖先生一样从事c++后台开发多年,代码也有完整的框架和重用库,会限制其他开发人员直接参与内存管理,每次提交测试后,每百行修改bug数量大约在0.5-0.8个之间。平常只有5%的bug大约和内存相关,大部分的都是业务逻辑,功能性bug。所以羞愧一下,和人家差距太远。

4               书中的瑕疵和bug

学术用词这个东西,冲突很多,但起码有两个东西要明确,一是尊重传统,二是如果有差异,也请请明细列出来,侯捷先生在这方面由于台湾口语冲突问题,曾被国内少数读者质疑过,其实侯先生对于歧义的名词都有对照表,真算是不错的楷模。而看完本文我才发现,肖先生的在学术用词上发明创造能力才是惊人的。

                                                                                                                                                    表1 肖先生的发明学术名词

发明的词汇

页数

调侃

远堆调用

P28

无非是用堆作为参数传递的方式。。。。

NPI

P55

问题是肖先生还是缺乏战斗精神,为啥没有FPI,文件读写API。MPI,内存读写API出来呢。

多读单写锁

P241

看steven书的可能会有点郁闷。。。。

“静态”数组

P330等

本文很多地方都用了静态这个词汇,但是如果你千万不要和static想到一块了。

死线程

P428

第一次听说这个概念,不知道作者是如何创造的这个东西

 

 

 

 

为什么我说这本书,完全不合适新手读呢,因为肖先生是在写blog(也可能是写bug),不是在写书,写书就必须照顾你的读者,要假设他的知识背景,如果你写给初学者看,你就要涉及背景,对每个细节把握,而且不能在某个主题过于深入。如果你写学术或者教育书籍,就一定要把所有的讲清环境,甚至版本,以及来龙去脉。这既是所谓严谨。其实国人写书严谨的也的确不多。也是国人的一个问题。(当然国人也不是没有写书高人,去年的《程序员自我修养》就非常不错。)

《0 bug——C/C++商用工程之道》在严谨这个问题上的态度是,他是出来打酱油的。

                                                                                                                                                       表2 书中间不严谨的地方

原文

页数

调侃

在32位操作系统,通常把内存分成两个2GB的空间,每个应用最大可以使用2GB私有空间

Linux(浮动栈)一般是10MB                

P26

P98

如果先生只在Windows下干活,我也就不废话,偏偏先生高举着跨平台大旗。

后来看到默认栈大小,我估计肖先生大约是在RedHat下干活的。

线程总数有限制,Linux下一般一个进程为300条左右。

P33

先生为何不说说为啥是300呢,是不清楚还是不知道Linxu有一个ulimit指令。不过好在有个一般做形容词糊弄。

另外我奇怪的是先生的前面说他使用的系统栈大小10M,用户空间默认2G。不是在不理解先生怎么能有300个左右?

COM技术的本质还是实现跨进程的通信而实现自动传参

P71

如果肖先生在COM前加个D还有说的过去。

严禁变量转义

P90

这儿明显不是我们常说的转义。而是多义

处理跨平台设计需求,建议尽量不要使用模板,继承,虚函数等C++高阶特性

P103

自己不懂这些高阶特性可以理解,不要打着跨平台的旗号说。。。如果肖先生有兴趣,去看看ACE的库。

不要使用两个以上的*号

P141

开始我也以为肖先生修炼有道。甚至可以不用scanf类似的函数。

看到下面发现先生同意用&*,我奇怪的是**和*&的区别是?

严禁使用指针参与四则运算

P142

不知道肖先生指的四则运算时哪四个,我很想看看肖先生用指针如何做乘除运算。

不安全的sprintf,还是不安全的_snprintf

P164

snprintf的问题建议大家还是看看网上对于各个平台这个函数的说明。

这个函数(vsnprintf)完全体现了我们的分析结论,即严格的防御性设计,构造100%安全的C语言字符串

P183

稍微有点常识的就知道printf类型的函数是是无法保证类型安全

请大家不要奢望在LINUX下可以自如的使用中文,所有的中文字符原则上都会显示成乱码。

P551

其实我强烈顶打印到屏幕上不要出现中文,但是Linux好歹也是一个操作系统,用不着这样小瞧他把。

发现32位Linux下一个文件的最大一般2GB

P507

一开始莫非先生的Linux使用FAT16文件系统,后来想了想肖先生可能在Redhat下干活,明白了。但是……,肖先生应该百度一下,这个2GB的大小限制是可以调整的。

……

 

 

文中肖先生的错误观念:

                                                                                                                                                             表3 文中的错误观念

原文

页数

调侃

统一使用基于TCP/IP协议的socket作为进程间通信手段

P39

如果世界真那么简单,写操作系统的人倒是可以轻松和下岗了。

Windows检查重复枷锁的漏洞

P45

这不是操作系统不严谨,而是作者的不严谨,请理解锁的概念。另外用信号灯代替一下MUTEX,或者请读一下ACE的实现。

笔者一个函数名称有237个字符

P80

这个事情自己看就可以,说出来容易吓唬大家。

只使用public和private定义,

用聚合不用重载

P102

第一个观点体现了作者的OO水平,

第二个观点除了不用这个观点偏激以外,文章内部说的好像是多重继承。

很多时候,VC这个编译器有一些怪癖,比较突出的就是stdafx.h这个预处理文件。

……

但一定要叫stdafx.h

P119

人家微软为了加快你的编译速度,好不容易实现了预编译头文件,你不知道如何用也就算了,取消不了还怪人家微软。难道肖老师连VC++工程文件都没仔细看看吗。

Makefile的简单写法

P120

这一章都充满着对Mafile的误读。。。肖先生写的那个Makefile真谈不爽简单。其实看了这一节。我很怀疑肖先生的工程在如何进行编译管理的。。。

单写多读锁

P241

对于这个读写锁的效率我保持很大的怀疑。由于这个读写锁的设计中读和写的操作实际使用中要多次使用互斥量。效果可想而知。

一般说来,线程启动时间间隔250ms会比较安全,低于这个间隔,则很可能导致“死线程”的出现。

P428

我不严谨的认为,这99.999%是臆断或者肖先生的程序存在什么bug。从来没有什么文档反馈Windows和Linux平台下的线程有这个毛病。

……

 

 

 

 

5               别把自己太当回事

最后说说另外2个事情。 一是别怀疑别人的动机。二是别把自己太当回事。

当然说了也白说,人家听不进去。或又肖先生已经进化到吧自己当凤姐了,此次粗口开骂也只是出名的一个机会,只是我等迟钝之人看不出来。

鉴于是国人自己的书,而且也有很多心血,野路子有时候对于解决问题的好方法,,我对此书打3星。但仍然不推荐新手购买。非常不建议。

最后还是建议肖老师别再叫东楼,这个字被人用过,而且用过的人……有典故了,于是有了上面的标题。肖老师大概加班太多,没时间阅读了,建议休息的时候看看《明朝那些事》。

 

最近折腾一点私事,本来打算3月初写完的东西,结果4月初都没有写完,本来想撤了,看东楼肖先生那边还挺起劲,又再折腾了一天写完。

 

【本文作者是fullsail(雁渡寒潭),本着自由的精神,你可以在无盈利的情况完整转载此文档,转载时请附上BLOG链接:http://blog.csdn.net/fullsail,否则每字一元不讲价。】

 

19楼 tony_xiao 2012-03-29 13:40发表 [回复]

我是作者马甲!
借贵方宝地坐个广告哈。
《0bug-C/C++商用工程之道》作者已经公开,欢迎大家下载批判性阅读哈。
地址在这里。
http://tonyxiaohome.blog.51cto.com/925273/813229

同时欢迎点评作者和LZ的RP。
18楼 qixinkui2 2011-08-30 21:17发表 [回复]
一边看一边会心地笑,呵呵,0bug老师的事虽然过去了这么久,还是蛮受教的。
早在上海这边听说sails老大的大名,看过一些您的ppt,听过一些同事的侧面描述,对您非常钦佩景仰。在我看来,您恰恰是和0bug老师对立的那一极的人。野路子vs玄门正宗的感觉,呵呵。
部门里做后台的人似乎都倾向于 浅平透的C+数据驱动编程 的TAOUP之道,我个人却也常倾向思考 抽象 OO 模式架构 这些内容,并常常在二者之间彷徨不已。区分本质性复杂性和非本质复杂性,分离技术性框架和领域框架以及具体应用,用什么样的方式以及怎样做,始终未得其道也,也许好的设计的过程就是不停地在二者之间摇摆的过程。

呵呵,问好,希望能在博客上看到老大更多的好文。另有一问:milo是不是您引进公司的,嘿嘿。
16楼 YUAN1125 2010-11-14 23:07发表 [回复]
32bit LINUX内核使用1G的虚拟内存空间吧,应用程序使用3G的虚拟内存空间。线程内核栈有4kb-8kb之间。

LINUX浮动栈是什么意思? 栈的大小应该是3G空间吧(除去应该有程序段之类的东西)。。。

LINUX下线程和进程是一回事,只是fork时候的行为不同罢了。

32bit的Linux和文件系统没啥关系吧。 32bit LINUX的处理文件大小的能力至少也是TB级别的,因为文件索引机制早就由“3级目录”改成了“基树”。
14楼 匿名用户 2010-05-16 02:38发表 [回复]
protected这个问题,见仁见智,Stroustrup说过: “在许多情况下,从继承不会获得任何实际效益,.....类层次结构并不是每个好程序中必不可少的一部分”。另附某人博文,http://blog.codingnow.com/2010/03/cpp_protected.html。
10楼 findsun 2010-04-20 14:32发表 [回复]
统一使用基于TCP/IP协议的socket作为进程间通信手段:
在多节点系统中倒是说的过去,多台主机通过高速网络互联进行通讯。本地用过Domain Socket也是常用的方式。

只使用public和private定义,
Effective C++中有此一说,protected会破坏类的封闭性。

不要使用两个以上的*号
 用*&有一个好处,这个指针的引用必须要初始化。
Re: fullsail 2010-04-21 00:56发表 [回复]
回复 findsun:不好意思,的确这的确不是一篇厚道的文章。[e04]
关于你的的几个问题,
1.统一使用TCP作为进程间的IPC方式,错在不要将这个想法用于普适性,毕竟很多时候我们需要更高的速度。

2.protected的确会破坏封闭性,但是不等于不用,除非将C++理解为带类的C语言。在一个类库中必然要使用protected。

3.**这个是无法完全回避的,C++特性决定了,很多地方还是需要改变某个地址的数据的。

8楼 efishocean 2010-04-19 21:39发表 [回复]

肖先生最新一篇blog还染指工业设备呢。我做的若干评论他竟然全删了。好在最有趣的评论被我截图咯。哈哈 http://blog.csdn.net/efishocean/archive/2010/04/17/5497221.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值