【翻译】我为何爱读代码?你为何也应当爱?

我为何爱读代码?你为何也应当爱?

原文:Why I Love Reading Other People’s Code And You Should Too by Alan Skorkin

翻译:Yurii

我恨读代码

我发现,许多程序员都讨厌读代码——拜托别掩饰了,承认吧。差不多每个人都喜欢写代码——写代码乐在其中。可是,读代码真是不容易,而且还很烦人,又无可逃避,其他人写的代码总是很垃圾(即便不说,我们心里也这么想的)。即使自己写的代码,过几个小时再看也有点垃圾,过的时间再久点,就更垃圾了。那么,还有什么理由去看别人的蹩脚代码,而是不自己写几手漂亮的?能不能暂且忽略这个问题,花上几个小时看别人的代码,再回头来看自己的是不是还那么漂亮?即便有位大师坐在你面前,如果你不能从他身上学习,你永远也成不了大师。办法之一就是找到这么一位大师,让他手把手地教会你全部知识。有这可能吗?——当然有,只是很难遇到这顶好的运气。不过你也不必奢求那么幸运,做程序员这行就很幸运,因为大师们的所有思想和技艺都凝铸在他们的代码里,供我们学习。你要做的只是阅读代码——当然,如果有人给你一点点地讲肯定更节省时间,但这基本属于痴人说梦。换句话说,要相当个好木匠,得仔细研究大量的精美家具。

我热爱读代码,我总是直观地认为读代码的收获很大,没错,它可能有点讨厌甚至烦人,但你的收益绝对大过这点麻烦。举个例子,你要当大作家,是不是只关心自己写东西就够了?你可以试试看,但是估计不会折腾不出什么名堂。公认的事实是,多数大作家都是会如饥似渴大量阅读的。想写出好的作品,必须先阅读其他大作家的作品,吸收不同的风格,了解他人的尝试,然后才可以培养自己的创造力。这样,你的知识才能逐渐积累,最终你写的东西才有几分成熟,你也才会找到“感觉”。写代码也是这样,如果你不去阅读那些伟大的代码,怎么可能把程序写的漂亮?阅读伟大的代码之于程序员,就如同阅读伟大作品之于作家(我不敢掠美,这句话是Peter Norvig(译注:Peter Norvig是著名的Lisp程序员,现任Google研发总监)说的,他可不是个简单人物,所以好好记住这句话吧)。

即使上面说的你都不信,但有个事实无可否认。要想当个称职的开发人员,能熟练阅读代码是非常重要的。如今,只要不是闹着玩的项目,都是团队协作的成果,所以总会有这样的代码:它不是你写的,但你必须跟它打交道,去修改,或者去扩展。于是,阅读代码很可能就是你身上最重要最常用的能力了,咬紧牙关练好这门本事吧——而且,要快。

要像…会读代码的那些家伙一样…阅读代码

我都说不清有多少次见过这样的事情了:程序员把一段不熟悉的代码上下拖动,几分钟之后仍然一脸迷离。不久他们就宣布,这段代码根本没法看懂,更不必浪费时间了,可以想办法绕过这个问题。我不知道他们真正要做的是什么,一点点弄明白这段代码的意思,还是睁大眼睛等着开窍?阅读代码不靠成年累月死盯着看,你要做的是弄懂它,把它变成自己的。下面说的是我用的一些技巧,但不是全部,不过我觉得这些非常有用。

看代码看到目光迷离

1. 尝试亲自构建和运行程序。通常这一步很容易做到,比如你看的是真正运行的工作代码时(而不是不知来源的古怪代码)就是如此。不过也不是每次都很容易,如果不能很容易地构建和运行,你可以在完成构建和运行的过程中,认识到代码的高层结构。而且,阅读工作代码,你会非常熟悉如何构建项目。构建通常是复杂的,但是了解构建过程,知道代码是如何变为可执行程序的,会大大加深你的理解。

2. 别死盯细节。读代码要做的第一件事,是找到对代码的结构和风格的感觉。开始应当浏览,并且努力找出各部分代码都在干什么。这样你能熟悉整套代码的高层结构,也会明白你正在看的是什么样的代码(重构良好的,还是乱成一团的)。这时候你要做的就是找到入口(可能是main函数,也可能是servlet,controller之类),看看下面的分支是怎么展开的。这一步不要花太多时间,你对全部代码更熟悉之后,随时可以退回来。

3. 确保理解所有构造(construct)。除非你非常精通这门编程语言,否则多半还有些东西是你不知道的。在概略了解代码的阶段,要记下每一个不熟悉的构造。如果这样的构造有很多,下一步就不言自明了。如果搞不懂代码行为的意义,你什么也干不了。即便你不熟悉的只是少数构造,仔细观察推敲没准也是好事。你可能会找到一些以前不知道的关于这门编程语言的知识,我就很乐意为此花上几个小时。

4. 待熟悉了大多数构造之后,就可以搞几次随机的深入探查了。做法类似第2步,快速浏览代码库,但是这次要随机抽几个函数或者类,一行行地看下去。真正的考验现在才开始,但你的收益也是从这一步开始显现。主旨是:真正深入到你所阅读的整套代码的概念体系(组件结构)当中。这又是一个速度快不起来的步骤,但是在这一步,一定要尝试深入理解若干繁杂的细节。和第2步一样,在这一步,每次你多了解了一些上下文再回头看看,你的理解就更深入一些。

5. 前几步中肯定还有你不明白的地方,现在最合适的就是跑几个测试,看看已有的测试。测试很可能会大大打消你的疑惑,加深你对所测试代码的理解。我时常不能理解,为什么有些开发人员在阅读和理解代码时,忽略严密而精巧的测试套件。当然,也有时候是因为没有测试程序。

6. 如果没有测试程序,这时候就该写上几个。这样做有很多好处,它会加深自己的理解,它可以完善整个代码库,在阅读代码的时候也在写代码,这样对已有代码和你都有好处,你也可以真正动手参与进去。即便有现成的测试程序,为了加深自己的理解,你也可以再写一些。测试人家的代码,一般要求换个角度思考,之前你感到迷惑的概念也会变得更清楚。

