《回首往事:十八年的语言分支》一文后,全民编程计划也算是正式启动开来,其实前几次的文章(详见底部的推荐文章)确实为我们分享出了很多的道理。从中我们看到了语言的“叛逆思想”、从中我们对一些语言有了更深入的认知、从中我们也能体会到身为程序员的各种生活。
肖伯纳有句名言是这么说的‘人生不是一支短短的蜡烛,而是一支暂时由我们拿着的火炬。我们一定要把它燃得十分光明灿烂,然后交给下一代的人们’。我们在之前的文章提到过,每个人的经历本身就一个“瑰宝”,把这些经历分享出来可以让别人得到很多的启示。这次,51CTO的记者邀请到了微软亚洲研究院研发工程师陈梓瀚陈老师来分享一下他在微软生活中的所接触的语言。我们来看一下陈老师能为我们带来什么样“瑰宝”。(他的博客园:http://home.cnblogs.com/u/geniusvczh/)
“初品编程语言”
当每个人第一次接触编程语言时,都会产生或多或少的感触,这很正常,也就是我们常说的第一印象。而我第一次知道有编程这回事时,是在广东汕头华侨中学念初二的时候学校开的课,刚好是这个世纪的第一年。当时学校发了一本前半本QB后半本VB5的教材,书里面有代码,就算是我第一个接触到的代码吧。当时的感觉就是:“真是直观啊。”
再后来我学习编程的过程中,我很少看别人的代码。一个功能的实现往往有很多种,就像一个方程的有很多个解法一样——尽管最后答案只有一个。我觉得知道一个具体问题的解往往是没什么太大的意义的,虽然这是初期重要的积累过程,但过了这个阶段,再纠结这些问题已经对自己的成长没有什么好处了。
在我基本上能用VB表达出自己的想法之后,我就差不多不看代码,而是只看各种原理和API(或类库,以下省略)手册了。尽管当时的代码还很烂,但是只要不断地写,变好只是时间问题。相比之下积累原理和API是更加重要的。
API的掌握
当一个编程人员,经历了从无到有的过程后,如果他对于编程产生了兴趣,他一定希望能够不断进步,达到一个又一个新的高度,我亦如是。
又过了一个阶段后,让我觉得API也变成一件不太重要的事情了,因为学习一个API实在是太简单了。你所需要知道的就是这些东西的存在,就跟看算法导论的时候知道有那么些算法每个算法的好处在哪就够了,等到真的需要了可以去查。当然如果你根本不知道这个算法,那也是不行的——API也是如此。等到学习API的时间已经短到可以忽略的时候,一般就是通过看博客文章微博等方法来知道这些世界上存在很多解决什么事情的API,这些API可能也是属于你从来都没用过的语言的,不过没关系,先放着。
在这段时间里。有空的时候我就不去具体研究每个API的细节了,而是去积累原理。这里所说的原理指的是类似数据结构背后的数学模型啊,或者是编译原理啊,或者做渲染的时候的各种计算方法啊,或者是设计一个语言的语法的时候需要掌握的一些譬如类型系统之类的知识等等。
当然想manage一个API/类库也是需要花上那么一段时间的。但是原理积累的足够多之后,看到一个新的东西,往往可以猜出他API背后的一些东西。只要这个API的作者也是靠谱的,那“英雄所见略同”的事情便时有发生。这就是为什么到了这个阶段之后掌握一个API是很快的,因为如果让你来设计他,那你大概也会设计出差不多的东西。所以这样的技巧就可以大大提升你学习一个新的API的速度,用到哪学到哪,这就仿佛你一开始就掌握得很好。还记得去年,一个在Office部门当过Architect的同事意味深长的跟我说“Architecture is patterns”的内容。正如古人所说,优秀的数学家在理论之间看到了相似,而卓越的数学家在相似之间看到了相似。我想就是这个道理吧。
虽然语法啊、API啊、类库啊、原理啊、架构有很多,而且中间千差万别,但是总的来说掌握他们有两件事情要做。第一件事情就是要知道他们。你可以掌握的不好,你可以完全不去试一试,这没有关系,但是你至少需要知道他好在哪。第二件事情就是要从中看到相似。再说下去估计就变成玄学了,所以就此打住吧,言归正传,接下来让我说说在微软接触到的一些语言吧。
我的微软生活
记得我从实习开始就是在微软里度过的,当时做的是Visual Studio相关的东西,后来转正的时候去了SQL Server,再后来就到了现在所在的MSRA了。
尽管这三个部门做的东西差距很大,但是选择的方法都是一样的——尽量用C#,不行再说。这也不是公司非得推广C#不可,而是因为C#能做【而且能做好】的事情实在太多了,非得用C++才能做得好的事情已经越来越少了。当然或许Windows组不是这么看的,他们觉得WPF和XAML设计得好,就做了一个native版本的轮子来当Metro UI用,还给VC++搞了一个/CX,不过至少在我呆过的地方都更喜欢C#。
至于C#是不是真的那么神奇,我只能说现在像我们的基础设施,譬如Azure和VS等,C#占的分量都远远超过C++的。只要不是特别计算密集型的东西,或者对资源的控制不用斤斤计较的东西,用不用C++的意义已经不大了。其实有些时候多买些机器要比花时间把程序在一些角落里写得好要节省更多的成本,当然前提也是需要有的——得先掌握写scalable程序的方法。
当然这并不阻止我在不工作的时候还继续研究C++的东西。我在上班的时候写公司的代码,下了班开始写自己的代码,其实自己研究项目的难度其实往往要更大,因为自己搞东西不在乎成本,搞不出来可以拖,慢慢研究会了再搞。尽管在微软内部也是差不多的,但是项目毕竟还是有期限的,事情不能做得太天马行空。
我所染指的语言
谈到语言,就不得不提到项目,项目确实是我们在工作中成长的重要因素。每个项目都有自己最合适的语言,只要政策允许,我都会尽量选择最合适的那门语言去学。所以这不是一个选择的问题,一个项目不是你用不同的方法去“选择”一门语言,最适合的语言就会变的。这就跟数学定理一样,一直在那里,只有你发现和没发现的区别。
很多新人认为编程语言的选择是否会对未来的职业规划出现影响,至少对我来说,我认为应该是不太会。因为学习一个语言需要花很长时间的这个阶段已经过了,为我在读书的时候的主题是做编译器,所以各种各样奇葩的语义结构基本上都见过了,所以当接触一门新语言的时候,就会跟上文所提到的一样产生各种“英雄所见略同”的感觉。当然有一些语言的设计者对一致性这种重要的特点是没有追求的——譬如说go,尽管他是Google做的,但这并不阻止这门语言看起来就像很多个补丁黏在一起。
在微软的生活中我重点染指的语言大概有VB、Delphi(前面这两个估计在也不会用它了)、C++、C#、F#、Haskell和Prolog。剩下的其它语言,绝大多数都跳不出这几门语言所能覆盖的范围。此后接触一门新语言的重点就是收集和体验他的一些最佳实践,所以已经不是什么重要的问题了。
其实还有一些其他的语言,例如Go啊,Rust啊,Scala啊,Java啊,Prolog啊,Erlang啊,Perl啊,Lisp啊,BrainFuck啊,JavaScript啊,objc什么的,还有很多叫不上名字的东西,我都会去看。有些语言还在别人那里很流行,至少我现在还用不上。我会去看的原因有两个,第一个就是说不定将来要面临“选择”所以知道的越多越好,另一个就是现在我的兴趣好保留在如何设计一门好语言,如何写一个好的library上面,所以开眼界是很重要的。
当然在这里我并不是提倡语言无用论,我提倡的是,语言有很多,而且不同的项目最适合的语言是千差万别的。所以千万不要试图去相信一个语言是银弹(最近迷信C语言的风气又再一次上来了),我们所需要做的事,把它们统统都学会,那这样选择也就变成一件容易的事情了。而且大项目里面的小项目用不同的语言来写这种事情是很常见的,不能回避。
接触过这么多的语言后,必定会有一个相互之间的比较,也会产生出每个人心中最倾心的一种编程语言,那么你猜我最倾心的编程语言回是什么呢?你肯定猜不到。
我最倾心的Haskell!
之所以上面我会说你想不到,是因为让我最倾心的语言是Haskell,你没看错,的确是Haskell。就像我《伴随我成长的编程书》所提到的一样,我是从Haskell开始才知道掌握程序语言相关的理论是多么的重要。当我逐渐把Monad啊、CPS变换这些看起来跟写代码没什么关系的知识都学会了之后,遇到一个所谓“多范式语言”(特别是C++和C#)的时候,在一个程序的不同的部分使用不同的范式来提高开发效率和可维护性(主要是通过违反多少次DRY原则来衡量的)的这种事情已经不再是一个问题了。
可以说没有Haskell,我就不会知道这个世界上还有lambda calculus,还有类型系统,还有各种各样美妙的知识。尽管对于我喜欢写的大部分程序讲Haskell都不是最好的语言,但是这并不妨碍我喜欢Haskell。Haskell让我对其它语言掌握得更好,特别是C++。
与Haskell相似的东西除了C++的模板以外,我再也找不出别的可以相提并论的语言了。只有这两个东西让我感受到编程语言的魅力。随着硬件越来越牛,将来取胜的程序语言,我在这里斗胆做一下预测,肯定包含两个特征:
1、语言表达能力强,噪音少,各种库一致性高。
2、语言本身要容易分析(指语义上的),这样才能不需要太过于复杂的过程(譬如说分析指针内容的别名这种乱七八糟的事情)也可以产生出很好的代码。
尽管最后的赢家可能不是Haskell,但估计也是差不多的东西。那种不仅学起来难,坑多,而且还很难分析的语言——首当其冲的是C语言——估计会跟Java一样因为有大量的遗留程序而得以保存,但迟早会被边缘化的。不过我想这个时间还很长,因为如何把Haskell编译的更好的这些相关技术还有待研究。
这么说可能有点抽象。如果想理解这方面的东西的话,我推荐一个视频教程集合Channel9:http://channel9.msdn.com。去上面找我敬仰的Erik Meijer关于Haskell、Linq和Reactive Programming等相关内容的东西去看。看懂了之后,就可以把将其他语言的优点强加在自己喜欢的语言上的这件事情,做得更加得心应手了。正如《Monadic Parser Combinators using C# 3.0》这篇文章所施展的技巧一样,当你看着LINQ的代码,眼睛里的不是LINQ,而是CPS变换的时候,你可以把Parser也写成跟LINQ一样的东西。
也许这对大部分人可能没什么用。因为我不管做什么东西,主要的业务还是做Library,所以关注点也好,但跟做App的人的区别还是相当大的。所以尽管有些人觉得“Monad都是些什么乱七八糟的东西反正我学了也不能让我涨工资也不能让我这个项目的加班时间更少”,至少对于我来说,是很有意义的。
全世界编程语言数不胜数,总有一个是你喜欢的,也总有一个语言是你听都没听过的,那么你会想,为什么会有这么多的编程语言呢?有些语言真的有存在的意义吗?
我是如何看待如此之多的语言
很多人认为之所以有这么多编程语言,有工作的需要,但也有一部分是因为每个编程语言都有一些缺点,所以需要另一种语言来进行完善。但是我觉得这种说法有一种“语言都是冲着成为银弹去的”的这个观点在里面。其实这样说是不合适的,譬如说SQL语言,虽然说SQL已经越来越像通用语言了,但是你也只会拿它来操作数据库,的同时你也不会选择其他语言来操作一个数据库。
另一个例子就是Shader语言了,Shader语言是用来操作显卡渲染图形的。做渲染一定会用Shader,而Shader也只会用来做渲染。尽管现在有什么GPGPL的概念,但是只要一涉及到通用计算,大家就不会倾向于选择DSL,在我们的日常开发里面,DSL往往充当一个更加重要的位置。因此我们就有业界良心NVidia公司的作品CUDA,还有VC++2012的一个更强大的实现C++AMP了。
其实还是跟上面所强调的一样,每一个项目都有自己的最好的语言。所以答案很明显,之所以语言这么多,除了作者闲到非要做一个编译器来玩一玩的这种事情(譬如说我,不过我的语言都坑了,有些人的语言就没坑,譬如说ruby之父松本行弘)以外,最重要的原因就是,项目之间的差距太大,所以对语言的要求的区别也很大。一个语言不可能同时满足这么多相差很大的要求,所以就有很多个语言长出来了。因果关系不能颠倒。
既然有这么多的语言,那必定市场上就会出现各种语言从入门到精通的书籍,在我的《伴随我成长的编程书》一文中已经分享了很多自己在实际开发中看过并觉得比较好的书籍,下面我会说说我在实际开发中认为比较好的工具。
推荐完书后我们在谈谈工具
说道最喜欢的工具,那么首当其冲的当然是Visual Studio。尽管我很喜欢搞那些平台无关的东西(这并不意味着我喜欢跨平台),但是我毫不否认一个称手的工具是相当重要的。IDE对我的重要性已经高到我会为我的语言写IDE的这种程度了。尽管我现在写的还不好,所以在可以预见的时间里面我还将继续研究这个事情。别的就不说了,VS写ASP.NET MVC4程序的时候,在一个Razor模板文件里面充满了JavaScript、C#、Html和CSS四种语言。令我感到惊讶的事,尽管这四种语言你揉在一起写,但是Visual Studio的IntelliSense精准而且好用到那四种语言仿佛就是一种。我无法想象要是让我用不带IntelliSense和Debugger的编辑器来搞这些事情那是个什么样子。
当然VS也并不是总是可以完成我想要完成的内容。我有一次还是掉了坑的,就是在我写GacUI(www.gaclib.net)的时候,我给我的类都加上了XML注释,结果发现没有一个工具可以让我用XML注释来给Native C++程序产生文档。微软的这方面工具都是针对.Net(包括C++/CLI)的。所幸的是,VS还是给了我一个读PDB文件的API,尽管藏得很深,但还是Public API。因此我最后选择通过把PDB和XML注释编译出来的一个XML文件拿来join的方法,自己搞定了这件事情。
还有一个我想提到的是,我们都知道因为C语言的宏实在是坑太多了,于是Boost.PP应运而生。但是Boost.PP因为是建立在宏上面的,因此坑也很多,我在大三那一年耗尽了心血都没办法把他掌握到一个可以再复杂情况下安全使用的地步,一怒之下,开发了fpmacro(gac.codeplex.com的项目里面就有,那些扩展名为fpm的文件就是)。fpmacro长得跟宏差不多,但是它是一门严谨的语言,语法是经过精心设计的,专门用来写只能用复杂的逻辑才能产生你的不想人肉写的C++代码。至于我为什么会需要这么一个工具,是因为我经常需要产生跟std::function一样风格的大量三角形特化。
这个故事告诉我们,能自己写工具,才是终极的解决办法。
全民编程
51CTO记者寄语:在语言这块,每个人跟每个人了解的各有差异,而陈老师在微软的成长,更是让他发现了他“独爱”的编程语言,本文中他对于Haskell的讲述更是让我们看到了这门很多人并没有在意的语言它的亮点,并且我们也应该深思一下,自己每天运用的代码是否自己真的了解其原理和机制呢?还只是一种熟能生巧的习惯呢?
网友朋友们,你们又将会有什么样的编成生活要讲述给我们呢?亦或是又会有什么样的语言见解给我们分享呢?这些都会是我们所期待的,就让我们行动起来,一起来参与全民编程吧!