Java语言学校的危险性(译文)

作者: 阮一峰

日期: 2008年12月 7日

面的文章是More Joel on Software一书的第8篇。

我觉得翻译难度很大,整整两个工作日,每天8小时以上,才译出了5000字。除了Joel大量使用俚语,另一个原因是原文涉及"编程原理",好多东西我根本不懂。希望懂的朋友帮我看看,译文有没有错误,包括我写的注解。

====================

JAVA语言学校的危险性

作者:Joel Spolsky

译者:阮一峰

原文: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html

发表日期 2005年12月29日,星期四

如今的孩子变懒了。

多吃一点苦,又会怎么样呢?

我一定是变老了,才会这样喋喋不休地抱怨和感叹"如今的孩子"。为什么他们不再愿意、或者说不再能够做艰苦的工作呢。

当我还是孩子的时候,学习编程需要用到穿孔卡片(punched cards)。那时可没有任何类似"退格"键(Backspace key)这样的现代化功能,如果你出错了,就没有办法更正,只好扔掉出错的卡片,从头再来。

回想1991年,我开始面试程序员的时候。我一般会出一些编程题,允许用任何编程语言解题。在99%的情况下,面试者选择C语言。

如今,面试者一般会选择Java语言。

说到这里,不要误会我的意思。Java语言本身作为一种开发工具,并没有什么错。

等一等,我要做个更正。我只是在本篇特定的文章中,不会提到Java语言作为一种开发工具,有什么不好的地方。事实上,它有许许多多不好的地方,不过这些只有另找时间来谈了。

我在这篇文章中,真正想要说的是,总的来看,Java不是一种非常难的编程语言,无法用来区分优秀程序员和普通程序员。它可能很适合用来完成工作,但是这个不是今天的主题。我甚至想说,Java语言不够难,其实是它的特色,不能算缺点。但是不管怎样,它就是有这个问题。

如果我听上去像是妄下论断,那么我想说一点我自己的微不足道的经历。大学计算机系的课程里,传统上有两个知识点,许多人从来都没有真正搞懂过的,那就是指针(pointers)和递归(recursion)。

你进大学后,一开始总要上一门"数据结构"课(data structure), 然后会有线性链表(linked list)、哈希表(hash table),以及其他诸如此类的课程。这些课会大量使用"指针"。它们经常起到一种优胜劣汰的作用。因为这些课程非常难,那些学不会的人,就表明他们的能力不足以达到计算机科学学士学位的要求,只能选择放弃这个专业。这是一件好事,因为如果你连指针很觉得很难,那么等学到后面,要你证明不动点定理(fixed point theory)的时候,你该怎么办呢?

有些孩子读高中的时候,就能用BASIC语言在Apple II型个人电脑上,写出漂亮的乒乓球游戏。等他们进了大学,都会去选修计算机科学101课程,那门课讲的就是数据结构。当他们接触到指针那些玩意以后,就一下子完全傻眼了,后面的事情你都可以想像,他们就去改学政治学,因为看上去法学院是一个更好的出路[1]。关于计算机系的淘汰率,我见过各式各样的数字,通常在40%到70%之间。校方一般会觉得,学生拿不到学位很可惜,我则视其为必要的筛选,淘汰那些没有兴趣编程或者没有能力编程的人。

对于许多计算机系的青年学生来说,另一门有难度的课程是有关函数式编程(functional programming)的课程,其中就包括递归程序设计(recursive programming)。MIT将这些课程的标准提得很高,还专门设立了一门必修课(课程代号6.001[2]),它的教材(Structure and Interpretation of Computer Programs,作者为Harold Abelson和Gerald Jay Sussman Abelson,MIT出版社1996年版)被几十所、甚至几百所著名高校的计算系机采用,充当事实上的计算机科学导论课程。(你能在网上找到这本教材的旧版本,应该读一下。)

这些课程难得惊人。在第一堂课,你就要学完Scheme语言[3]的几乎所有内容,你还会遇到一个不动点函数(fixed-point function),它的自变量本身就是另一个函数。我读的这门导论课,是宾夕法尼亚大学的CSE 121课程,真是读得苦不堪言。我注意到很多学生,也许是大部分的学生,都无法完成这门课。课程的内容实在太难了。我给教授写了一封长长的声泪俱下的Email,控诉这门课不是给人学的。宾夕法尼亚大学里一定有人听到了我的呼声(或者听到了其他抱怨者的呼声),因为如今这门课讲授的计算机语言是Java。

我现在觉得,他们还不如没有听见呢。

这就是争议所在。许多年来,像当年的我一样懒惰的计算机系本科生不停地抱怨,再加上计算机业界也在抱怨毕业生不够用,这一切终于造成了重大恶果。过去十年中,大量本来堪称完美的好学校,都百分之百转向了Java语言的怀抱。这真是好得没话说了,那些用"grep"命令[4]过滤简历的企业招聘主管,大概会很喜欢这样。最妙不可言的是,Java语言中没有什么太难的地方,不会真的淘汰什么人,你搞不懂指针或者递归也没关系。所以,计算系的淘汰率就降低了,学生人数上升了,经费预算变大了,可谓皆大欢喜。

学习Java语言的孩子是幸运的,因为当他们用到以指针为基础的哈希表时,他们永远也不会遇到古怪的"段错误"[5](segfault)。他们永远不会因为无法将数据塞进有限的内存空间,而急得发疯。他们也永远不用苦苦思索,为什么在一个纯函数的程序中,一个变量的值一会保持不变,一会又变个不停!多么自相矛盾啊!

他们不需要怎么动脑筋,就可以在专业上得到4.0的绩点。

我是不是有点太苛刻了?就像电视里的"四个约克郡男人"[6](Four Yorkshiremen)那样,成了老古板?就在这里吹嘘我是多么刻苦,完成了所有那些高难度的课程?