7. 把弄不懂的部分拿到单独的程序中来。我发现,读代码时这样做,哪怕只是为了调节阅读的节奏,也是非常有乐趣的。即使你不理解代码的底层细节,也可能会对代码的功能有些高层面的想法。那为什么不把一些功能抽到单独的程序中测试呢?如果只运行一小段程序,debug就容易多了,而且这样的过程反过来又会加深你的理解。

8. 代码很乱(dirty)很糟糕(smelly)?那么重构吧。我可不是建议你把整个代码库推倒重来,但是重构一些部分确实可以让你的理解更上层楼。一开始要做的是把你明白了的功能变为独立的函数。在你真正理解之前,重构之前的函数只是看起来没问题,而重构可以把它们变成你想要的样子。依靠重构,你可以把代码变成自己的,而不要全部重写。好的测试程序可以帮上忙,不过如果你没有,就一边测试一边重构吧,而且只改动那些你确认弄懂了的功能。即便测试看起来太少太不完善,也要相信你自己的开发水平,有时候你只管大胆尝试就好(如果确实需要,总是可以回退(revert)的)。

9. 如果上面说的都不管用,就找个同伴跟你一起读代码。能从读代码中受益的可能并不只有你一个人,所以不妨抓住其他人,一起阅读。不过别找专家,他们给你的解释都是高层面的,这样看代码时注意的那些细节就都被忽略了。如果找不到人一起阅读,你又实在看不懂,有时最好的办法就是问别人。可以问你的同事,如果你在读的代码是开源的,也可以在网上问问其他人。记住,这只是最后的办法,不要一开始就这么做。

如果时间很紧张,短时间内必须弄懂某些代码,上面的步骤中只能选一步,我会选择重构(第8步)。你可能没法明白太多东西,但你肯定可以理解真正动过的部分。无论时间是不是紧张,你要记住的是:如果你第一次接触重要的代码库,肯定不能一下子就看懂,甚至不可能很快看懂。你可能需要耐心读上几天,几周甚至几个月——坦然面对就好。即便有专家坐在你身边,也省不了太多时间(我写的关于教和学的系列文章最后一篇就会谈这个问题)。如果你读(或者写)代码的耐心足够,方法得当,你肯定能成为对项目所有方面都非常熟悉的人,也是大家对代码库有问题时出面解答问题的人。你也可以不阅读代码,选择成为那个总想找人来解释的家伙。我想要做哪样的人,我自己很清楚。

抓住阅读代码的机会,别错过

我们都喜欢新写代码,它的诱惑力在于,我们能搞定问题。起码,这次搞不定,下次可以搞定。真相是:你在实践中不断提高,永远不可能一下就彻底搞定。这就是新写代码的价值所在,你在练习,你的水平在提高,但是阅读和改动其他人写的代码也很有价值(至少不亚于自己重新写),从中你学习到的不光是有价值的技术知识,还有关于整个工作领域的知识(毕竟,代码才是文档的最终形式),这种知识通常更有价值。

每一段不遵循传统的,莫测难懂的代码,都是有价值的。你知道我说的是什么,虽然它看起来一团糟,但本意并非如此(也可能因为它是Perl代码:))。每次我看到这样的代码,我都这么想。不妨把阅读它当作猜谜游戏,想想你能学到什么。是的,这很折磨人,但必须承认,你也希望能动手就能写出这么糟糕的代码。如果你花时间阅读这样的代码,你肯定更可能写出这样的代码——这倒不是说,你一定会写这样的代码,但你肯定希望自己能够。最后要说的是,态度总是非常重要的。如果你把阅读代码看作闲杂事,那它就是闲杂事,而你肯定会逃避,但是如果你把它看成机会,事情就不一样了。

朝三暮四,还是朝四暮三?

朝三暮四是个老典故:古时候宋国有个人养了一群猴子,早上喂它们三颗果子,晚上四颗,猴子就恼怒;如果改成早上四颗,晚上三颗,猴子就高兴了。小时候听了这个故事,总觉得猴子太傻:反正每天都是七颗果子,何必在乎早晚呢?长大了做许多事情也是如此,反正总量不变,朝三暮四还是朝四暮三,只有时间的差别而已,想找出什么分别都是徒劳,还不如索性从容点。而且,许多人的潜意识里似乎也这样认为的,至少争辩起来,许多人都会这样反驳,典型的句式就是“反正……,何必呢?” 可是,我又逐渐发现,有些事情似乎不是这样的。

就从生活的小事说起吧:现在物价飞涨,当过家的人都知道,有些菜简直是一天一个价,许多事情就不再是“早晚一样”了,能赶早的就得尽量赶早,否则,拿同样的钱,就买不到同样多的菜,要买同样多的菜,花的钱就不一样。换句话说,在迅速变化的形势面前,朝三暮四还是朝四暮三,就不再只有时间的差别,而是有了实实在在的不同。

而且,即便不是在迅速变化的形势下,朝三暮四和朝四暮三,也可能存在真正的分别。还是拿我自己当例子,我生活还算规律,晚上一般十二点左右睡觉,早上六点半起床,之后要锻炼、读读书、收拾收拾,八点多出门上班,时间充裕,动作从容,自己也比较满意。可是有一天,周老师跟我说,晚上早点睡觉,早上早点起床,这样可以做的事情多得多。开始我并不相信,抱着怀疑的态度尝试了几天之后,发现果然如此。可是,这是为什么呢?我仔细思考之后,终于找到了原因:我自己习惯每天要认真读点书学习点资料,大概是每天2小时左右,以前因为早上六点半起床,留给看书的时间大概是二十到三十分钟,刚刚进入状态,想清楚几个题,就得去忙别的了。提早到五点半起床之后,留出来看书思考的时间就多了很多,夸张点说,可以很从容地安排两节自习课。相应的,晚上不必看那么长时间的书,也更容易保持清醒的头脑,效率也高了不少。看来,“朝三暮四还是朝四暮三”的道理,也可以用在学习上:相比之下,“每天学习xx小时”这样的目标,还是显得太粗了,更细致更妥善的安排,完全可以收获更好的效果。

前些年我读冯仑先生写的《野蛮生长》,也见到了道理:年轻的时候,到底是多玩乐一些好,还是多积累一些好?对这个问题,他似乎并没有给出明确的答案,如果一生中用来积累的总量和玩乐的总量差不多,年轻的时候多积累一些,虽然看起来玩的少了点,但年纪大的时候收益更多一些,玩起来的后顾之忧也少一些;如果年轻的时候玩得多一些,老了就得花更多的精力补上积累的课。我想这说法确实有道理,此类问题也确实不宜从“总量一定”的角度来看:积累和玩乐之间,到底是选择朝三暮四,还是朝四暮三,它们之间,远远不只是时间的差别。

