首页 >程序人生

《程序员的呐喊》读书笔记

2017-12-01 18:21 编辑: suiling 分类:程序人生 来源:代码湾

程序员的呐喊》是Google一位老程序员的经验总结,文中展现了他对各大语言如Java、C/C++、Lisp、Python、Ruby、Perl等的极端观点,比如大力吐槽C++,极力推崇C、Lisp、Ruby。他的观点只是他个人经验所得,也不一定符合实情,仅供参考,有任何想法都可以说出来一起讨论。

1、程序员和司机一样,总是自我安慰说等到需要的时候再去学新技能也来得及。但是在内心深处他们都明白,其实当需求出现的时候就已经太晚了。因此现实情况是这样的,旱鸭子会和水保持距离,司机会绕开泥泞的路段,而程序员会躲在舒适区里,搭建围栏把自己保护起来,然后祈祷世界和平。

me:其实喜欢躲在舒适区里是每个人都或多或少存在的性格弱点,谁能克服它谁就能学到新技能,谁就能站的比别人高。对于偶尔努力经常懒惰的我来说,技术也是学的广而不精,对新技术都有兴趣但学不到精深处,希望刚工作的我可以改善这个弱点。

2、当时04年亚马逊正饱受其庞大代码库的困扰,我曾经一度认为它的代码库失控是因为语言问题,后来才意识到企业文化是主因。首当其冲的是,亚马逊的主流语言里有两门非常哆嗦的语言C++中和Java,外加一门精练的语言Perl。但是Perl正受到排挤,渐渐退出主流。我觉得这是因为Perl程序员能用更少的人力完成和Java/C++程序员同样的工作量,所以要是比人多的话,他们注定是赢不了的。根据我们的估算,亚马逊的代码量比它的功能数量膨胀得更快。第二个因素是,亚马逊的很多技术问题完全可以用自定义领域语言(DSL的方式来解决),比如大规模的查询、分布式计算、产品配置等,他们写了太多不必要的代码了。我后来跳到Google,发现他们为这些完全一样的问题专门编写了强大的自定义DSL。这证实了我心中的疑虑,亚马逊的工程师在这些问题上和无头苍蝇没什么两样。我敢说这句话误伤的概率极低。最后一点就是,和绝大多数公司一样,亚马逊非常抗拒用新语言来解决问题。他们会避免使用表达能力更强的通用语言,比如Ruby或Erlang。他们也几乎从来不会想到自己去写DSL。

me:庞大代码库是很多公司都有的弊病吧,可又有多少能想到用DSL来解决呢。害怕变动、拒绝新技术的公司注定是失败的。

3、为什么C是必修课?
一个原因是现在的电脑都是冯诺·伊曼结构的,而C以精悍的语法展现了冯·诺伊曼机的能力,其他类型的机器也是存在的,比如Lisp机。还有一个原因就是,Unix是用C写的,不仅如此,包括Windows等在内的几乎所有的操作系统都是用C写成的,因为它们全部属于冯诺伊曼机操作系统。你觉得自己还有其他选择吗?至少在操作系统领域里,任何与C迥异的语言都发挥不出硬件的实际能力,至少这句话放在近一百年里都是对的这些系统都诞生于这段时期内。

4、计算机编程语言里没有所谓的“亲近生侮谩“,只有在掌握更优秀的语言前提下,才会懂得怎么批判自己最熟悉的那门语言。因此,要是你不喜欢我批评C++,我建议你去了解一下更优秀的语言是什么样子的,然后你才有资格否定我的话。不过到那时你就不会来否定我了,我忽悠成功了。那时你不会再喜欢C++,可能会有点生我的气,忽悠你讨厌自己之前最爱的语言。所以你还是别管我说什么了。C++很出色,非常优秀。别在意我的话。它是门很棒的语言。

me:作者是有多么讨厌C++啊!“亲近生侮谩“的意思是当你对一个人或事物越亲近越熟悉,你就会越讨厌越忽视TA。而作者认为计算机语言里不会发生这种事情,除非你知道了其它更优秀的语言。我赞同这个观点。