我再告诉你一件事。1900年的时候,拉丁语和希腊语都是大学里的必修课,原因不是因为它们有什么特别的作用,而是因为它们有点被看成是受过高等教育的人士的标志。在某种程度上,我的观点同拉丁语支持者的观点没有不同(下面的四点理由都是如此):"(拉丁语)训练你的思维,锻炼你的记忆。分析拉丁语的句法结构,是思考能力的最佳练习,是真正对智力的挑战,能够很好地培养逻辑能力。"以上出自Scott Barker之口(http://www.promotelatin.org/whylatin.htm)。但是,今天我找不到一所大学,还把拉丁语作为必修课。指针和递归不正像计算机科学中的拉丁语和希腊语吗?

说到这里,我坦率地承认,当今的软件代码中90%都不需要使用指针。事实上,如果在正式产品中使用指针,这将是十分危险的。好的,这一点没有异议。与此同时,函数式编程在实际开发中用到的也不多。这一点我也同意。

但是,对于某些最激动人心的编程任务来说,指针仍然是非常重要的。比如说,如果不用指针,你根本没办法开发Linux的内核。如果你不是真正地理解了指针,你连一行Linux的代码也看不懂,说实话,任何操作系统的代码你都看不懂。

如果你不懂函数式编程,你就无法创造出MapReduce[7],正是这种算法使得Google的可扩展性(scalable)达到如此巨大的规模。单词"Map"(映射)和"Reduce"(化简)分别来自Lisp语言和函数式编程。回想起来,在类似6.001这样的编程课程中,都有提到纯粹的函数式编程没有副作用,因此可以直接用于并行计算(parallelizable)。任何人只要还记得这些内容,那么MapRuduce对他来说就是显而易见的。发明MapReduce的公司是Google,而不是微软,这个简单的事实说出了原因,为什么微软至今还在追赶,还在试图提供最基本的搜索服务,而Google已经转向了下一个阶段,开发世界上最大的并行式超级计算机----Skynet[8]的H次方的H次方的H次方的H次方的H次方的H次方。我觉得,微软并没有完全明白,在这一波竞争中它落后多远。

除了上面那些直接就能想到的重要性,指针和递归的真正价值,在于那种你在学习它们的过程中,所得到的思维深度,以及你因为害怕在这些课程中被淘汰,所产生的心理抗压能力,它们都是在建造大型系统的过程中必不可少的。指针和递归要求一定水平的推理能力、抽象思考能力,以及最重要的,在若干个不同的抽象层次上,同时审视同一个问题的能力。因此,是否真正理解指针和递归,与是否是一个优秀程序员直接相关。

如果计算机系的课程都与Java语言有关,那么对于那些在智力上无法应付复杂概念的学生,就没有东西可以真的淘汰他们。作为一个雇主,我发现那些100%Java教学的计算机系,已经培养出了相当一大批毕业生,这些学生只能勉强完成难度日益降低的课程作业,只会用Java语言编写简单的记账程序,如果你让他们编写一个更难的东西,他们就束手无策了。他们的智力不足以成为程序员。这些学生永远也通不过MIT的6.001课程,或者耶鲁大学的CS 323课程。坦率地说,为什么在一个雇主的心目中,MIT或者耶鲁大学计算机系的学位的份量,要重于杜克大学,这就是原因之一。因为杜克大学最近已经全部转为用Java语言教学。宾夕法尼亚大学的情况也很类似,当初CSE 121课程中的Scheme语言和ML语言,几乎将我和我的同学折磨至死,如今已经全部被Java语言替代。我的意思不是说,我不想雇佣来自杜克大学或者宾夕法尼亚大学的聪明学生,我真的愿意雇佣他们,只是对于我来说,确定他们是否真的聪明,如今变得难多了。以前,我能够分辨出谁是聪明学生,因为他们可以在一分钟内看懂一个递归算法,或者可以迅速在计算机上实现一个线性链表操作函数,所用的时间同黑板上写一遍差不多。但是对于Java语言学校的毕业生,看着他们面对上述问题苦苦思索、做不出来的样子,我分辨不出这到底是因为学校里没教,还是因为他们不具备编写优秀软件作品的素质。Paul Graham将这一类程序员称为"Blub程序员"[9](www.paulgraham.com/avg.html)。

Java语言学校无法淘汰那些永远也成不了优秀程序员的学生,这已经是很糟糕的事情了。但是,学校可以无可厚非地辩解,这不是校方的错。整个软件行业,或者说至少是其中那些使用grep命令过滤简历的招聘经理,确实是在一直叫嚷,要求学校使用Java语言教学。

但是,即使如此,Java语言学校的教学也还是失败的,因为学校没有成功训练好学生的头脑,没有使他们变得足够熟练、敏捷、灵活,能够做出高质量的软件设计(我不是指面向对象式的"设计",那种编程只不过是要求你花上无数个小时,重写你的代码,使它们能够满足面向对象编程的等级制继承式结构,或者说要求你思考到底对象之间是"has-a"从属关系,还是"is-a"继承关系,这种"伪问题"将你搞得烦躁不安)。你需要的是那种能够在多个抽象层次上,同时思考问题的训练。这种思考能力正是设计出优秀软件架构所必需的。

你也许想知道,在教学中,面向对象编程(object-oriented programming,缩写OOP)是否是指针和递归的优质替代品,是不是也能起到淘汰作用。简单的回答是:"不"。我在这里不讨论OOP的优点,我只指出OOP不够难,无法淘汰平庸的程序员。大多数时候,OOP教学的主要内容就是记住一堆专有名词,比如"封装"(encapsulation)和"继承"(inheritance)",然后再做一堆多选题小测验,考你是不是明白"多态"(polymorphism)和"重载"(overloading)的区别。这同历史课上,要求你记住重要的日期和人名,难度差不多。OOP不构成对智力的太大挑战,吓不跑一年级新生。据说,如果你没学好OOP,你的程序依然可以运行,只是维护起来有点难。但是如果你没学好指针,你的程序就会输出一行段错误信息,而且你对什么地方出错了毫无想法,然后你只好停下来,深吸一口气,真正开始努力在两个不同的抽象层次上,同时思考你的程序是如何运行的。

顺便说一句,我有充分理由在这里说,那些使用grep命令过滤简历的招聘经理真是荒谬可笑。我从来没有见过哪个能用Scheme语言、Haskell语言和C语言中的指针编程的人,竟然不能在二天里面学会Java语言,并且写出的Java程序,质量竟然不能胜过那些有5年Java编程经验的人士。不过,人力资源部里那些平庸的懒汉,是无法指望他们听进去这些话的。

再说,计算机系承担的发扬光大计算机科学的使命该怎么办呢?计算机系毕竟不是职业学校啊!训练学生如何在这个行业里工作,不应该是计算机系的任务。这应该是社区高校和政府就业培训计划的任务,那些地方会教给你工作技能。计算机系给予学生的,理应是他们日后生活所需要的基础知识,而不是为学生第一周上班做准备。对不对?

还有,计算机科学是由证明(递归)、算法(递归)、语言(λ演算[10])、操作系统(指针)、编译器(λ演算)所组成的。所以,这就是说那些不教C语言、不教Scheme语言、只教Java语言的学校,实际上根本不是在教授计算机科学。虽然对于真实世界来说,有些概念可能毫无用处,比如函数的科里化(function currying)[11],但是这些知识显然是进入计算机科学研究生院的前提。我不明白,计算机系课程设置委员会中的教授为什么会同意,将课程的难度下降到如此低的地步,以至于他们既无法培养出合格的程序员,甚至也无法培养出合格的能够得到哲学博士PhD学位[12]、进而能够申请教职、与他们竞争工作岗位的研究生。噢,且慢,我说错了。也许我明白原因了。

实际上,如果你回顾和研究学术界在"Java大迁移"(Great Java Shift)中的争论,你会注意到,最大的议题是Java语言是否还不够简单,不适合作为一种教学语言。

我的老天啊,我心里说,他们还在设法让课程变得更简单。为什么不用匙子,干脆把所有东西一勺勺都喂到学生嘴里呢?让我们再请助教帮他们接管考试,这样一来就没有学生会改学"美国研究"[13](American studies)了。如果课程被精心设计,使得所有内容都比原有内容更容易,那么怎么可能期望任何人从这个地方学到任何东西呢?看上去似乎有一个工作小组(Java task force)正在开展工作,创造出一个简化的Java的子集,以便在课堂上教学[14]。这些人的目标是生成一个简化的文档,小心地不让学生纤弱的思想,接触到任何EJB/J2EE的脏东西[15]。这样一来,学生的小脑袋就不会因为遇到有点难度的课程,而感到烦恼了,除非那门课里只要求做一些空前简单的计算机习题。

计算机系如此积极地降低课程难度,有一个理由可以得到最多的赞同,那就是节省出更多的时间,教授真正的属于计算机科学的概念。但是,前提是不能花费整整两节课,向学生讲解诸如Java语言中int和Integer有何区别[16]。好的,如果真是这样,课程6.001就是你的完美选择。你可以先讲Scheme语言,这种教学语言简单到聪明学生大约只用10分钟,就能全部学会。然后,你将这个学期剩下的时间,都用来讲解不动点。

唉。

说了半天,我还是在说要学1和0。

(你学到了1?真幸运啊!我们那时所有人学到的都是0。)

================

注解:

[1] 在美国,法学院的入学者都必须具有本科学位。通常来说,主修政治学的学生升入法学院的机会最大。

[2] 在麻省理工学院,计算机系的课程代码都是以6开头的,6.001表明这是计算机系的最基础课程。

[3] Scheme语言是LISP语言的一个变种,诞生于1975年的MIT,以其对函数式编程的支持而闻名。这种语言在商业领域的应用很少,但是在计算机教育领域内有着广泛影响。

[4] grep是Unix/Linux环境中用于搜索或者过滤内容的命令。这里指的是,某些招聘人员仅仅根据一些关键词来过滤简历,比如本文中的Java。

[5] 段错误(segfault)是segmentation fault的缩写,指的是软件中的一类特定的错误,通常发生在程序试图读取不允许读取的内存地址、或者以非法方式读取内存的时候。

[6] 《四个约克郡男人》(Four Yorkshiremen),是英国电视系列喜剧At Last the 1948 Show中的一部,与上个世纪70年代问世。内容是四个约克郡男人竞相吹嘘,各自的童年是多么困苦,由于内容太夸张,所以显得非常可笑。

[7] MapReduce是一种由Google引入使用的软件框架,用于支持计算机集群环境下,海量数据(PB级别)的并行计算。

[8] Skynet是美国系列电影《终结者》(Terminator)中一个控制一切、与人类为敌的超级计算机系统的名称,通常将其看作虚构的人工智能的代表。

[9] Blub程序员(Blub programmers)指的是那些企图用一种语言,解决所有问题的程序员。Blub是Paul Graham假设的一种高级编程语言。

[10] λ演算(lambda calculus)是一套用于研究函数定义、函数应用和递归的形式系统,在递归理论和函数式编程中有着广泛的应用。

[11] 函数的科里化(function currying)指的是一种多元函数的消元技巧,将其变为一系列只有一元的链式函数。它最早是由美国数学家哈斯格尔·科里(Haskell Curry)提出的,因此而得名。

[12] 在美国,所有基础理论的学科,一律授予的都是哲学博士学位(Doctor of Philosophy),计算机科学系亦是如此。

[13] 美国研究(American studies)是对美国社会的经济、历史、文化等各个方面进行研究的一门学科。这里指的是,计算机系学生不会因为课程太难被淘汰,所以就不用改学相对容易的"美国研究"。

[14] 参见http://www.sigcse.org/topics/javataskforce/java-task-force.pdf。

[15] J2EE是Java2平台企业版(Java 2 Platform,Enterprise Edition),指的是一整套企业级开发架构。EJB(Enterprise JavaBean)属于J2EE的一部分,是一个基于组件的企业级开发规范。它们通常被认为是Java中相对较难的部分。

[16] 在Java语言中,int是一种数据类型,表示整数,而Integer是一个适用于面向对象编程的类,表示整数对象。两者的涵义和性质都不一样。

(完)

留言(80条)

啊哈哈……我们在学单片机的时候认真学习了汇编,所以对指针的概念十分了解,在学Mathematica的时候认真学过函数式编程,把SICP认真学了一遍,所以对Lambda演算也很了解。但是我真是没做到花一两天就学会Java……

说Java可能不是足够简单,是希望避免编程语言(比如Java)特性的复杂性掩盖了实际问题.

实际上,各种编程语言的怪僻行为本来就与CS无关..
因为,没有教授在数据结构课上想给学生讲解"如果你在Java的注释中加入\unit这样的东西会让你的程序编译不过"这样的内容.

不动点?定点?我不清楚那个术语。

峰兄,辛苦了。给你千字千元都不贵,要花那么多的心思。虽然我看不懂内容,但能看出努力。

“计算机科学是由证明(递归)、算法(递归)、语言(λ演算[10])、操作系统(指针)、编译器(λ演算)所组成的。所以,这就是说那些不教C语言、不教Scheme语言、只教Java语言的学校,实际上根本不是在教授计算机科学。”

现在看来,真的是这么回事。但读书的时候,真的常常抱怨。
指针什么的,觉得还不算难。不过到编译原理时,彻底崩溃了。

implementation language 翻译为开发语言,是不是不太恰当,实施/实现语言,如何?

“以及其他诸如此类的课程” with extensive use of pointers 没有翻译出来哦。呵呵

图灵公司找对人了。比我翻的好,哈哈。虽然,偶也算是cs专业的。

我觉得翻译得已经很不错了 ,很流畅
注解的也很到位,考虑到读者人群,程序员不怎么需要注解就能理解作者在说什么,而简短的注解也有利于非计算机专业的读者查询理解

原作者在極力的論證一個觀點——計算機科學是聰明人的專利,任何智商不過關的人進入這個行業都是對從業者智商的褻瀆,包括“我”。
好吧,計算機科學和計算機工業的確不是一碼事,這點我確信原作者搞混了。

^H^H^H^H^H^H 在Unix世界好像有个特别含义,我记不清了。阮老大不妨考证下,翻错了就不好了。

我学了C语言的 ,
应该……

作者对于Java的技术含量的贬低显得过于武断了,但是他要证明的论点是正确的。

翻译得很不错,我是学Java的,文中说到的SICP这本书只看了前面几章,确实很有难度,不过也很有趣。

软件学院教出来的是做软件民工,大把的软件公司只需要会java的人。混口饭吃。

引用无名的发言:

^H^H^H^H^H^H 在Unix世界好像有个特别含义,我记不清了。阮老大不妨考证下,翻错了就不好了。

就是为了这12个符号,我花了一个多小时考证呢。最后找不到有其他涵义的证据,才译成现在的样子。
引用jt的发言:

implementation language 翻译为开发语言,是不是不太恰当,实施/实现语言,如何?

我想过按照字面译成“实施语言”,但是觉得“开发语言”是现成的名词,有助于译文的流畅。而且二者的意思,说实话,我看不出有区别。

感觉你做的事情好多啊,
可是,想知道你的主业或专业是什么呢?
注:这里的主业或专业,指的是你愿意付出最多并追求在这一领域成为数一数二的人物。

我也是ET加CS的老学生了。用了很久的C++但是也没有做到"一两天就学会Java……哈哈"。但是C语言的确很重要,不会指针和递归,不算是学CS的人。
BTW,很久之前我看过原版,你翻译得非常好。

阮老大,我一直在看你的blog,今天我看你提到MIT学校的SICP这本书,你提到

你还会遇到一个不动点函数(fixed-point function),它的自变量本身就是另一个函数

我想这个所谓的不动点函数(fixed-point function),在SICP里面应该有一个名字叫做高阶函数或者高阶过程。我手头正好有一本SICP,原书第二版的中文版,在P37页。我抄写一下吧:然而即使在数值计算过程中,如果将过程限制为只能以数作为参数,那也会严重的限制我们建立抽象的能力,经常有一些同样的的程序设计模式能适用于若干不同的过程。为了把这种模式描述为相应的概念,我们就需要构造出这样的过程,让他们以过程作为参数,或者以过程作为返回值,这类操作过程的过程称为高阶过程。

翻译的很流畅。
虽然我不学计算机,但一口气读完了。
加油!

实际上...汇编和函数式语言最好也学,然后就行了。

翻译得不错~

不过最后一段
*"The most sympathetic interpretation "*
翻译成
*"最合理的解释"*
是不是更"合理"一点?

那个skynet^H^H^H^H^H^H,一个^H表示一个退格键,所以作者的意思其实是要删除那个skynet单词,而不是H次方。

确实,^H 是退格,也就是Ctrl+H,用过shell的就知道。

作者用^H表示要删除那个字眼。但又把它写出来,意思应该是,google是在建skynet,但我们不能说喔。skynet这个系统很邪恶的。

集体智慧就是强大啊。楼上两位对于^H的解释正确。
这里Joel先透露了skynet计划,然后又表示“当我没说过”。是一种幽默。

呵呵,博主在实验wiki化翻译吗?看来效果很不错哦!

不得不说一句,博主的翻译质量比译言上大多数文章好太多

翻译得很好,补充几点:

1. 其实SICP就出过两版,第二版在网上可以免费阅读,并不是作者所说的“你能在网上找到这本教材的旧版本”。

2. “在第一堂课,你就要学完Scheme语言[3]的几乎所有内容,你还会遇到一个不动点函数(fixed-point function),它的自变量本身就是另一个函数。”窃以为用“参数”代替“自变量”更好。

3. ^H表示退格,哈哈,不就呼应了文章开头说punch card不能退格了吗?确实在有些古董终端或者没有设置好的程序上,按backspace不能退格而是给你显示一个^H.

4. 原文最后一句“You had ones? Lucky bastard! All we got were zeros.”实在是没看懂。

OK,关于第一条,我看了一下原文,是你翻错了。作者指的是,网上有课程的老版录像,并不是说课本。

留言的这几位兄弟都很强大

确实在有些古董终端或者没有设置好的程序上,按backspace不能退格而是给你显示一个^H.

-----------------------------
Unix上一直如此啊

能解释下为什么 Ph.D. 不直接译成理学博士吗?这样让人感觉很怪异。

引用11的发言:

不过最后一段
*"The most sympathetic interpretation "*
翻译成
*"最合理的解释"*
是不是更"合理"一点?

sympathetic没有“合理”的意思啊。但是,我的那一句也译得不好。
引用NickyHu的发言:

我想这个所谓的不动点函数(fixed-point function),在SICP里面应该有一个名字叫做高阶函数或者高阶过程。

fixed-point theorem在经济学里就叫做不动点定理,这个我很清楚。因为我试图学过,但是没学会……至于它在CS里有没有别的名称,我不知道,但是我觉得肯定不是高阶过程,因为同英文原名差的太远了。

引用Shawn的发言:

那个skynet^H^H^H^H^H^H,一个^H表示一个退格键,所以作者的意思其实是要删除那个skynet单词,而不是H次方。

引用kylexlau的发言:

确实,^H 是退格,也就是Ctrl+H,用过shell的就知道。

作者用^H表示要删除那个字眼。但又把它写出来,意思应该是,google是在建skynet,但我们不能说喔。skynet这个系统很邪恶的。

多谢二位提供宝贵意见,应该就是“退格”的意思。我把译文改成了“Google已经转向了下一个阶段,开发世界上最大的并行式超级计算机,不把Skynet 铲除掉誓不罢休。”

引用roy_hu的发言:

OK,关于第一条,我看了一下原文,是你翻错了。作者指的是,网上有课程的老版录像,并不是说课本。

引用roy_hu的发言:

2. “在第一堂课,你就要学完Scheme语言[3]的几乎所有内容,你还会遇到一个不动点函数(fixed-point function),它的自变量本身就是另一个函数。”窃以为用“参数”代替“自变量”更好。

谢谢指出这二点,都按照你的意见改了。

引用pingz的发言:
能解释下为什么 Ph.D. 不直接译成理学博士吗?这样让人感觉很怪异。

美国没有理学博士的,物理博士拿的也是哲学博士学位。关键是你要把哲学理解成“智慧之学”就行了。

引用Ruan YiFeng的发言:

fixed-point theorem在经济学里就叫做不动点定理,这个我很清楚。因为我试图学过,但是没学会……至于它在CS里有没有别的名称,我不知道,但是我觉得肯定不是高阶过程,因为同英文原名差的太远了。

fixed-point function翻译成不动点函数没错。它是一种高阶函数(higher-order function),但在这里不能直接翻译成高阶函数,因为两个术语并不等价。

引用Ruan YiFeng的发言:

多谢二位提供宝贵意见,应该就是“退格”的意思。我把译文改成了“Google已经转向了下一个阶段,开发世界上最大的并行式超级计算机,不把Skynet 铲除掉誓不罢休。”

作者的意思是,Google要开发的超级计算机系统,最终可能成为像skynet那样不可控制的系统。要铲除掉skynet的意思,从何而来?现在还没有skynet呢。

Google is becoming skynet,是很多人在担忧的事情。参考http://msforums.ph/forums/p/49739/242937.aspx,正好这里也提到了^H的幽默,可以参照。

The most sympathetic interpretation => 最善意的解释?

The lucky kids of JavaSchools are never going to get weird segfaults trying to implement pointer-based hash tables. 翻译成 "当他们用到以指针为基础的哈希表时,他们永远也不会遇到古怪的段错误" 是不是有问题啊?原文是在表达"去实现以指针为基础的哈希表,在这个过程中遇到了段错误"吧.

关于"pack things into bits",找到一段话:
Perl's pack and unpack functions allow us to read and write buffers of data according to a template string. The template string allows us to indicate specific byte orderings and word sizes or use the local system's default sizes and ordering. This gives us a great deal of flexibility when dealing with external programs.
出自http://www.perlmonks.org/?node_id=224666
大概打包成位元主要是为了正确地更有效率地进行某些底层通讯吧.所以'pack'是一种转换.

引用kylexlau的发言:

作者的意思是,Google要开发的超级计算机系统,最终可能成为像skynet那样不可控制的系统。要铲除掉skynet的意思,从何而来?现在还没有skynet呢。
Google is becoming skynet,是很多人在担忧的事情。参考http://msforums.ph/forums/p/49739/242937.aspx,正好这里也提到了^H的幽默,可以参照。


Skynet是一个很响亮的名字,阿诺施瓦辛格主演的经典系列电影《终结者》里面的统治人类的超级计算机网络。
Google好谦虚~~~

翻译得太棒了~~~
非常喜欢作者的见解~~~
期待后面的内容^_^

請問版主知道這個網頁嗎?

http://local.joelonsoftware.com/mediawiki/index.php/Main_Page

看的出來版主下了一番功夫,翻譯的不錯

引用kylexlau的发言:
作者的意思是,Google要开发的超级计算机系统,最终可能成为像skynet那样不可控制的系统。要铲除掉skynet的意思,从何而来?现在还没有skynet呢。

6次退格键,不正是删除Skynet这个词吗?

至于说到现在还没有Skynet,我认为Joel在这里是针对电影情节而言的。

引用路人的发言:

請問版主知道這個網頁嗎?

http://local.joelonsoftware.com/mediawiki/index.php/Main_Page

看的出來版主下了一番功夫,翻譯的不錯

我参考了上面的翻译,有些地方非常有启发。不过,总的来说,那里的错误不少。

引用必填的发言:

The most sympathetic interpretation => 最善意的解释?

意思是没错,但是哪一种说法好?

1)计算机系如此积极地降低课程难度,有一个理由我最赞同