从QQ大战360想到的

按:QQ与360的大战已经持续一段时间了,而且显然成了最近的热点。网上网下,大家都在讨论,我也有些看法。不过,各方动态和大战进程已经有很多详细的报道,这里不赘述,只说说我的想法。

公关的新形势

公关(PR,Public Relation)是现代企业不可忽略的一面,无论是推广品牌价值、营造良好形象、应对负面信息,都离不开公关。传统的公关往往更侧重也更善于与媒体打交道,因为媒体几乎“决定”了公众的情绪——至少是垄断了情绪的表达。但是,随着博客尤其是微博的兴起,越来越多的个人成为了“自媒体”(we the media),即便在传统媒体的擂台上打了胜仗,也往往无法堵住所有用户的嘴,不一样的声音仍然会发出来,传播开来。“公关”丢了“公(公众)”,只剩下“关(关窍)”,自然成了无本之木,效果也大打折扣。

在这次的大战中,QQ和360的公关策略就是两种思路的典型代表。QQ更“愿意”(姑且这么认为)使用接受专访等方式发布和传播信息,立足点也多是“对方这么做,会把我们(QQ)如何如何”的逻辑(这更适合教室,而不是广场),微博上发布的信息也以“通告”口气为主,说是“以用户为核心”,却没有体现和传达出这种理念,更多的是自顾自地论证“不以用户为核心就没有腾讯的成功,没有全球第三的互联网公司”。这样的战法,似乎更希望也更合适在媒体擂台上跟360“一对一”,由专家点评、裁判论断,与普通人的感受相差十万八千里;然而昔日台下默不作声的观众早已登上擂台,感同身受地近距离观战,他们可以影响甚至决定舆论形势。

相反,360更多通过微博、论坛进行互动,反馈迅速而精准,而且强调始终“用户(您)会受什么影响”,而不是“我们(360)会受什么损失”。在公众表达渠道日益丰富,表达意愿日益强烈的今天,两套武功的高下立现。据我观察,QQ酝酿出台每一招都很正式,义正辞言,但360都可以迅速以草根形式应对,以巧劲化解;几个回合下来,360在公关上已经确立了完全的优势。

QQ以IM为核心的弊端

QQ庞大的“帝国”,始终是以IM为核心的,其它业务也多是以IM为入口和推动力。这样的好处是,具备足够黏性的IM能为其它业务提供可靠的依托和支撑,弊端则在于,一俊遮百丑——其它业务相对羸弱甚至不够称职,平时却没有机会暴露出来,比如上面提到“不称职”的公关就是如此。

QQ的公关的不称职,不但表现在缺乏应对新媒体、新形势的能力,而且在一些基础方面都很差劲。比如在微博中说“这种“云查杀”模式的指令来自服务器后台,在远程遥控安装在2亿台电脑里的360安全软件。这甚至是连微软、谷歌等国际互联网巨头也没有的超级能力”,措辞失当,贬损变成了褒扬;又比如在新闻发布会中,其公关经理前一分钟还说“昨晚腾讯一万多名员工,彻夜不眠”,后一分钟又说“其实作为有6千多名员工的公司我们有很多的办法结束这场战斗的”,且事后既没有“公关”修改此错误(照道理说,公司员工数目是一个相对稳定的常量,也无须保密),也没有给出解释,实在让人大跌眼镜;很难想象QQ帝国的公关部是这样的素质,可能的解释是,因为IM太核心、太显眼,公关部门的羸弱被掩盖了。

IM巨大用户量给QQ带来的好处,有时也可能变成坏处。前几个月QQ先后推出了“植物精灵大战格格巫”和“葫芦娃大战蛇妖”两款游戏,上线就引起强烈负面反响,旋即下线。我听闻这两款“山寨”游戏并非公司战略,而是个别部门自作主张的结果,他们认为随便山寨一个热门游戏,傍上QQ用户这棵大树就可渔利,不料恶评如潮,公司紧急叫停。没错,QQ确实模仿过不少产品,但做的成功的模仿,都离不开周密策划与精心投入(这就是我反对把QQ的成功简单归因为纯粹“模仿”的理由)。此类“仓促退出又迅速召回”的草率举动,对小公司来说或许无甚影响,但由QQ推出,造成的印象就是QQ恣意山寨,借IM入侵他人地盘,即便迅速召回也是赔了夫人又折兵,恶劣的印象一经留下,就难以磨灭。此次大战中,其它许多力量都暗中观战、巴不得QQ落败的心理,或许也与此类印象有关。

我们应该怎么看

之所以提到这个问题,主要是因为昨天看了霍炬的这两篇文章(流氓的背后是什么金山的流氓事)后的留言。大多数留言可以这样概括:要么“支持360”,要么“支持QQ”,要么不分黑白地大骂,却根本没读懂,甚至也没看文章的内容。
这里又不得不重弹“独立思考”的老调,所谓“独立思考”,就是不要“抽象支持”360或者QQ来“保持立场”,也不要笼统地“各打五十大板”以示公平,而要根据具体事件来判断。很可能在这件事情上是360有道理,而在那件事情上是QQ有道理;也可能,在某件事情上,QQ和360都不是“完全有道理”或者”完全没道理“,而是“各有一部分道理”或者“各有一部分错误”。只有摆脱情感好恶的垄断,脱开抽象笼统的概念,细致到具体的问题,仔细听取、分析他人的看法,才算得上真正具有了“独立思考能力”。

正则表达式的与或非

今天我的同事老赵 @jeffz_cn 问我,有没有办法用正则表达式匹配“不包含某个字符串”的文本,正好,我在写作的《正则表达式傻瓜书》中也提到了这类问题,就把这一节放出来,给大家参考,也希望大家多提建议(尤其是配图方面)。

正则表达式的与或非

我们都知道,写正则表达式有点像搭积木,复杂的功能总可以拆分开来,由不同的元素(也就是子表达式)对应,再用合适的关系将它们组合起来,就可以完成。在这一节,我们讲解常见的与或非关系的表达。