5、亚马逊的伟大元老们只用两种语言:C和Lisp。显然,他们都是Emacs的拥趸。

me:的确很多编程界的大佬都爱这两门语言,比如《黑客与画家》的作者。

6、杰米·扎温斯基曾经写过一篇非常有名的文章来批判Java有多糟糕,但他还是这样写道:“先说好的地方:Java没有free(),我必须承认这一点,其他锦上添花而已。光这一点就足以让我忽视其他缺点了,不管它们有多糟糕。有鉴于此,本文接下来的内容都可以说无足轻重。”杰米的这篇文章写于1997年,那时的Java还在襁褓之中,如今Java早已今非昔比,他当时抱怨的有些东西现在都已经修复了。但也不是全都改好了。就语言层面,Java仍然算不上优秀。但正如杰米所言,它“依然是今天最好的语言,远远比我们在实际工作中用的那些彻头彻尾的垃圾语言要好得多”。不过Java也缺了一些C++的优点,比如(在栈上)传引用、typedef,宏,还有重载操作符。这些东西并非必不可少,但是需要的时候就很方便。对了还有多重继承,说得我都开始怀念从前了。假如你要用我自己的“固执己见的精灵”来反对多态,那么我还可以举出更多为什么多重继承是必需的例子。有时间我们可以讨论一下“火焰剑”或者“盗贼披风”的问题,你就会明白接口是多糟糕的东西了。几年前,高斯林自己也承认,要是有机会重来的话,绝对不会考虑接口。而这正是Java的问题所在。

me:Java好在垃圾自动回收,坏在臃肿不堪,语言本身设计的不好。

7、总之,Ruby对Perl充分实行了拿来主义。Ruby的作者Matz(我没记错的话,他的本名是松本行弘,不过通常都自称“Matz”)甚至可能有点借鉴过头了,连些不好的东西也拿了过来。好在不多,只有一点点而已。基本上Ruby照搬了Perl的字符串处理和Unⅸ集成,语法完全一样,只此一点,Perl的精华就全都有了。这可以说是开了个去芜存菁的好头。接着Matz从Lisp那里吸收了列表处理的精华,从Smalltalk那里拿来了OO,迭代器则是取自CLU,基本上各个语言里的优点都吸收进来了。所有的这些东西被完美地糅合在一起,你压根注意不到斧凿的痕迹。

me:Ruby本质上就是各种语言精华的大杂烩,去芜存菁,作者精通这么多语言的精华非常值得敬佩。现在的框架也是的,都是互相之间借鉴精华,按需索取,无可厚非。

8、Python本来是有机会一统江湖的,但是它有两个致命的缺陷:一个是空白符,另一个是死脑筋。所谓空白符的问题就是Python的嵌套是通过缩进来完成的。它强迫你用特定的方式来缩进,这样大家的代码看起来就是一样的了。可惜,很多程序员都讨厌这个规定,感觉好像被剥夺了自由一样;他们觉得胡乱排版和和编写那种精简到一行没人看得懂的小程序是自己的权利,而Python却侵犯了这一点。Python之父吉多·范罗苏姆之前也出过几次昏招,虽然不如拉里那么惊世骇俗,但也真的是够小儿科的了。比如,Python原本是没有词法作用域的。可问题是它连动态作用域也没有,虽然说动态作用域也有自身的问题,但至少还勉强可以用。Python最早只有全局和局部(函数)作用域,所以虽然它拥有一个“真正的OO系统,可是—个类却连自己的实例变量都没法访问。你只能给每个实例方法带上一个self参数,然后通过self来访问自己的实例数据。所以你在Python里看到一堆self ,哪怕你忍了空白符,这些self也能把你给逼疯了。

me:用空格缩进的确让人不爽,不过提升了规范性。