2)计算机系如此积极地降低课程难度,有一个最善意的解释

好像有一些区别,让我再斟酌一下。

总体质量相当不错。图灵为你自豪啦。

有几个小地方供你参考:
1. 作为补充说明中文意思的括号里的英文,一般我们不要那个表示复数的s(除非s不可删,比如Windows Forms),只是说明前面的名词而已。否则,你无法说出规则,为什么有些是单数,有些是复数。
2. 哈希表是老说法,现在的标准改为“散列表”了。请注意。哈希这个译法显然是前人误以为Hash是个人名。
3. linked list是链表。线性表=Linear list。好像没有线性链表的说法。
4. “他们不需要怎么动脑筋,就可以在专业上得到4.0的绩点。”绩点这个词太生涩了,不如就译为“成绩”。

一个关键的建议:自己感觉比较别扭的地方,不要隐藏起来,暴露在稿子里(用批注、颜色突出),留待其他人解决。翻译之难,一个人不可能解决所有问题。

对了,你进了图灵俱乐部论坛了吗?论坛里有精通各种技术的热心伙伴,各种问题,都可以讨论。请记住:你不是一个人在战斗!

引用Ruan YiFeng的发言:
6次退格键,不正是删除Skynet这个词吗?

至于说到现在还没有Skynet,我认为Joel在这里是针对电影情节而言的。