“与”是最简单的关系,它表示若干个元素必须同时相继出现,比如匹配单词cat,其实就是要求字符c、字符a和字符t必须同时连续出现。

正则表达式表达“与”关系非常简单,直接连续写出相继出现的元素就可以,我们可以想象,在各个元素之间,存在看不见的连接操作符·,比如上面匹配单词cat的正则表达式,就是『cat』,我们可以将它想象为『c·a·t』。

“与”关系也不限于字符之间,任何子表达式都可以用它来连接,如果我们把上面单词中的a替换为字符组『[au]』,表达式就变为『c[au]t』,你可以想象为『c·[au]·t』。

“或”是正则表达式灵活性的重要体现,我们可以规定某个位置的文本的“多种可能”,比如要匹配cat或是cut,在正则表达式看来,就是“字符c,然后是a或u,然后是t”。

如果“或”的多种可能都是单个字符(一般要求ASCII字符,中文字符等多字节字符的情况,可以参考本书专门论述的章节,此处仅以ASCII字符为例),就可以用字符组来表达“或”的关系,比如上面的cat或者cut的情况,正则表达式写做『c[au]t』,其原理如下:

更复杂的情况是“或”的多种可能,并非都是单个字符,有些可能是多个字符。比如,我们可以看一个更复杂的例子,不仅要匹配cut,还要匹配c开头、t结尾的单词chart、conduct和court。也就是说,在开头的c,结尾的t之间“可能”出现的是:uharonducour。

遇到这种情况,就不应使用字符组,而应当使用多选分支『(…|…)』,将各个“可能选项”列在多选分支中。于是,正则表达式变为『c(u|har|onduc|our)t』,其原理如下:

关于多选分支,还有两点要补充:

多选分支也可用于“每个选择都是单个字符”的情况,比如『c[au]t』写成『c(a|u)t』是没错的,但字符组的效率要远高于多选分支,所以,在这种情况下,推荐使用字符组『c[au]t』;

默认的多选分支『(…|…)』使用的括号是会捕获文本的,也就是说,括号内的表达式真正匹配成功的文本会记录下来,匹配完成之后可以提取出来,具体到上面的例子,就是我们有办法在匹配完成后“提取”出u或har或onduc或our。但许多时候,我们需要的只是整个表达式的匹配,而不关心“匹配时到底选择的哪种可能情况”,在这种情况下,我们稍加修改,使用“不捕获文本的括号”,可以提高效率。不捕获文本的写法也很简单,只是在开扩号之后加上字符『?:』,也就是『(?:…|…)』,具体到上面的例子,就应该写成『c(?:u|har|onduc|our)t』。这样做虽然繁琐点,但效率有保障,阅读起来也不困难,我推荐养成这种习惯,只要用到了括号,就想想是否真的要捕获括号内表达式匹配的文本,如果不需要,就是用不捕获文本的括号。

“非”看起来简单,其实是最复杂的,以下分几种情况讨论。

首先讨论针对字符的“非”:不容许出现某个或某几个字符。这是最简单的情况,直接用排除型字符组就可以对付,仍然用上面的例子,如果要匹配的单词是c开头、t结尾,中间有一个字符,但不能是u(也就是说,整个单词不能是cut),直接用『c[^u]t』就可以了,若中间的字符不能是a或u(也就是说,整个单词不能是cat或cut),则表达式改为『c[^au]t』。

如果你认真读过关于排除型字符组的章节,肯定会知道,这个表达式能匹配的只是cot之类的单词,因为中间的排除型字符组『[^au]』必须匹配一个字符。可是,如果我们还想要匹配chart、conduct和court,怎么办?最简单的想法是去掉排除型字符组的长度限制,改成『c[^au]+t』——不幸的是,这样行不通,因为这个表达式的意思是:c和t之间,是由多于一个“除a或u之外的字符“构成的,而chart、conduct和court,都包含a或u。

我们回头仔细看看这个“非”的逻辑,我们发现,其实我们要否定的是“单个出现的a或u”,而不仅仅是“出现的a或u”,所以才出现这样的问题,要解决这个问题,就应当把意思准确表达出来,变成“在结尾的t之前,不容许只出现一个a或u”。想到这一步,我们就可以用否定顺序环视『(?!…)』来解决了,它表示“在这个位置向右,不容许出现子表达式能够匹配的文本,我们把子表达式规定为『[au]t\b』(最后的『\b』很重要,它出现在t之后,保证t是单词的结尾子母)。

有了这点限制,匹配a和t之间文本的表达式就随意很多了,我们可以用匹配单词字符的简记法『\w』表示,于是整个表达式就变成了『c(?![au]t\b)\w+t』。请注意,这里出现的并不是排除型字符组『[^au]』,而是普通的字符组『[au]』,因为否定顺序环视『(?!…)』本身已经表示了“否定”的功能。

如果我们再进一步,“整个匹配文本中都不能出现字符串cat”,要怎么办呢?许多人的思路就是借鉴处理“或”关系的思路:既然字符组对应单个字符的情况,多选分支对应多个字符的情况,那么在否定时也是这样。可惜,正则表达式并没有提供与多选分支对应的“否定”结构,那么,应该怎么办呢?

解决的办法还是得依靠否定顺序环视——“整个匹配文本中都不能出现字符串cat”,换句话说,就是“在文本中的任意位置,向右,都不能出现该字符串”。因此,我们用两个锚点『^』和『$』,分别匹配整个字符串的开头和结尾位置,再用否定顺序环视『(?!cat)』表达“不能出现字符串cat”。

即便知道了原理,也不见得能写对正则表达式,比如『^(?!cat).+$』就是不正确的,因为它只限定了在文本的开头(也就是『^』)右边不能出现cat,而我们真正要做的是,在文本的每一个位置右边,都不能出现cat,所以应该改成『^((?!cat).)+$』;但这还说不上完美,根据前面提到的关于括号捕获的知识,因为此处并不需要括号捕获的文本,所以最好使用非捕获型括号『(?:…)』,最终我们得到的表达式就是『^(?:(?!cat).)+$』。

我翻译的几个步骤

提高自己的效率,做到事半功倍,是我们都希望达到的目标。如何达到这个目标呢?根据我的经验,不断反思、总结自己做过的事情,是很有成效的办法。翻译,也是这样,下面是我自己总结提炼的翻译步骤,给有兴趣的朋友作参考。

第一步,通读