9、Java 其中特点之一就是凸显了“架构”。Java国王授予了架构尊崇的地位,因为架构完全是由名词组成的。我们都知道,名词就是事物,而在Java里,事物的地位远胜一切动作。建筑是由看得见摸得着的事物构成的,譬如高耸入云的庞然大物,又如用棍子敲打时发出低沉悦耳声音的东西。Java国王特别喜欢这种沉闷的声音,每次换新马车的时候,他都特别喜欢从踢轮子中获得快感。不管上述的儿歌有何瑕疵,它就是不想要任何东西。
me:的确,Java最让人受不了的就是一堆架构,一层层封装致死,调试起来也麻烦。

10、福勒告诉我们所谓重构,就是通过迭代,将恶心的代码变成优质代码的艺术和科学,是能妆点代码却不会在操作过程中产生破坏的算法,而且正确性都是能证明的。

me:作者认为福勒写的重构这本书非常不错,值得一读。

11、那么这些代码一开始是怎么变烂的呢?首先当然是由于过早优化造成的,为了避免重复计算而保存了太多的中间变量。因为害怕方法调用会造成虚幻的负担,而刻意回避编写短小的函数。我们还弄出一大堆类的继承关系,仅仅是为了想象中可能存在的复用,为了避免分配器对象而弄出一个巨大的参数列表。滥用null,把它当成成具有语义的符号。放任简单的布尔逻辑表达式变成错综复杂、无法阅读的浆糊。不用访问方法来封装数据结构。还有其他很多乱七八糟的问题。正是因为各种各样的小错误别类,加以命名,并归类成严重错误。me:这是福勒重构这本书告诉我们的。

12、那我们的代码是怎么变成那样的呢?因为写得烂。这时重构就能救命。再优秀的设计也会出纰漏,但我们仍然可以补救,反正有自动化的奴仆来帮我们修复这些:小问题。它们不知疲倦,我们只要点个按钮就行了。既然如此,谁能离得开自动化重构工具?还有谁能协调Java那些数以百计的小腿,让它们像毛毛虫一样统一行动呢?让我来告诉你答案:Ruby是蝴蝶。(意指Ruby是完全不同的物种,Java中自动化重构工具所要解决的问题在Ruby中根本不存在。)

me:作者喜欢Ruby,觉得Java需要重构是因为代码写的烂,要是用Ruby写的话根本不需要重构,也就没有自动化重构工具。

13、首先,再垃圾的语言和技术也一样有机会赢。甚至赢面可能还会大一点,因为改正起来会更快。Java击败了smalltalk , C++击败了Object-C,Perl击败了Python,VHS击败了Beta,诸如此类。并不是说一项技术(特别是编程语言)比较优秀,它就一定会胜出。营销才是关关键。追求公平竞争只会导致你的语言无人问可津。

me:原来一门语言的流行起关键作用的不是这门语言有多优秀,而是它的营销做的有多好。嗯,我记得Java就是营销搞起来的。

14、注意,骂谁也不能骂Python。相反,骂Ruby骂得最凶的人可能就是Matz自己了。他在自己的演讲“为什么Ruby很烂”里,自陈了Ruby的各种问题,当时看得我汗都下来了。不可否认,任何语言都有缺点。相比之下,我更喜欢Ruby众的坦诚,Pyhon那种一味指责别人,回避问题,过分地自我标榜的行为令人感到恶心。

me:作者的意思是Python众狂妄自大,而Ruby相对比较坦诚,这是作者通过经过逛两个社区得出的结论,也不一定准确。

15、Ruby谈不上有多出色,但它现在手上有杀手级应用。Rails对推动Ruby起到了巨大的作用。在Web框架方面,Python可谓输得一败涂地。号称要和Rails竞争的Python框架至少有五个:Pylons、Django、TurboGears、Zope,还有Subway。其实3个(甚至4个)都嫌多啊。从营销的角度来讲底哪个比较优秀其实根本不重要,重要的是Python社区应该选中其中一个后全力鼓吹;否则每个框架都只只能分到20%,结果谁都没有实力跟上Rails的步伐。
me:再一次吐槽Python在web框架方面的不足,话说Python有杀手级应用吗?

