谈谈写程序与学英语 宋劲杉
宋劲杉老师一些英语的建议,还有他写的书——Linux C编程一站式学习,开源发布的,自由分享
http://www.akaedu.org/page/newsdetail-634.html
俗话说,没有金刚钻,就别揽瓷器活儿。套用到IT业,英语不行,就别做程序员。网上关于程序员学英语的文章不少,但我想谈谈我自己的看法。首先详细讨论一下为什么程序员离了英语不行,然后针对程序员应该怎么学英语说说我的体会。
英语是计算机的母语,是程序的母语,所以必然是程序员的母语。程序中的变量名、函数名起得好不好是决定代码质量和可维护性的最关键因素。高质量的代码应该是这样的:代码基本上是自解释的(self-explanatory),不需要太多注释,不管代码的规模有多大,具有相关知识背景的读过文档的人都可以立刻上手、立刻参与维护和开发。要想使代码能够自解释,给变量和函数起个好名字很关键,很显然,只能用英文起名字,一是用汉语拼音起名字可读性很差,二是英文单词通常比汉语更expressive(看吧,如果用汉语来说,就得说“表达能力更强”、“更有表现力”这么罗嗦),由于程序的复杂性,变量和函数往往表示一些很抽象的概念,起个既准确又简洁的名字并不容易,可是很多时候,用汉语需要很多字才能说清楚的一件事,用英文一个单词再加点词形变化就能说清楚了。例如APUE上讲sleep函数的实现,其中有个变量表示“本来应该睡到某个时刻,但是提前被信号唤醒了,唤醒时与本来应该睡到的时刻相差的时间”,如果为了简洁而不求准确,这个变量名至少也得叫“未睡到”,而书中只用了一个单词unslept,非常准确、简洁地表达了这个意思。为了写程序而学英语需要学到什么水平?我认为能起出这种变量名就够水平了。很多在IT外企工作的中国人,说话写文章经常夹杂着英文单词(比我严重多了因为我不在外企),非常可以理解,确实是为了表达得更准确简洁的需要,而不是纯为了play zhuangbility。总之,要写程序必须学好英语,否则连变量名都起不好,这虽然是一个非技术问题,但却是个根本问题,比任何技术问题都重要。当然,现在很多编程语言也支持用Unicode字符给变量和函数起名,但是你见过有人用汉字写程序吗?根本不实用。有人会辩驳说一页英文翻译成中文往往只占半页,中文不是更简洁吗?但是你算算打一页英文和打半页中文哪个敲键盘次数多。另外,要读别人的代码也必须学好英语,如果你不知道unslept是由 sleep变形而来的,就体会不到其中的精妙,只有大量阅读高质量的代码,才能写出高质量的代码,创作都是从模仿开始的。
说说英语对于看书学习的重要性。中文技术书和英文技术书的水平根本不在一个量级上,这是有很多原因的,不能全归结于中文书的作者水平差。最重要的是,出中文书的低回报率决定了作者不可能花太多心血在上面,你去amazon看看一本书卖多少美刀,再去chinapub看看一本书卖几块钱。老外写一本书,可以做到全书没有一个拼写错误(当然英文的拼写检查工具更完善也是部分原因),中文能找出一本没有错别字的书吗?Knuth可以悬赏让全世界读者来找磋,中文书作者有哪个敢这么做?不是因为老外态度有多认真治学有多严谨,而是因为他们赚到了,就应该拿出高质量的作品来,不然会被读者骂的。
英文技术书的翻译质量通常很差。也不能归结于译者的水平差,我也翻译过书,也努力想译好,但真的很难译好。IT业的新名词层出不穷,像“内核”、“网络”这种常见术语还好,稍微专一点的术语都没有统一的译名。我们在教学中发现,很多学员看书时搞不清这本书的名词A和那本书的名词B是什么区别,来问老师,才发现原来A和B就是一回事儿。这是一个单词对应多个译名的情况,还有一个译名对应多个单词的情况,比如field、domain、realm都译成“域”,block、 bulk都译成“块”,argument、parameter都译成“参数”,attribute、property都译成“属性”,虽然这些词的意思本来就差不多,但是在一篇文章里,作者可以换着用,不同的单词表示不同的概念,翻译完了一看,都成一个概念了。英文书背后都有index,看到一半忘了某个名词是怎么定义的就可以翻index,而译文通常没有index,名词都已经乱七八糟了,没法做index。还有更发指的是,老外喜欢造词,现有的单词上加一点变化和组合(例如有人喜欢说automagically),看着心领神会,想译出来就很费劲。老外即使在技术书中也经常用一些生动的表达方式和俏皮话,而中文的书面语言非常死板,生动的表达方式只存在于口语中,如果写在书上就很不像话,这也是很难翻译的一个重要原因。看中文译本,不仅质量差,而且跟不上时代,通常一本英文书出来,至少要等一到两年才能看到中文译本。两年啊!等你看到这本书的中文译本时,这个版本都快淘汰了。
然后说说英语在开发工作中的重要性。看书学习通常只起一个引导入门的作用,在工作中更有用的是手册、文档。学完了C语言开始写程序了,谁还会去查K&R附录中的库函数?查man page才是最有效率的。然而手册比入门书更少有中文译版,因为手册是随时变的,会随着软件版本更新,而且需要看这些开发手册的人通常不会有英文障碍,有英文障碍的人即使看了翻译的手册也写不出好程序来,所以当然没必要翻译了。不管什么技术,官方的手册和技术标准才是最原始的第一手资料,看别的书都是以讹传讹,由于自然语言不可避免是有歧义的,文档中表达得不准确的地方就会被文档的读者也就是技术书的作者误解,技术书中再有表达不准确的地方又被译者误解。我们小时候都玩过传话的游戏,几个人站一排,通过悄悄话传一句话,传到最后变成什么了?所以,学网络协议,就得看RFC,学ARM,就得看ARM公司的 Architecture Reference Manual,要学习C语言就得看C99,有歧义不要紧,自己去揣测原作者的意思,总比道听途说的可靠。
我们的学员出去面试经常被问到的一个问题就是:在开发工作中遇到问题,书和文档上都没有答案,网上搜一下也没有答案,怎么办?要我说,能看懂源代码的就去源代码中找答案,这称为hacking,不管是内核、libc还是各种framework,你调用的东西有问题都能从它的代码中找到原因。如果没有能力 hacking,或者时间紧不想去hacking,最好的办法就是去官方邮件列表和IRC问。如果英文不行就没办法了,只能去一些中文论坛:“各位大虾帮忙,小弟有一个问题求救!跪求!!在线等!!!”在线等了好几天也无人问津,或者答非所问。岂不知逛这些论坛的没有大虾,都是菜鸟,大虾们都在IRC上聊得正欢呢。我在做Qt开发时曾经有一个问题,当时在教育网,上国外网不方便,去各大中文论坛问了好几天也没人给出满意的回答,后来花钱连了国外网,去 trolltech官方新闻组提问,只等了几分钟就得到了满意的解决办法。这次经历给我留下了深刻印象,从此以后再也没有去中文论坛。
那么,如果现在英文水平很差,又想做程序员,应该怎么学英语呢?我下面说的方法有两个前提,一是你的英文至少达到高中毕业水平,也就是语法基本都学完了,即使用得不熟练也知道有那么回事儿,二是你希望尽快在工作中用上英语,写程序够用就行,而不是有考T考G这样的更高要求。
学习英语有听说读写四个方面的要求,做程序员至少需要读和写非常流畅,如果在外企工作还需要听和说的能力。技术英语和考T考G是不一样的,一是听和说不像读和写那么重要,不必担心自己是“聋哑英语”,没关系,丝毫不影响你成为编程高手,二是要求的词汇量要小得多。考T考G都要拿一本单词书背,很少有人会觉得背单词很有意思,至少我是觉得很痛苦,幸运的是看技术书不需要多少词汇量。技术书的描述对象都是局限于一个很窄的领域的,就那么几个单词翻来覆去地用,而且技术书是为了让人看懂的(不像诗是为了让人看不懂的),比较复杂的词在书中都有定义或解释。有些作者喜欢卖弄词汇量,用一些很生僻的单词,也有些作者卖弄一些典故,由于文化背景不同很难理解,不过这些通常都可以无视,不会影响阅读,还是因为技术书是为了让人看懂的。对于学习者来说,阅读能力是最重要的,等你完成了学习,成为一个合格的开发者时,需要写代码注释,需要写文档,需要通过邮件交流,写作的能力才开始重要了。所以应该首先从阅读开始练习英语。
现在就拿起一本英文原版书开始看吧。和学游泳一样,阅读的能力只能通过阅读本身来练习。我的经验是,不必先系统学习了单词和语法再看书,可以在看书时用到什么就补什么。我建议初学者看电子版,因为现在的词典软件都可以鼠标取词,边看边查很方便,很多勤快人喜欢把查过的单词都抄下来,我觉得没有必要,反正查字典很方便,下次再看到了就再查,多查几次总会记住的,抄下来就打断了看书的思路,而且不见得抄下来就能记住。也许是因为我这人比较懒,我用的都是懒办法。很多人不喜欢看电子书,理由是盯着屏幕看书太累,那么盯着屏幕写程序累不累?这种人显然不适合做程序员。语法不熟练怎么办?大多数情况下单词的意思都明白了就不影响阅读。技术书有时候喜欢用长句,其中可能包含各种从句,如果实在读不懂就去查语法书,同样也不需要把这种从句彻底弄明白,只要这一句能看过去就行了,以后多查几遍书,自然就掌握了。另外,技术书是说明文,通常不应该有过去时,看到过去时就需要注意了,很可能是虚拟语气,如果不注意这一点,看到的意思可能和真实的意思正好相反。
应该从哪本书开始看起呢?从你当前最需要学的技术书看起。看书是相当花时间的,如果能一边学英语一边学技术,这时间利用得就很有效率。比如,如果你的C语言已经学得相当好了,不要专门为了学英语去重看一遍原版的K&R。市面上有一些专门的计算机英语教材,我的建议是不要看,浪费时间,nonsense。初学时最好选一本有中文译本的书,有看不懂的地方可以翻中文版来对照,但是不要相信中文的翻译,原因在前面讨论过了。如果你是初学编程,没有任何基础,我可以推荐一本英文很浅显技术也很浅显的书:How To Think Like a Computer Scientist,有Python、Java和C++版本,可自由下载。
要逐渐养成良好的阅读习惯。一是不要每个生单词都去查,有些单词很生僻,查了也记不住,记住了也不会再见到它了,但是前面讲过,都是作者在卖弄词汇量,无视它丝毫不影响阅读,因此要学会猜测单词的意思,能不查就不查,继续贯彻“懒”的原则。二是看书不要动口,不念出声也不行,就是不要动口,要努力在大脑中建立从词形到语义的直接映射,如果只能从词形到读音再到语义就太慢了,严重影响阅读速度。三是努力做到每句话都从头到尾只看一遍,不许回头反复看,这一点比较难,必须注意力高度集中,经常在记忆中暂存前面半句的内容和句式才能做到,但是一旦神功练成就会成倍地提高阅读速度。最后一层境界,学会skim,就是略读,很多优秀的作者在组织材料时会给读者一些建议,比如这一段是扩展的高级话题,和主线的相关度较低,可以先skim到后面,注意不是让你skip到后面,这一段还是要读的,但是不必逐字句地读,而是抓主旨,大概讲了个什么概念(有一些下定义的句式),有哪些要点(有数字编号或bullet列表项),适用于哪些场合有哪些注意事项(有 caveat、gotcha、noteworthy这种字眼),后面可能还会碰到这个概念,虽然你没有仔细看这是个什么东西,但大体上也知道了,这样就能不影响后面的阅读,这不仅需要高度集中的注意力、熟练的语言能力,而且要有足够的背景知识去猜测性地理解。但是语言能力还是最重要的因素,我和几个同学交流过,他们也能熟练地看英文书,但是需要skim查一个东西时就觉得还是不如中文书查得快。skim的技能在查阅手册时尤其重要,没有人会像看入门书一样把上千页的手册从头到尾看一遍,都是用到哪儿就查哪儿。总之,锻炼各种阅读习惯就为了一个目的:如何在最短的时间内,在保证正确性的前提下,获取尽可能多的知识。程序员的学习时间都是非常宝贵的。
以上本着“够用就好”的原则,多次提到用懒办法,但是学技术学英语这两件事不能懒,贵在坚持。要养成良好的阅读习惯也有很多东西需要坚持,其中最根本的是持续高度集中注意力,充分调动记忆能力、推理能力、猜测能力,就像考试做阅读题一样看每一段话。最根本也是最重要的,“有英文原版就不看中文版”这个原则一定要坚持。一开始看英文书可能会很慢,但只要一直坚持就会慢慢达到原来看中文书的速度,再坚持下去就会比中文书看得更有效率,因为避免了很多歧义和术语翻译的问题。有人会说,项目紧任务急,看英文资料太慢,这次就先用中文尽快解决工作中的问题吧,等以后有时间了再看英文书学习。可是什么时候才会有时间呢?工作总是一个接一个的,老板怎么会付了工资让你闲着呢?如果你有这样的困难,我的建议是干脆辞职,学好了英文再去工作。你只要想想,你的同行们在外企全英文的环境下工作,英文和技术每天都在突飞猛进,而你还在用效率极其低下的方式学习和工作,你和别人的差距不是越来越大了吗?另一方面,现在的在校学生从小学就开始抓英语,基础都很好,很多高校也逐渐重视引进原版教材,开设很多英文授课的专业课。你再不奋起直追,就不觉得以后的职业道路充满危机吗?
最后说说写作。刚开始练习时不要怕写错,能表达清楚自己的意思即可。我看过很多源代码和文档中的英文,一看就是中国人写的,谓语动词不分单复数,名词复数不加s,处处可见中国式英语,但是丝毫不影响我对这些编程大牛的景仰,因为其中的思想我看懂了,并且我认为很强大。我有一个朋友,中学毕业就出来混的,由于工作的性质总要跟老外打交道,他从来不惧和老外交流,虽然连一个囫囵的句子都说不出来,但总是能用中学学的那点单词让老外明白他的意思,这一点我就非常佩服。总之就是说,不要因为不知道怎么写是对的就不敢动笔写,只要敢交流,并且别人能懂你的意思,就是很有效的交流。而且随着阅读量的增加,自然能写出一手好英文,前面讲过了,创作总是从模仿开始的。不怕出错才能有一个好的开始,才能逐步练习提高,而练习的最终目的当然还是希望写好,不仅字句通顺无语法错误,还能适当修辞。