通读很重要,却被许多译者忽视,他们往往认为,自己已经了解原文的“意思”,可以直接下笔,遇到问题“见招拆招”即可,翻译前通读原文,完全是浪费时间。

但是,事实似乎并非如此。我们翻译文章,要做的并不是“代替作者写文章”,而是“解释/传达作者的文字”。而文字本身是内涵丰富的,除去“意思”本身,还有用词、结构和风格等诸多方面。比如用词,原作者往往可能用一些双关语、多义词,在不同场合表达不同的意思,译者则应当尽力找到“对应”的双关语、多义词,这是个苦差,因此就更需要译者有大局观,知道原文中该词出现在哪些场合,都表示什么意思,才好取舍;再比如结构,原文中很可能有前后关联的典故/故事,有时甚至横跨几个章节,如果没有通读原文,翻译时就容易遗失原文的逻辑结构;风格也是如此,好的翻译讲究贴合原文,这种“贴合”,当然也包括风格的贴合,原文是轻快的,就不能翻译成沉重的;原文是严肃的,就不能翻译成平淡的。

当然,通读只是提供了观察鉴别这些“意思之外”的方面的机会,并不能保证译者能“准确把握”这些方面。但是不通读,却是绝不可能“把握”的。要想提高自己的通读效率,可以参考郝明义先生翻译的《如何阅读一本书》。

Continue reading 我翻译的几个步骤

怎样翻译更地道:尾大不掉的处理

常做翻译的人都知道,英文讲究结构严密、成分齐整,我们遇到再长的英文句子(哪怕是多个从句,或者有长长的插入语),只要能正确解析结构,都不难理解;中文则更追求“写意”,不太受形式规则的拘束,好的中文能营造出“行云流水”的感觉。单独看这两种语言的特点,各有理由,但是做起翻译来,就难免出现冲突,“尾大不掉”就是突出现象之一。

这里的“尾大不掉”,借用了余光中的说法,问题并不在并不是“尾大”,而在于“身躯臃肿”——“头”和“尾”是必须要同时出现的,但之间的内容太多,等看到“尾”,往往感觉突兀,但没有“尾”,结构又不完整。比如以下三个例子:

就是为什么他历经磨难也绝不放弃,一定要回来的原因

桌子边坐着一位漂亮的、大方的、温和的、优雅的女士

就像花儿到了季节会开放、小鸡到了时节要破壳一样,小孩子到了年纪,自然就学会走路了。

the reason why……、多形容词并列、as开头,也都是英语中自然的现象,并无不妥(as的另一个用法请参见《怎样翻译更地道:as somebody said的翻译》);但这些英文中本来可以紧密联系不必拆分的词语,翻译成中文,必须改成“为什么……的原因”、“就像……一样……”,而本来很常见的多形容词并列,也要插入到“坐着一位……女士”中间。于是乎,“尾大不掉”就露头了。这样的译文,并不妨碍理解,但读起来多少有些梗滞,在阅读长长的中间部分时,总得“惦记”最后的那个尾巴。

按照我的经验,要想让译文读起来更加舒服,小修小补是不够的,必须对“尾大不掉”动手,彻底打破“头……尾”的形式结构。比如,以上三句话可以分别改为:

因此(所以/故而),他历经磨难也决不放弃,一定要回来。
(可以这样译,是因为这句话一般出现在真正的原因之后)。

桌子边坐着的一位女士,漂亮大方,温婉可人
(关键做法是把形容词“自然”地挪到后面去,但是,这样处理也要求译者能灵活熟练锻造四字短语:有时需要将两、三个词合并到单个四字短语,比如“温婉可人”,也有时需要将单个词扩展为四字短语,比如“性情温和”)

花儿到了季节会开放,小鸡到了时节要破壳,小孩子到了年纪,自然也能学会走路。
(这类句子最好处理,直接去掉“就像……一样”,最后的主句酌情添加助词即可)

P.S. 我的另一点经验是,如果想译出好的文字,最好还是抽点时间读读古文,比如上面第二、三个例句,如果你熟悉介绍人物的通用句式,以及诗经中的比兴手法,多半不会译得生硬。

看得见的和看不见的

18世纪的法国,有位叫巴斯夏的经济学者写过一系列妙趣横生的短文,我印象最深的一篇叫做《看得见的与看不见的》:

詹姆斯•“好人”先生的儿子贪玩打破了一块玻璃,“好人”先生不得花6法郎去换玻璃,于是玻璃匠得到了6法郎。这时候有人说:快看哪,如果不是那个孩子贪玩,玻璃匠就得不到那6个法郎,资金就不会流转……由此引申开去,整个行业、整个经济体也会受益。
“且慢,让我跳出来大喊一声,”巴斯夏写道:你只看到了你看得到的,没看到你看不到的,即便贪玩的孩子没有打破这块玻璃,好人先生也不会把那6个法郎埋到地下,他可能用来修鞋,于是鞋匠拿到了那6法郎;他也可能用来理发,于是理发师拿到了那6个法郎……虽然这个鞋匠/理发师是藏在影子里的,但是你不能忽略它。

这个故事令我印象深刻,倒不是因为我们身边还有不少“地震/洪水/天灾有利经济发展”的言论,而是因为我深刻感觉到:许多东西我们可能看不见,但并非不存在,如果仅仅按照我们看得见的样子去直观理解,忽略了看不见的方面,很可能会产生错误的观念。

2003年夏天,我正在复习托福考试,每天的生活就是背单词,做一两套模拟题。当时正是暑假,许多人都回家了,留下的人也大多过得逍遥,想到这自己还能坚持每天复习,我颇有些自豪。当时托福的满分是667,我每次做模拟题都有630到640,自己也很满意——复习托福不过如此嘛。考前一两周,与朋友W通电话,我告诉他自己水平很稳定。于是他问我“很稳定是个什么概念?”。我说“就是每次都有630左右啊。”“这怎么能行呢?复习这种考试就应该只有一个目标啊。”我忙问“什么目标?” 他说,“就是满分啊,要不你总这么630就满意了,考试时全部发挥出来最多也只有630。再说我们大家复习都是以满分为目标的……”  许多年后,我依然清楚记得当时自己有多么震惊和羞愧,他的话好像晴空霹雳,而我猛然发现自己之前的想法是多么可笑。于是我强打起精神,努力分析总结自己每一个错误,努力抠每一点分数。可惜觉悟还是太晚了,考试的分数果然只有六百出头。这些年来,我时常想到,如果当年我能早点看到其他人认真投入复习的样子,而不是看看自己周围就满意了(好像看到玻璃匠得了6法郎,就认定打破玻璃有益于经济发展一样),会是一番多么不同的景象呀。不过,我也因此学会了在许多事情上“较真”,不要觉得还凑合,就糊弄自己,坚持下来还是很有收获的。