16、Java并没有提出什么新鲜的东西,它有的SmallTalk早就有了。

me:这种论点好像在哪里听过。

17、相反我却亲眼见识了日本服务生为了满足那些在商务旅行中的醉汉所作出的努力,他们的敬业程度让我这个美国人都感到羞愧。如果要问世界级的服务水平是什么样的,来日本看看就明白了。

me:真的吗?真的吗?继续学日语,好去日本玩……

18、最终让Java平台占领了那些它做梦也没想到过的领域,一切都亏了这个所谓的“杀手级应用”Applet。

me:不会吧???没听说过Applet这么厉害,一直觉得它是鸡肋。

4

程序员需要了解的是哪些数学分支?

1、实际生活中,计算机科学家常用的数学和上面那个列表几乎没有重叠。其一,小学和中学里教的绝大部分数学都是连续的,也就是实数上的数学。而对计算机科学家来说,95%有趣的数学都是离散的,也就是整数上的数学。

me:程序员所要解决的数学问题一般都是离散数学,其中最有用的课程应该就是组合数学和概率论统计。

2、除了概率论和离散数学,其他数学分支也是有助于程序员的。可惜除非你去辅修数学,否则学校是不会教你的。它们包含了:
(1) 统计。我的离散数学书里讲到了一点。但是统计是一门完整的学科,而且是非常重要的学科,重要到根本不需要额外介绍。
(2)代数和线性代数(比如矩阵)。线性代数应该紧跟在代数后面教。它不是很难,而且在很多领域都非常非常有用,比如机器学习。
(3)数理逻辑。
(4)信息论和柯氏复杂度。信息论(粗略地讲)主要是关于数据压缩的,而柯氏复杂度(同样粗略地讲)则是关于算法的复杂度(比如最小空间是多少,需要多长时间,程序或者数据结构有多优雅等)的。它们都是好玩,有趣,实用的学科。
当然还有其他的分支,而且有些学科互有重叠。但重点在于:对你有用的数学和学校觉得有用的数学是非常不同的。

3、微积分的本质就是连续一变化的速度,曲线下的面积,固体的体积。很有用,记忆和很多烦琐的步骤程序员通常不需要这些东西。知道大致概但是需要大量的概念和技巧就可以了,细节方面等到需要的时候再查也来得及。

5

编译器,你懂吗?

1、我在招人的时候有一个诀窍。就是在寻找优秀的软件工程师“通才”的时候,通常在简历上你可以看到到各种让你觉得不行的关键字和词,但“编译器”是我唯一感兴趣的词。

me:作者强烈要求程序员学编译器原理,你还记得吗?

2、编译器会接收一串符号流,根据预先定义好的规则,分析出这串符号的结构,然后把它转换成另一串符号流。是不是很笼统?的确是。一幅图片能不能被当成是符号流?当然可以。它可以是每一行像素所组成的流。每个像素就是一个数字。每个数字就是一个符号。编译器当然可以转换图片。英语可以被当做符号流叫吗?当然可以。规则或许会很复杂,但是自然语言处理的确可以被看成是某种很炫的编译。

  1. 编译过程中第一个大阶段就是解析,即把输入的内容变成一棵树。中间要经过预处理,词法分析(也叫单词化)然后是语法分析和中间代码生成这几个步骤。词法分析通常是由正则表达式来完成的。语法分析则是根据语法完成。你可以采递归向下(最常见)或是解析器生成器(在小语言中比较常见)或是更炫的算来实现,只不过相应的执行速度也会慢一点。无论如何,最后的结果通常都是某解析树。
    第二个大阶段是类型检查。这是一群狂热的学术分子(包括他们的组织以及或者手下的研究生)他们自信可以写出非常聪明的程序,能分析出你的程序想干什么,并且在你出错的时候帮你指出。不过奇怪的是,他们并不觉得自己是在研究人工智能毕竟人工智能界已经(明智地)放弃确定性的方法了。
    第三个阵营是代码生成,他们通常都被边缘化了。只要你对递归有足够的了解,知道自己的祖先不是亚当和夏娃,那么代码生成还是挺直观的。这里要讲的其实是优化就是那种生成足够正确的代码,让绝大多数用户都意识不到有问题的艺术。等等不好意思,这是亚马逊化。优化是指根据你那些昂贵的菜鸟程序员写出来的垃圾代码生成“正确”代码的艺术。