我相信,如果你去google下'google skynet',在第一页里的网页中随便挑几个扫两眼,你绝对会改变你的想法的。

刚好今天看到了wiki上这个关于^H的页面,供你参考:
http://en.wikipedia.org/wiki/Backspace,其中提到

Terminals which did not have the backspace code mapped to the function of moving the cursor backwards and deleting the preceding character would display the symbols ^H (caret, H — see Caret notation) when the backspace key was pressed. This sequence is still used humorously by computer literates to denote the deletion of a pretended blunder, much like overstriking.

Example: My slave-dri^H^H^H^H^H^H^H^H^Hboss decided to stall the project.

我觉得可以用删除线来翻译,skynet。

另外the most sympathetic那句,我觉得可以翻成“...计算机系争先恐后地降低课程的智商要求,如果尽量从善意的角度去理解的话,或许可以说这是为了留出更多的时间...”

还有最后一句,我的理解是
“--我要回到零和一的机器码时代。
--什么,你那时候还有一?好狗运!我们就只有零。”
好像也是在模仿Four Yorkshiremen。

你的留言系统不支持html里的尖括号del...

引用图灵刘江的发言:

1. 作为补充说明中文意思的括号里的英文,一般我们不要那个表示复数的s(除非s不可删,比如Windows Forms),只是说明前面的名词而已。否则,你无法说出规则,为什么有些是单数,有些是复数。