过了几年,还是从W那里,我又接受了一次教训。因为打算出国留学,他开始精心准备自己的P.S.(Personal Statement,个人陈述),我见过其他朋友准备的P.S.,虽然大家都花了时间,但大多数人写完、投出去,自己其实并没有太多的把握;而W的P.S.,我见到的感觉就是“眼前一亮”,虽然一时说不上究竟哪里好,但可以感觉到低调的文字间散发出卓尔不群的张力。我自然要问他,这是如何做到的。他说,这份P.S.弄了三四个月,一开始觉得照网上模板写写就好,给在美国的同学看却被批得一塌糊涂,于是下来几个月里,每天都在琢磨这份文档(甚至是忍着恶心),反反复复修改,真正是“字斟句酌”,到最后才算是真正满意了,投出去后自己心里也很有底,当然,最后申请的结果也相当满意。相比之下,我也看到身边有些人,找工作的时候大言不惭地说“简历就是随便弄了弄,别介意”之类,投出去的结果自然也是“看运气”。我问过一些人,为什么不花点时间认真做做简历,至少不用说“随便弄了弄”;而回答大都是“没时间”、“不知道怎么做”、“懒得弄了”;而且,越是这样回答的人,似乎也越难找到满意的工作,于是他们大都认为“如今工作不好找”、“太难”或是“我命不好”,而别人找到了好工作就是因为“机会好”、“会钻营”…… 我见过W对P.S.的态度之后,时常觉得摆这些理由其实就是“打破玻璃有益于经济发展”——因为没有看过那些“藏在阴影里”的现象,没有看到有人可以突破“凑合就行”的局限,没有仔细观察思考过其他人是如何找到好工作的,所以认定“工作难找”、“运气不好”,这类理由固然能够自圆其说,却可能并不是真正的原因,而且,相信此类理由,最终受影响的还是自己。

我自己亲身经历的另一件事情也是如此:刚上班的时候,我总觉得每天劳累不堪,累了自然就要休息,越累就越觉得要多睡觉。可是有一天我忽然发现身边有人做的事情一点不少,也不用睡那么长时间,精力照样很好。于是我想,“累了就要靠睡觉来补,越累就越多睡”可能不见得是真正的逻辑,仔细观察那些精神很好(并非天生精力旺盛)的人,并读过一些书之后,我逐渐发现,如果能够合理安排作息时间、规律生活、坚持锻炼身体,即便每天睡觉的时间不变,甚至还要少些,精神却好得多。回头想想,正是因为我有幸看到一些人和现象,现在的精力才好了许多,否则,多半还在“太累-睡不够”的简单逻辑里循环。

这个道理还可以推开来说:多留心一些“看不见的”东西,有助于我们形成更加准确的认识。比如近来非常流行的“一万小时”的说法很流行,它的大意是,不管你天资如何、所处环境如何,认定某件事情坚持练习一万小时,总会出类拔萃。许多人听到这个说法非常激动,但真正行动起来却又推三阻四。或许对他们来说,看得见的是“出类拔萃的人其实并不稀奇,只是坚持练习了一万小时而已”,看不见的则是“身边或许就有人一直在默默练习,而在你的无聊和犹豫的时候,生命留给你练习一万小时的时间,已经越来越少了”。

争当科学的逃兵吧

我的父母都是大学生,但严格说起来,我家并不算“知识分子家庭”:我父亲是学无线电的,母亲是学分析化学的。充其量也只算是“双料理科”家庭,少点人文气息;小时候没读过什么人文经典,不过爸爸妈妈从来都不给我太多的限制,只是根据我的兴趣,讲讲各种有意思现象背后的原理。而且,托“理工科”的福,我很小就在母亲实验室用氢气充过气球,用水银温度计测过温度,用比自然教科书上精密得多的仪器制过蒸馏水;也在父亲实验室的示波器上见过各种无线电波的“样子”,在中秋节用天文望远镜看过月亮上的环形山…当然,为此也弄过不少笑话:小朋友们都喜欢互相吹嘘自己父母的工作,有的说自己爸爸是解放军,有人说自己爸爸是大干部,我说“我爸爸是研究电子枪(电子枪是阴极射线管显示器里的元件)的”,当即引来大家的不服气,而且老师也没听说过什么是“电子枪”,于是宣布我在吹牛……

读大学之后,曾有一段时间我总抱憾小时候缺了“人文经典”的课,但这些年陆陆续续看了些书,看法又有改变:虽然没动多少人文,但大言不惭地说,好歹受了点科学的熏陶。真正的科学,总是能“养住”人的好奇心,把精力引导到大千世界的奥妙中去;即便不从事尖端的科学研究,多了解一点点科学,也能大大丰富自己的认知,看到与之前大不一样的世界,生活也会因此多了不少妙趣。

但是,要保持对科学的兴趣,对我们来说并非易事。现在许多人说起“科学”,想到的要么是不苟言笑、木讷寡言的孤僻,要么是全知全能、四处指点的霸气,所以多少有些“敬而远之”的味道。我有幸从小就接受科学的“浸染”,能够以柔润自然的方式体会到科学的妙趣,欣赏知识之美,并保持至今;另一方面也时常有些惋惜,我们本身就缺乏科学的传统,当今的科普又缺乏“柔润”,所以科学或被奉为神明,或被斥为外夷,总之就是“科普不得法”,许多人抱怨生活无聊乏味,这或许也是原因之一。

不过,科学松鼠会算是科普中的异数。借用革命导师的话说,“让科学流行起来”的口号,给科普增加了中国作风和中国气派;虽然某些人觉得不够严谨,但事实是最有说服力的:以我的经验来说,活动总是妙趣横生,嘉宾也总是和蔼严谨,这正是我所欣赏的“柔润”的方式。尤其是创始人姬十三,我见他之后最高兴的是:如今终于可以正经讨论我看《恐龙特急克塞号》时的奇怪念头——“如果几千万光年外的外星人,看到了恐龙灭绝的情形,用录像机录下来,再传回地球,我们就可以知道恐龙灭绝的原因了”,这样的人作“大当家”,还有什么好说的?后来参加“科学嘉年华”的经历,更是肯定了这一点。

