回复几个问题

这几天写了两篇博客,很多老朋友关切,问了一些问题。

比如说,怎么又有时间关心技术了?是不是没那么忙了?我说,其实一样的忙,只不过兴致所致,牺牲一些休息时间罢了。说不定一个猛子扎下去,又是长时间潜水。

再比如说,怎么还在搞C++?我说,我没搞C++,一直以来都是C++在搞我们,我只不过发表一点被搞以后的感想。

有人问,你要讲的那三个C++特性,网上资料一大堆,你就免了吧。我说,如果我有时间,我会写的跟网上所有人的写法都不一样。比如说,讲 function/bind/lambda/closure,我会从 callback 讲起,回顾一下 C++中的 virtual function和成员函数指针,MFC中的message mapping,Borland C++Builder中的event handling,WTL的 CRTP 模拟虚函数,然后谈谈为什么 Java 需要加入 inner class,为什么C#把 delegate 作为first class citizen,以及 Qt 是如何用 meta-object 系统打造出迄今为止C++最漂亮的GUI框架,以及所有以上一切,在简单的 C 前是多么的多余和废柴。比如说,如果讲 rvalue reference,我会从孤魂野鬼似的匿名临时对象讲起,从 const T&,讲到 RVO/NRVO,说不定还会触及 expression template。

但是,我知道我没那么多时间来把这些东西都写下来,写下来也用处不大。这些东西已经不是今天技术的主流。“why”现在越来越不重要,“how”压倒一切。

“既然如此,你怎么还在鼓吹C++的那些奇技淫巧?你没看到C++已经越来越边缘了吗?”

这个,得容我自辨几句。

首先,我现在只有在业余时间看看技术,所以当然选自己最熟悉的领域。

其次,我不认为C++就没有用武之地了。C++会长期存在下去,而且在一些特殊的领域里仍然充当主角。比如,我们不应该小看 Qt 在移动开发中的发展空间,而在一系列我称之为“对抗性应用”的领域,C++还将占据优势,直到出现真正的替代者——肯定不是D,比较有希望的是Go。只是希望Rob Pike老人家坚持到底,不要跟当年plan 9一样,easy come easy go.

第三,最重要的,我鼓吹的不是奇技淫巧。相反,我可能比那些没学过C++或者被C++难倒的人都更讨厌C++中那些奇技淫巧,因为它曾浪费了我大量的时间、精力和热情。

为了讲清楚这个问题,我得谈谈C++的风格,这个老掉牙的话题。

上周末跟老朋友聚会,谈到技术的时候,有一个共识,软件开发方面真正有价值的进步,应当是有利于用户、有利于项目管理、有利于解决领域问题,而不是有利于程序员。多年以来,主流语言和系统的很多改进,其目的都是为了让写程序的人感觉更爽,而与用户、管理和解决问题毫无关系。C++在这方面是带了一个很坏的头,又要追求强大的表达能力,又要追求不打折扣的效率,结果搞出一大堆诸如操作符重载,template meta-programming之类的东西。老实讲,我也觉得:

Matrix4f a, b, c; c = a * (b – a);

要比:

Matrix4f a, b, c; c = a.mul(b.sub(a));

更清爽,但是就算是第二种形式,又能怎么样呢?无非多敲几个字而已,能有多大不了的事?哪个合格的程序员敢说无法理解?可为了让程序员的视觉更清爽一点,C++花了n年时间,弄出来一大堆奇技淫巧,再与之前之后诸多特性相互干扰,复杂度成倍增加,

有人可能会跳出来反驳说,如果表达能力不重要,那么你干脆回去写汇编好了。

所以我得把话说全了。程序的表达能力,只有在反映了其抽象能力的提高时,才是重要的,否则就是自娱自乐。

抽象是程序开发的全部意义所在。之所以C比汇编是一个伟大的进步,是因为C建立了一个机器抽象,把诸如寄存器、cache、寻址方式、位对齐之类的细节都透明掉了,由此而带来的表达能力提升,当然是伟大的。但是你看看上面我举的那个例子,有抽象层次的提升吗?没有!有的只是YY暗爽值的提升。这种表达能力提升,如果得来全不费工夫,当然也无伤大雅,如果是呕心沥血,伤人一万,自损三千,窃以为大可不必也。

软件搞了60年,我认为真正被实践证明了的抽象,一共有四个半,分别是:

1. 机器抽象,或者称语言抽象,构造一台新的计算机或程序语言,使其能理解领域特定的语言,从而最妥帖地解决问题。这是最有力的抽象,是软件开发中的“火箭科技”。

2. 过程抽象,把一件事情看成是一系列嵌套和串接执行的标准化过程的总和,就像流水线一样。这是极为有力的抽象,因此C语言无所不能。但是层次偏低,规模增大以后带来一些挑战。

3. 函数抽象,最玄妙的一种,这个我不多说,有兴趣的去看 Structure and Interpretation of Computer Programs.

4. 面向对象抽象,把一件事情看成是一组各负其责的对象彼此之间相互收发消息,根据消息相互协作完成工作的过程。这个抽象也极为有力。

4.5 僵化的面向对象抽象,把世界看成是由层次分明、庞杂万端的类型体系“实例化”而出的对象组成的,把事情看成是这些对象之间互相收发消息、协作而成的过程。

问题出在这最后一个抽象上。由于面向对象早期的主要应用场合是 GUI 和仿真,是特别适合于建立类型体系的应用领域,结果人们误以为这种抽象模型可以应用于所有领域。成长于这个时期的C++受了这种思想的毒害,建立了一个极其严苛、吹毛求疵的类型系统,自以为这样可以在编译时发现更多错误,没想到其结果是在编码时和运行时引起更多麻烦。动态面向对象语言的实践已经证明,所谓没有严格的类型检查就无法有效地发现错误这一说法,在今天这个时代已经不符合实际了。

事实上,后来的实践表明,拿静态的类型系统去套多姿多彩、变化万千的现实世界,纯粹是人类的狂妄自大。除了在少数几个完全是人造出来的领域(典型的就是GUI,什么窗口、控件、菜单…,完全是人自造的)还是可以的,在很多其他领域则是无力的。所以只能算半个抽象。

C++就是被这个半吊子抽象所害,以至今天,积重难返。至于用template泛型去放松类型的约束,实属亡羊补牢。template可谓毁誉参半,其中的精妙之处固然令人激赏,其中诡异无聊之处也令人愤懑。现在boost和其他一些C++库之中,把template舞得虎虎生风,我也不知道抽象到几天云外去了,但是仔细看来,往往是自取其乐,跟实际效果并无干系,反而有碍管理与交流。

无论如何,C++已经走到了今天。作为一个提供了较强抽象能力,同时性能又不打折扣的语言,还是不失其地位。

以上是个人观点,仅供参考。

猜你喜欢

转载自blog.csdn.net/myan/article/details/5884695#comments_22517399