2. 哈希表是老说法,现在的标准改为“散列表”了。请注意。哈希这个译法显然是前人误以为Hash是个人名。
3. linked list是链表。线性表=Linear list。好像没有线性链表的说法。
4. “他们不需要怎么动脑筋,就可以在专业上得到4.0的绩点。”绩点这个词太生涩了,不如就译为“成绩”。

1)已把多余的s都去掉了。我是在原文电子稿上直接翻译,有时就忽略了复数问题。

2)google上搜索的结果是,“哈希表”的说法比“散列表”多很多,我本人也更接受“哈希表”,我建议这个就不改了吧。

3)已经改成了“链表”。

4)原文应该指的是GPA“绩点”,而不是5分制里的4分。

引用必填的发言:

我觉得可以用删除线来翻译,skynet。

另外the most sympathetic那句,我觉得可以翻成“...计算机系争先恐后地降低课程的智商要求,如果尽量从善意的角度去理解的话,或许可以说这是为了留出更多的时间...”

还有最后一句,我的理解是
“--我要回到零和一的机器码时代。
--什么,你那时候还有一?好狗运!我们就只有零。”
好像也是在模仿Four Yorkshiremen。

Skynet^H^H^H^H^H^H有两种可能,一种是google要“删除”Skynet,另一种是作者要删除Skynet。我现在觉得是第二种意思了。

