我关于C和C++的一点观点
嗯,我昨天写了一篇《我这一年》,表示最近有点时间了,可以写点博文了,网友们就很热情,马上在回帖中提问,其中有一篇比较引起我注意,就是和我讨论我的书《0bug-C/C++商用工程之道》里面对C和C++的应用比例和深度问题。
应该说,我自己一直定位还是技术人员,我呢,也有兴趣在关于技术方面展开一些讨论,所以我暂时放下准备回复的一些其他朋友们的问题,先回答这个问题。
先立一个大前提,我无意引发语言之争,在我心目中,各种语言无优劣之分,合用的就是最好的,不同意这个观点的朋友,就不必向下看了。谢谢!
原文如下:
肖舸老师您好!
我是一名在校计算机专业在校研究生,一直默默关注您的博客,您所写的东西给了我莫大的帮助,开阔了不少视野。之前买了您的书《0 bug C/C++商用工程之道》,目前阅读了大概2/3,我觉得的书中的内容对我受益匪浅,除了增长了经验性质的东西,也学习了不少实用的以前不曾所知的技术,真的非常谢谢您!希望以后还能出这样类似的好书!
学习归学习,肖老师是业界的专家,而我只是初出茅庐的小鸟,不过我对肖老师书中的个别观点不太苟同。肖老师C语言的功底非常深厚,但是对C++的理解一定不够深,或者说对面向对象的编程不够深(至少在写这本书之前)。肖老师鼓励我们不用多态、继承等面向对象的高级特性,只是把C++当作了一门多了封装特性的C语言,开发方式上仍然是纯面向过程的,这点至少这是本人从书中所看到的,我想肖老师那时肯定没看过关于设计模式方面的书吧,以至总是把C++当做只是多了对象的C语言去用。《0 bug C/C++商用工程之道》中讲解到的基础库,因为都只是基础功能性质的数据结构或库,所以对面向对象的高级特性依赖不多,但是在开发实际应用层面上的东西或软件架构时,面向对象的高级特性能有效降低系统的耦合性,增强系统可维护性。
不过我仍然觉得《0 bug C/C++商用工程之道》是一本不可多得的好书,个人只是不太苟同里面对于C++使用的观点,这个纯属自己本人观点。再次谢谢肖老师,希望能再读到类似的好书!
我的回复:
这位朋友你好,感谢你对我书的关注,关于你的问题,我可以做一点说明和探讨。
嗯,关于C和C++使用深度比例的问题,我同意你的看法,我其实对C++了解并不深入。对于你说的多态、继承等面向对象的高级特性,理解不深刻。设计模式也没怎么看。呵呵,是不是有点失望?
是这样的,我是商业化程序员,从1995年我进入游戏公司,正式成为一个职业程序员开始,嗯,怎么说呢,压力一直在这么多年伴随着我,其中主要就是生存压力。
了解我的朋友都知道,我原来是学习建筑的,计算机软件专业是半路出家,就是因为喜欢,所以我放弃以前国营单位的建筑施工员职务,专门跑到成都一家公司打工,写程序。
这种情况下,我起点比别人低,又要在这个行业里面生存,怎么办呢?
我首先要学习,以获取足够的职业技能,来满足工作的需求,不然就会被炒掉。但另一方面,我也不可能像大学里面的学生一样,系统地学习,为啥?我还得先写出程序来,让老板赚到钱,我也才能领到我的薪水吃饭。
所以,我的学习,我想,社会上很多职业程序员的学习模型,大概都差不多,我归纳就是“用以致学”。即用到哪块知识,就恶补哪块,很K书,多做实验,多掌握一点细节特性,以便立即应用到工作中。
说个笑话,以前我基本上每找到一份工作,都需要恶补1~2个月,为啥,因为工作机会这个东西,只有我将就他,不可能他将就我,如果他需要的知识我没有,我就恶补,然后还要在以后的工作中,边做边学。
这样做的好处和坏处都是显而易见的:
坏处是我没有经过系统的理论训练,对于很多理论上已经定论的东西,不知道,非得自己试验出来,才能深刻了解。实际上,这是走了很多弯路,做了无用功。而且,我在工作中的用词、用语习惯,和很多科班出生的人不一样,大家沟通不容易。
但好处是我们脑子里面没有条条框框,一个语言、一个技术,大家都说好,我未必说好,我喜欢自己来测试,看能不能带到我的工作中有效帮助我,不行的就算了。并且,由于很多试验我不是听人说的,而是自己做试验的结果,所以很多东西很凌厉,实用性很强,对于解决实际工作中的问题,很有帮助。
所以,这个问题我认为见仁见智,还真说不好那个就是最优秀的,科班出身和实做出身,都能成才,也都有混不下去吃不上饭的。你说是不?
但我想有一点是最重要的,长期这么坚持,我养成了一个习惯,就是“实践是检验真理的唯一标准”,特别强调实验法和方法论,很少去人云亦云。结合到我们的软件专业,我也总结出一句话,你看看能理解不:“计算机是检验程序的唯一标准”。
一个程序、一个语言,一门技术,你说好不好,没用,我说好不好,也没用,计算机说了算。我今天有个用户需求,它满足了,并且开发起来多快好省,就是好东东,满足不了,说什么都是假的。这就是我对技术的看法。呵呵,你看呢?
嗯,归纳到C和C++语言上,我是这么看得,两个都是语言啦,它们和其他Basic语言、汇编语言、C#、PHP、Java。。。等等,这些语言来说,并不具有什么高贵之处,任何语言,能解决问题就是好语言。大家觉得呢?
我呢,前期从汇编入行,如果说我有面向过程的情节,我是同意的,对于面向对象,我学了一点,能理解,够用了,我觉得就好了,我毕竟不是语言专家,不需要对一门语言掌握到100分的。只要它能满足我程序开发需求就好了,这中间,还不能产生太大的学习成本,因为我不可能脱产几个月去学习,那不用等我学好,工作就丢了,我也饿死了。呵呵。
但是,后来即使我薪水慢慢增高,已经有条件深入研究C++这门语言的时候,其实我也没有兴趣去研究它了。
我想我说到重点了:为什么我没有兴趣去研究它?
我得说,是开发需求。
长期的程序生涯,我想很多职业程序员都会意识到一个问题,语言不重要、平台不重要、技术不重要、算法不重要、数据结构不重要,所有这些,其实都不重要。
重要的是如何满足用户需求。
在开发中,用户需求千变万化,程序员如果不能够抽象需求的共性,而是疲于奔命地以项目制,就事论事的开发,自己的经验技术没有一个高效的积累,会累死的。
年轻时,我们还可以加班拼命,但是年纪大了呢?也和年轻人一样加班?我今年快40了,这半年加班说实话自己觉得有点来不起了,现在还行,过个三五年,我也加不动了,那个时候怎么办?
这时候我想到了库,即,能否通过对以前工作的归纳和总结,为自己总结出一套高效的、没有多少bug的,可以拿来就用的基本开发库,通过对自己这个库不断地增补、优化、长期维护,来不断支持自己以后的工作,使自己以后的工作越来越轻松,而不是每个工作都从零开始,最后自己累死。
我后期的兴趣主要就在这上面,所以,大家看见了《0bug-C/C++商用工程之道》这本书里面的工程库。
因为我觉得,这个库的维护和精益求精,更能帮助我赚钱,而不是我去把C++语言背的滚瓜烂熟。
这里我也奉劝学计算机软件专业的学子,或者正在从事程序员这个职业的朋友,如果你想在这个行业里面走得很远,走一辈子,成为专家级程序员,最好从现在开始,就准备自己的工程库。只有有了这些沉淀和积累,你才可能平安度过程序员35岁现象,写程序写到60岁去。嗯,这其实是我个人的一个梦想,中国还没有多少60岁的程序员,我想做这种程序员。
总结库不难的,一个人再跨行业,但是软件专业有些通理是不变的,把这些总结下来,不断根据新的需求调整,每次调整力求没有bug,最终,会有一套真正属于自己的库的。
嗯,这个时候又有人说了,“不要做重复造轮子的事情!”,言下之意,只要这个世界上有了现成的库,就完全不必自己做无用功。
不知道大家怎么看,我发现,说这话的,学校里面的学生说最多,我也一直认为,这里面或多或少有点自我解释,有点给自己偷懒找个理由的味道。
原因很简单,以后大家走到工作岗位,面临的机器、平台、需求千变万化,每个库在写的过程中,都是开发者凭想象在预估未来的需求,总有不满足之处,如果一个人,只会依靠现成的库来写程序,嗯,如果有一天没库给你用了,你怎么办?
我不敢想,起码,我自己不敢做这种程序员。
事实上,走上工作岗位的程序员,不多,1~2年,我想一定就会碰到找不到现成库来用的情况。
我的感觉,大多数库在大多数时候都是无用的。
怎么办?自己来咯。
举几个例子吧,就说我最近做实时数据库的问题。
二分法大家知道吧,我想这种算法是高校里面最喜欢研究的,也是库最多的。
我们面临的情况比较特殊,二分法可能查找时间点,可能匹配时间段,也可能去一个数序中模糊检索一个偏移位置,然后决定是否再进一步精细查找。。。。还有很多特殊的应用需求。
最变态的,我们需要二分法给我反三,即最后模糊查到最靠近的三个元素,并论述我们标定的查询条件在三个元素的相对关系。
还有就是我们要求送进去的可能是几种结构体,也可能是一个浮点数表示的时间点,还有可能是一个包容了某个时间戳的一个大型结构体。
还有返回值,可能我们需要一个精确的index,一个反三的报告,或者一个时间段与时间段比较的两重报告。
这些都是应用需求。
怎么办?自己写咯。
最后我们光二分法开发出好几个模块,嗯,而且基本上都是纯C的,没用C++,为啥,这一个纯方法,没有实体数据,我确实想不出有什么封装的必要,面向对象,这个对象的定义如果我没有记错的话,是一堆数据以及其方法的集合,数据都没有,咋封装?
封装一个类,里面全是静态函数?那我还真不如用纯C完成。
还有树,我们玩来玩去,最后做了一个非常奇怪的结构,甚至我们都不知道它算不算树,一个双向链表,上层还有另外一个双向链表,二者每个元素之间还彼此耦合,以便获得检索寻路的最大方便性,大家想象一下火车的铁路桥,有那种加固钢架那种,我们就是那种结构。
这也是自己努力分析了半天,学习了国外很多先进经验之后,定义出来的一套核心数据组织架构,最后证明,我们这套架构比较科学,我写了一套检索算法,自动优选路由,也就300行代码左右,最多遍历40几个块,就能精确定位一笔数据。
这意味着什么?在服务器上,我的cache每秒钟能吞吐125万块左右,除去写入的20万块,我还有100万块地交换能力,除以40,我每秒钟能承接2500路并发查询请求。目前国内外最高的才500,大家觉得我这么写程序,能不能赚到钱?
说到cache,嗯,LRU算法,大家可能学得多了,我想这方面的库很多,但是,我们从一开始就没打算用库,为啥?效率。
所有的LRU算法,基本上都是双向链表,OK,多任务环境下,要不要加锁?不加就崩掉了。
如果用别人的库,我就只能在外面加一把大锁,即每个块被访问时,是排他的,cache同时只能支撑一个块被访问,这么做当然没问题,就是赚不到钱了。程序效率太烂了。
那怎么办?我自己想了一个办法,也做了一些断言和推论,最后让cache自己就变成一把单写多读锁,针对每个块分别加锁,实现了这个需求,这个,可是找不到库的。也就是因为我这么设计,大家以为前面每秒125万块的交换能力怎么来的?呵呵。
嗯,就这么几个例子,大家觉得能说明问题不?
好吧,最后还是要回归到C和C++的讨论,总结一下吧。
我认为,对于语言,学校中的学习需求和实际中的应用需求,并不完全一致。
学校里面是“学以致用”,老师无法预估到大家以后从事何种行业,何种工作,因此,必须把一门语言所有的特性都交给大家,还要考试,因此对于一门语言学习的广度和深度,很好,但是,如何在以后的应用中,巧妙地利用语言的某个特性,来解决实际中的问题,这个没有讲。甚至很多老师自己都不知道。
实际中呢,是“用以致学”,可能对一门语言,一门技术不求精准,特别强调实用性,这个呢,能有效解决问题,但是由于缺乏理论支撑,容易走弯路。浪费很多无用功,很多不必要的加班。
最好呢,是二者结合,即在学校中努力学习,理论掌握尽量扎实,以后到了实际中呢,也不要带着太多的偏见、成见,虚心学习很多别人的窍门、经验、实用技术,同时善于总结归纳,不断形成自己独有的一些开发思想体系,方能成才。
至于把C++当做多了对象的C语言用,没有用到它的高端特性,我想既然这么多年,它担任这个角色挺好,在我库中和工作中,也挺合适,那就让它继续做下去吧。呵呵,不然,我的书就不是C/C++商用工程之道了,而是《0bug-C语言商用工程之道》了。
呵呵。
嗯,这样回复你还满意吗?
肖舸