在北京的时候,我参加过松鼠会好几次活动,大感意外的是,有许多年轻的家长带着孩子来参加松鼠会的活动,看到他们,我总是想起自己的童年,继而心生羡慕:他们要更加幸福,因为他们遇到的科普更丰富,更好玩,也更深刻;这样的孩子,一定能从容面对科技更加发达的生活。

今天看到松鼠会“寻科学逃兵”的活动,我立刻答应帮忙吆喝两声:年轻的时候,能做点自己真正喜欢的而又有意思事情才好,哪怕累,也是有意思的累(借用韩寒的话说,等你老了回忆自己的年轻岁月,至少敢说真正做了点有意思的事情);真正对科学有兴趣的同学们,不妨大胆去争当“逃兵”,我相信,科学的逃兵,能在松鼠会“淘”出点意思。

——————————【北京 and 上海】招聘职位分割线—————————–
科学编辑
科普图书编辑
实习编辑
IT实习生
NGO合作官员
媒体品牌主管
会计
公益活动志愿者

http://songshuhui.net/job/

古人更聪明,还是我们太大意?

按:这个问题是我长久以来都有希望想明白的,最近和徐宥同学讨论,终于稍微理清了思路,写在这里给有兴趣的朋友参考。认真的讨论,真是帮自己厘清思路的好办法。

有一类事情,我小时候就遇到过:好不容易有了个不错的主意或发明,不久却发现早就有人想到过了,于是陷入沮丧;如果我能早点出生,说不定记入历史书的就是自己的名字呢。

这种事情遇到的多了,我便开始想,我们要读那么多书,要记忆那么多先贤的名字,但是,他们真的比我们更聪明吗?或许仅仅是因为他们出生更早,“抢先”想到了那些问题,所以更聪明,这太不公平了。尤其是不断听到“从古人/老祖宗那里学习智慧”的说辞,就更加不服气了:他们真的比我们更聪明吗?而且我相信,有这种想法的人不在少数,我也见到不少人宣称自己“不逊于古人”,原因就是他们有一些“独立”的发明或发现。

可是,见识稍微多了些之后,我却逐渐相信,这样的“独立”发明和发现,并不能说明我们“不逊于古人”。要知道,发明和发现,并不是凭空产生的,有机遇的成分,更有知识储备、认知背景的因素;如果苹果不是掉在牛顿身上,发现万有引力定律的时间可能还要推迟。因此,所谓“独立”的发明和发现,也不能脱离文明发展水平而独立存在。举个例子:在现代,随处都可以见到火,摩擦生热也是生活的常识,所以哪怕现代有人“独立发明”了钻木取火,难度也远逊于茹毛饮血的时代。故而我们可以说,现代人即便有独立的发明和发现,也未必比古人更聪明。

那么,古人真的更聪明吗?我们随处可以看到“从古人/老祖宗那里寻找智慧”的说法,也听惯了“古人早就讲过…”的言辞,但是细细推敲一番,就发现这些说法似乎也不成立。

举个最简单的例子吧,许多人都知道一句名言:“人是政治的动物”,这是希腊大哲人亚里士多德的名言。读过他原著的人都知道,亚里士多德说的“政治”,并不是“权术”,而指公共空间(或者说“共同体”)中的言行,也就是说,人必然需要参与公共事务,每个人都不可能脱离社群而单独存在。但是,现代许多人引用这句话时,却有意无意忽视了“政治”的变化,甚至直接把“政治”等同于“权术”。如此一来,许多怪异甚至恶劣事情就“师出有名”了,更可以借此“教训”其他人:这可是古人的智慧,深刻的洞见。

这类现象,在我国尤其明显,因为我国历来缺乏解释学的传统,缺乏复现原文语境、辨别真义的持续探索和努力,古人留下的只言片语,就更容易“与时俱进”,不断附会出新的意义,久而久之,就愈发像“真理”了。然而,无法复原语境,无法确知语言的真正含义,其实根本谈不上什么“深刻洞见”的。

再退一步说,即便我们能确认古人说话的语境与现代的语境差别不大,古人做的“正确”判断,也不足够证明“古人更聪明”:我们都知道,要真正解决一个问题,必须经过若干个步骤(一般来说,越到现代要解决的问题更加复杂),但是,刚开始的几步基本是不变的,即便后来要反复试错,也难以全部推倒重来过。古人的许多话也是如此,限于当时的认知水平和文明发展程度,他们更多是做一些“原初”的判断,远不如今天的判断精密严格:没有准确的限定,也没有可证实或证伪的结论。比如,我们都知道有句老话叫“物极必反”,但针对一个具体的复杂问题,什么是“极”,“反”了之后会成什么样,估计没多少人弄得清楚:往一个方向走了一百步发生了甲变化,可以说是“物极必反”,往另一个方向走了一千步发生了乙变化,也可以说是“物极必反”……结果就好像《爱丽丝梦游奇境》里柴郡猫所说的“只要你走的足够远,总能找到些东西”,也就是说“物极”总是可以找到“必反”。诚然,我们不必否定“物极必反”,但在当今社会,面对更复杂更精密的问题,仍然只知道“物极必反”,就是我们不够聪明:社会进步了,文明发展了,认识却没有深化。因此,现代人除了要知道概略的“物极必反”,更应该知道在什么情况下,会发生什么样的变化——虽然这样的知识很可能出错,而“无极必反”却从不会错,如果做不到这一点,倒真是证明了“古人比我们更聪明”。

所以,我的看法是,古人是不是比我们更聪明,这个问题很复杂,我们固然不宜因为自己的发明发现就否认古人的艰苦努力,但也不宜还没全面了解就把古人的话奉为金科玉律,更不宜把给笼统的判断戴上“本质/普遍规律”的高帽子来膜拜;对古人的话,应当努力理解语境,弄清它的本来意义,把握好分寸(比如:它到底是个定性的概略判断,还是个定量的具体判断),才能得到自己的客观判断。也正是因为如此,胡适先生才告诫年轻学子:不假思考地引用古人的话当论据,其实是非常要不得的习惯。当然,胡适先生的这句话,我们同样要多加思考、妥善运用。