我觉得,“如果尽量从善意的角度去理解的话”不如“最善意的解释”简洁。

至于最后一句话,我还是没理解。只能依样画葫芦地译了。“你有1?幸运的家伙!我们那时所有人得到的都是0。”有可能,1和0同不动点定理有关。

博主太固执于^H的本意“删除”了,实际上它的惯常用法就是一种幽默。在这里可理解为“我什么都没说过,与我无关哪”。
前面已经有几位朋友表达了类似的想法。看得出来,你始终不接受这个观点。

最后一句话的zeros可能与早期的打孔纸带上面的圆洞有关

我第一次到这个博客,结果呢,一个上午就在这里了。
看了很多的文章,特别是后面的评论,感觉真的不错。
我是计算机专业的一名研究生,看到这篇译文,这才是真的翻译阿,比起那些机械工业出版社的翻译版书籍,真是好的多了。
在这里,希望博主再接再厉。

引用无名的发言:

博主太固执于^H的本意“删除”了,实际上它的惯常用法就是一种幽默。在这里可理解为“我什么都没说过,与我无关哪”。
前面已经有几位朋友表达了类似的想法。看得出来,你始终不接受这个观点。

顶你。 原作者是幽默的意思,模拟了他在写作中的操作——“打出了skynet,又删掉了”——因为这个是大家对google的一种担心,不是没有证据,但是也没有确凿的证据。 ruan一开始误解了,现在应该接受这个意思了。

很精彩啊,上一个公司翻译的这本书,简直是糟蹋啊
期待着这本书!!!
谢谢 老阮
谢谢 灵图公司!!

请问 more joel on software 是否一起翻译呢?
谢谢..

关于^H的解释, 我也写了一篇文章, http://xdaqing.blogbus.com/logs/35211245.html