6

保守派和自由派,你属于哪派?

1、软件工程有自己的政治轴心,—端是保守派,另—端是自由派。

毕竟“保守的”这个形容词基本上和谨慎、厌恶风险就是同义词。金融上的保守主义常常(也是显而易见的)和年龄以及财富联系在一起。公司会随着时间逐渐变得保守起来,因为它们熬过过了各种法律诉讼、技术失败、公共危机、金融风暴等危机。连蚂蚁和蚱蜢的寓言故事都告诉我们寒冬将至,要储存食物。
本质上,保守主义就是风险管理。
同样自由派的观点常常和年轻、理想主义、天真无邪联系在一起。在企业里,创业公司往往是典型的自由派,一部分原因是他们本来就是为了(在一定程度上)改变世界而存在的(而自由主义原本就意味着变化),另一部分则是他们必须全力以赴完成投资人设定的目标,所以放弃一点软件安全也就变得合理(不得已)了。

me:保守派,尽量修复所有bug,回避错误,学不会新语法,通过编译器安全检查,数据必须遵循事先定义好的格式,公共接口必须严格建模,生产系统里绝不允许存在危险过有风险的后门,安全性有疑虑就不能上线,快比慢好,注重性能。自由派则相反。

2、各大语言的分派:(作者自己使用语言的经验,仅供参考)
难以言喻的自由:汇编语言
极端自由:Perl、Ruby、PHP、脚本
非常自由:Javascript、VB、Lua
自由:Python、Common Lisp、Smalltalk/Sqeak
温和自由:C、Object-C、Schema
温和保守:C++、Java、C#、D、Go
保守:Clojure、Erlang、Pascal
非常保守:Scala、Ada、Ocaml、Eiffel
极端保守:Haskell、SML

3、(1)Facebook是极端自由的。他们主要用的是C++和PHP,他们的数据都放在memcached里:只有键值对,没有数据库结构。他们把数据导出来放到一个后台Hⅳe数据仓库里,然后用Hadoop来进行离线数据分析。每两个星期左右他们仍然会举办通宵黑客马拉松,反正他们的程序员大多都是单身男青年(至少我上次去参观的时候还是如此),股票的估值也还很高(我上次查价格的时候好像已经没那么好了)。作为一家公司,Facebook是非常紧密的,具有很强的执行力,十分注重程序员在网站上发布新功能的单兵能力,没有什么官僚主义。这对一家规模这么大、用户那么多多的公司来讲是难能可贵的。保守派毫无疑问会厌恶蔑视他们。但是Facebook证明了不管具有什么世界观的程序员,只要联合起来,就能解决很多问题。
(2)Amazon是自由的。
(3)Google是保守的。开始是有点自由的 ,然后就变得越来越保守了。只有在刚刚开始的时候才是软件自由的,那时候的搜索引擎是用Python写的。随着公司不断壮大,他们很快就转向了软件保守主义,而这完全是由工程师自己主导的。他们写了很多宣言警告太多语言所带来的危险,而仅有的几门语言里,也里,也有严格的风格指南,限制使用那些端保守,险”或者“难以阅读”的语言特性。
(4)微软是难以言喻的保守。


搜索CocoaChina微信公众号:CocoaChina
微信扫一扫
订阅每日移动开发及APP推广热点资讯
公众号:
CocoaChina
我要投稿   收藏文章
上一篇:程序员上下班途中都在想什么
我来说两句
发表评论
您还没有登录!请登录注册
所有评论(0

综合评论

相关帖子

sina weixin mail 回到顶部