知识背后的知识

我刚刚上政治课的时候,总是不明白“形而上学”是什么东西,课本总是语焉不详,又大加挞伐;后来,我从《现代汉语词典》里查到了“形而上学”的概念,把它工工整整地抄在扉页上,现在还大致记得内容:一种哲学观点……强调用静止、孤立、片面的眼光看待世界……

到后来终于有机会看点哲学原著,才知道“形而上学”并不仅仅是“一种”哲学观点,而是在哲学乃至人类文明中占有相当地位(至少是曾经)的知识门类。再学了点英文,知道“形而上学”的原文是metaphysics,meta表示“之后/之上”,physics的希腊原文φυσικά(physiká)则表示“自然,自然的产物”;照字面意思,不妨翻译为“自然现象之后”,也可以这么说:形而上学就研究的是自然现象背后内容的学问。这背后的内容,你可以叫它“本质”(所以形而上学才会与“本体论”联系起来),也可以认为它是理念、规律;无论怎么称呼,它总是代表了人类不满足于现象本身,而要探究其幕后景象的渴望。可以说,也正是因为这种不满足和渴望,人才有动力超越自身经验的局限,逐渐摸索出规律和原理,把不同的现象联系起来,拓展对世界的认识,也才有今天庞大而复杂的知识结构。

形而上学固然有过这样的好处,但这种超越(脱离)感知,更多借助理性和推演的做法,却不见得容易认同。举我自己的例子吧,小时候父母希望培养我读书的爱好,但开始并非全给我讲有趣的故事,而是花了很多精力让我学习查字典,当时我很不理解,因为相对看有意思的书,学习查字典实在是很无聊的工作,而且查字典与看书并没有特别紧密的联系,一个字在字典里有很多解释,但看书时其实只要用到一种,为什么要费力走那些弯路呢;另一个例子是父母带我去认各种生物(主要是植物和昆虫),回来之后必然要我去查百科全书,了解一样生物的分类、习性、分布等等知识,很长时间里我也不了解这样做的意义,分类、习性、分布等等,知道了固然没什么坏处,但这些知识,完全不能对接上我的感觉经验,用现在许多人的话来说:搞那么复杂,何必呢?

同样的看法,我保持了许多年,直到后来才逐渐改变:查字典看似与读书没有直接的关系,但在普通阅读时,我们接触到的都只是字词的某个方面,而要妥善运用这些字词(比如翻译时就很需要),就得把握它的“实质”,就必须做些脱离现实的工作,了解这个词的起源、词性、应用场合;查百科全书也是如此,它让我知道了生物与生物之间存在哪些奇妙的联系,而且知道已经有了某些完善的工具来分析和描述看到的现象,即便这些知识暂时“没有用”,将来也多半能有用得着的地方(比如判断某种说法的可信度)。

不过,最重要的收获是:我逐渐发现,这些“脱离实际”、去追求“知识背后的知识”的做法,帮我养成了“不满足”的习惯——遇到什么,都不大甘心止步于最基本最简单的现象,而希望更进一步,到更深入、更广泛、“脱离实际更远”的世界(虽然可能仅仅是“理念世界”)看待它;或者可以这么说:我看到一个世界,不光要想去认知这个世界中的一切,还要想想我是怎样看到这个世界的——是在怎样的条件下,借助怎样的光线看到的——如果这些条件变化了,我看到的世界还会是这样吗…… 当然,有人不屑地说这是“玩套路”或“太麻烦”,但我自己确实能从中受益。比如读书,我读书的速度其实不够快,只是花了些时间学习如何阅读一本书,于是遇到好书,总愿意花时间了解作者的身份和流派,全书核心观点的渊源,在相关领域/学科的地位和批评,我觉得,这样才算真正掂量准了这本书的分量,才能够做真正的评判和取舍、有所收获,一个例证是:与人谈起来,自己的理解更可信、更稳定(当然不是为辩论而辩论的稳定);再比如专业技术的学习,我也愿意多花点时间,培养、积累对新技术的理解和判断能力:几乎每一门新技术,都对应了一类问题,背后都有一道渊流,我们学习的时候,如果能突破技术本身(许多时候就是相关书籍)的局限,梳理清楚它产生的原因、它擅长解决的问题、它合适应用的场景、还有大家对它的批评,真正解决起问题来,把握感和驾驭感都会大大增加,生产效率也随之上升。

更重要的是,人类的行为是严重受到知识影响的,许多时候,不去努力学习一点“知识背后的知识”,很快就把一条路走到头,而陷入无解的局面:比如如今流行的一个说法是“现代社会知识大爆炸,让人根本无从选择”。的确,在之前很长的时代里,我们都处于知识匮乏的状态,于是遇到信息总希望吸收,遇到知识总希望掌握,但是现在这样做已经行不通了。这看似是一个无解的问题。但是,如果不止满足于“学习知识”,还愿意认知原理(也就是“关于学习知识的知识”),这问题就迎刃而解了:像海绵一样,看到知识就学,看到信息就吸取,这是信息匮乏年代的模式;在信息丰富的年代,我们需要走一条不同的道路了:把自己的大脑锻炼成有效的筛子(这种训练和锻炼也是有章可循的,虽然它们似乎更加“脱离实际”),像淘金一样,只留下最有价值的内容,放任那些无价值的信息流过。与此类似的“无解”问题还有许多,但并非都真正“无解”,如果你愿意多掌握一些“知识背后的知识”,多半能看到全新的解决办法。

学过中学物理的人都知道磁场和磁力线,它们看不见、摸不着,但可以想象、归纳,也在人类生活中发挥了巨大作用(比如,在没有树木、没有阳光的地方,也可以指引方向);从某种程度来说,“知识背后的知识”也是如此,它们看不见、摸不着,可是一经掌握,你就能获得全新的视角,看到很多全新的办法——比如,许多人常常一面学习,一面苦恼,于是有了“知识越多越烦恼”的说法,但是如果你愿意花些时间掌握“究竟要学习什么”的知识,愿意了解人在生命的每个阶段会遇到哪些问题、应当为下一阶段做哪些准备,所谓“知识越多越烦恼”的说法,也就变成了“知识越多越坦然”、“知识越多越有节奏感”。