“skynet^H^H^H^H^H^H"这种写法是模拟了一个输入序列, 就是先输入了"skynet", 又按了6次"Control-H"(表示退格)把这6个字母删掉.

这是中幽默的表达方式, 意思是就当我没说过"skynet"这种东西。

引用daqing的发言:
关于^H的解释, 我也写了一篇文章, http://xdaqing.blogbus.com/logs/35211245.html “skynet^H^H^H^H^H^H"这种写法是模拟了一个输入序列, 就是先输入了"skynet", 又按了6次"Control-H"(表示退格)把这6个字母删掉. 这是中幽默的表达方式, 意思是就当我没说过"skynet"这种东西。
我觉得这个就是书中作者一直强调的的聪明人类型,不仅聪明,而且懂得幽默。Cool!

这篇文章的作者数理思维很强!但他恐怕不懂得哲学。

个人感觉JAVA和OO的主要意义是在于将编程从复杂的底层数学逻辑中抽象出来,使得编程更接近于人的直觉。站在人的角度,而不是机器的角度思考!

很关注C,很想学习的底层的东西,但是仍然可以确定java还有很强的生命力,互联网(BS)和移动开发(android)将会是未来软件开发的趋势,所以这个不够聪明的语言仍然有广泛的应用前景

引用xiaoyu的发言:
个人感觉JAVA和OO的主要意义是在于将编程从复杂的底层数学逻辑中抽象出来,使得编程更接近于人的直觉。站在人的角度,而不是机器的角度思考!

什么跟什么...数学和逻辑是底层的?函数式程序设计的粉丝们估计要“情何以堪”一下了...建议了解一下Haskell和ML家族甚至整个程序设计语言理论领域的研究工作,OO这种东西在学术界里就是一小旮旯。

其实真正的学会j2ee就很不容易了!但外国人看这个是不是特别简单啊!但国人学会这东西真的捏一把汗啊!

关于文章中的fixed-point-function,应该是指这个 http://en.wikipedia.org/wiki/Fixed-point_combinator 我在Y Combinator里看到过。这个概念

貌似MIT现在都把python当做入门语言了

http://danweinreb.org/blog/why-did-mit-switch-from-scheme-to-python


作者放着更傻瓜的各种动态语言不说,关一个劲地骂Java。
Python程序员、PHP程序员、javascript程序员是不是都笑而不语了。。

翻译的比我看过的那些外国计算机教材中文译本强多了。
另外看完这些评论,最佩服的就是你们严谨的治学态度。

引用Ruan YiFeng的发言:


我想过按照字面译成“实施语言”,但是觉得“开发语言”是现成的名词,有助于译文的流畅。而且二者的意思,说实话,我看不出有区别。

关于^H^H^H的一些解释:http://answers.google.com/answers/threadview/id/386870.html

另外SICP真的是一本非常好的书,6.001也是非常好的课程,即使是公开的1986年的教学视频也让今天的我受益匪浅。真的很遗憾国内没有类似的课程作为计算机专业的导论。

刚刚开始学scheme。作为入门课,真的让我很头疼。有关tree的,感觉特别难。我在重新考虑是不是这表示我不适合学CS了。

哈哈 回头看看 java现在真的是非常难 结构非常复杂 你不仅要会写 还得懂虚拟机 难度超越其他语言

第一门语言就是java...半路出家...乘着学校最后两年好好练好内功

引用等的发言:

哈哈 回头看看 java现在真的是非常难 结构非常复杂 你不仅要会写 还得懂虚拟机 难度超越其他语言

现在有多少JAVA工程师懂虚拟机呢?

至少我见过公司里面的JAVA工程师,每一个了解过虚拟机的概念。

可以无限的开启线程,是他们的专利。

写这篇文章的人的思想和希特勒有区别吗?请问?

指针这种artifact还好意思和递归相提并论……?(C那种)指针是个显然的烂设计。比指针更一般的抽象多得是,然而原作者还是图样。

引用Nexus的发言:

啊哈哈……我们在学单片机的时候认真学习了汇编,所以对指针的概念十分了解,在学Mathematica的时候认真学过函数式编程,把SICP认真学了一遍,所以对Lambda演算也很了解。但是我真是没做到花一两天就学会Java……

看什么算学会。
啃spec的话,JLS的核心语言特性比ISO C和ISO C++加起来还多,而且并不方便分拆。
“认真学习了汇编,所以对指针的概念十分了解”基本就是现行反面教材了,因为汇编中所说的指针和高级语言常见的指针其实根本就是两回事,尽管从一开始的动机和语源来讲有那么点关联。

引用Denmark的发言:

说Java可能不是足够简单,是希望避免编程语言(比如Java)特性的复杂性掩盖了实际问题.

实际上,各种编程语言的怪僻行为本来就与CS无关..
因为,没有教授在数据结构课上想给学生讲解"如果你在Java的注释中加入\unit这样的东西会让你的程序编译不过"这样的内容.

和不少人想的正好相反,这里真正严重的“实际问题”就是因为太拘泥“实际问题”——而不是尽量把问题抽象为能让计算机解决的问题使解决方案变得更可行,更易于满足工程需求(比如降低成本)。当然,政治需求另说。
而尽量使用语言的抽象而避免冗余的不严谨的自然语言描述恰恰是其中最有效的手段之一。
这样的问题和CS显然有关。像注释加入\unit这样的东西被用于形式验证也不算什么新闻了。(当然,你可以硬说它是数学而不是CS,顺带把自动机理论啥的都踢出去。)
当然实施成本仍然是个问题——这跟CS关系不太大,仍然有关。

引用xiaoyu的发言:

这篇文章的作者数理思维很强!但他恐怕不懂得哲学。

个人感觉JAVA和OO的主要意义是在于将编程从复杂的底层数学逻辑中抽象出来,使得编程更接近于人的直觉。站在人的角度,而不是机器的角度思考!

想多了,Java一开始就是要降低智商门槛而已。
然而这并没有消灭问题本身,结果不能满足一些需求还要另外擦屁股。这样,工程上仍然是相当失败的。注意,“接近于人的直觉”不是直接的需求,必要时就应当舍弃。
至于语言的设计者自己抽风偏执狂搞出来一坨翔还有跟风洗地的,那是和这里主题没直接关联的另一回事。

引用jockey的发言:
什么跟什么...数学和逻辑是底层的?函数式程序设计的粉丝们估计要“情何以堪”一下了...建议了解一下Haskell和ML家族甚至整个程序设计语言理论领域的研究工作,OO这种东西在学术界里就是一小旮旯。

无关FP与否,数学和(形式)逻辑就是相当底层的东西。
这不是说底层的不一定普遍适用。注意底层是说被依赖的层次而不是抽象的程度(低级)。

引用bqdx的发言:

貌似MIT现在都把python当做入门语言了

http://danweinreb.org/blog/why-did-mit-switch-from-scheme-to-python


作者放着更傻瓜的各种动态语言不说,关一个劲地骂Java。
Python程序员、PHP程序员、javascript程序员是不是都笑而不语了。。


那是什么时候的事了……
动态语言显然未必更傻瓜。
py的逗比之处不是常识么。拍黄片不评论。js倒是更接近设计烂了的Scheme,倒是能点了perils的题。

跟语言无关,只要能解决现实存在的需求问题,就是好的工具

论文本身就片面 如果说整个世界的技术员都研究所谓最好的技术又能怎样 世界本来就是多元化的 多元化才意味着有更多不同的发展和结果 市场需求会催促技术进步 不要拿技术危险 来骗人 如果某天市场需求变化了 技术结构也自然会变化

感觉有些人学术式的评论真是搞笑,你回到当初开发语言的环境看 你才能明白为什么这些语言会出现 你们还要批判这种工具 却不知道他们的背景 不是搞笑吗

引用等的发言:

哈哈 回头看看 java现在真的是非常难 结构非常复杂 你不仅要会写 还得懂虚拟机 难度超越其他语言

你是在搞笑吗?哪个认真学C的会不去看看汇编长什么样,什么链接过程,什么动态库加载,什么延迟符号链接,接下来 linux kernel, 什么编译器乱序,什么CPU乱序,什么内存barrier, 你真的是在说Java比较难?

引用幻の上帝的发言:

指针这种artifact还好意思和递归相提并论……?(C那种)指针是个显然的烂设计。比指针更一般的抽象多得是,然而原作者还是图样。

和不少人想的正好相反,这里真正严重的“实际问题”就是因为太拘泥“实际问题”——而不是尽量把问题抽象为能让计算机解决的问题使解决方案变得更可行,更易于满足工程需求(比如降低成本)。当然,政治需求另说。
而尽量使用语言的抽象而避免冗余的不严谨的自然语言描述恰恰是其中最有效的手段之一。
这样的问题和CS显然有关。像注释加入\unit这样的东西被用于形式验证也不算什么新闻了。(当然,你可以硬说它是数学而不是CS,顺带把自动机理论啥的都踢出去。)
当然实施成本仍然是个问题——这跟CS关系不太大,仍然有关。

擦,这里也遇见帝球。你特么真是无处不在。

顺便也扯下指针的事情。C的层面来看指针是带有类型信息的,而且由编译器维护指针的概念,所以说从汇编代码去看指针什么的确实鬼扯。至于说指针设计有多烂倒未必,C反正就是那么dirty,给工程师用挺好的。要我来鬼扯的话,scheme里面的list, car cdr cons的不就是一对指针嘛(啊?我又错了?虐我吧哈哈)

同意p**n 说的“跟语言无关,只要能解决现实存在的需求问题,就是好的工具”!
其实作者只是在说java无法区分优秀程序员和普通程序员而已,并没有全盘否定java。单纯脱离特地环境来评论一个语言的好坏,本事就是错误的。你用c写网络程序试试,你用java写桌面程序试试?

今天上网找ES6教程的时候进来了,发现之前大学里面图书馆读过的对我受益匪浅的《黑客与画家》这本书竟然是你翻译的,真是相遇恨晚呐。
同时看完这篇文章之后,想说,写的很好,很用心,让人看了陷入深深的沉思。在学校还抱怨过学校学的东西没有培训机构学的东西能够直接作出项目来,但现在越来越发现,学校学的数据结构,C语言等才是真正的知识。
膜拜,大神。

说的好像不是从C入门就完蛋了一样,计算机从来都是一个数学计算的工具,算法、数据结构可以跟任何的语言都没有关系,更不要说离散数学这些纯数学。
然后像数据结构这些课程不用一些更简单的语言进行教授不是扯淡,难道学个数据结构还要花大力气关注某个节点内存是否已经被释放,这样只会浪费学生的精力去关注一些细枝末节而不是关注一个数据结构本质特征,在这点上Python真的很适合用来教数据结构
主要课程中跟C较大关系的是操作系统

今天回来看,C语言用的已经不多了,而且现代C语言里面为了实现设计模式已经快把函数指针玩坏了。再看C++,智能指针,auto推断,lambda。再看JAVA,var定义变量,lambda。 除了C语言,其他的所有语言的同质化越来越严重了,学习一门语言确实可以在两天内搞定,BUT,BUT,一门语言有太多附加的东西要学,尤其是框架

感谢阮老师。
以前我总是抱怨大学教的东西没有作用,和工作没有太大关系。看了这篇文章,我基本上理解了大学的教学目的,当然后面我也自然而然地这么认为了,我发现自己自学能力很强,才知道,为什么要去大学读书。
只是,在学这些基础课程的时候,没有老师跟我们聊过这些思想性的内容。不过,可能当时和我们聊我们也听不懂吧。
PHD, 终于明白为什么是PHD了。只有思想上(道)融会贯通,才不会为一些术而迷惑。感谢阮博,很有启发

我要发表看法

«-必填

«-必填,不公开

«-我信任你,不会填写广告链接