为什么每个人都这么着急?

随便走进任何一家书店,你都可以看到 Teach Yourself Java in 24 Hours 与其他很多类似的书摆在一起:它们声称能在几天或者几小时内教会你编写 C、SQL、Ruby 等语言及算法代码。亚马逊高级查询( title: teach, yourself, hours, since: 2000)的结果显示,诸如此类的图书共有五百一十二种。前十名或前九名均为编程类书籍。如果你用 “learn” 替换 “teach yourself”,或用 “hours” 替换 “days”,也能得到类似的结果。

可能的结论:人们要么正在急急忙忙地学习计算机编程,要么就是计算机编程相比其他东西更容易学习。Felleisen 等人针对这种趋势在 How to Design Programs 一书中给予了这样评论:“糟糕的编程很容易上手,傻子都能在二十一天内学会,即使他们愚蠢得一塌糊涂。” Abstruse Goose 漫画也对这种现象表达了同样的讽刺

我们来分析一下,一本名曰 Teach Yourself C++ in 24 Hours 的书究竟意味着什么:

  • Teach Yourself: 在二十四个小时里,你没有时间写出一些意义重大的程序,你无法从成功或失败中获益。你没有时间与有经验的程序员一起合作,也无法理解真实的工作场景。简言之,你不会有时间学习太多东西。所以说这本书只会谈论一些浅表知识,而不是深入理解。正如 Alexander 教皇所说,浅尝辄止是件危险的事儿。
  • C++: 在二十四个小时里,你可能会学到一些 C++ 语法(如果你已经学过类似的语言),但你学不到更多的如何使用这些语法的知识。也就是说,如果你曾是一位 BASIC 程序员,你可以学着用 C++ 语言写出类似 BASIC 风格的程序,但你不可能真正了解到 C++ 的好处(以及坏处)。那么要点是什么呢?Alan Perlis 说过:“一种无法改变你编程思维方式的语言,不值得学习。” 有一种可能的情况:你必须学到一点 C++ 的知识(或者更有可能是 JavaScript 或 Processing 之类),主要是因为你需要利用现有工具或接口来完成某个特定的任务。不过那不是学习如何编程,而是在学习如何完成某个特定的任务。
  • in 24 Hours: 很不幸,这根本不够,原因下一节予以解释。

学习编程十年路

研究表明 (Bloom (1985), Bryan & Harter (1899), Hayes (1989), Simmon & Chase (1973)),在任何一种领域,诸如下棋、作曲、绘画、钢琴演奏、游泳、网球、以及神经心理学和拓扑学等,想要成为合格的专业人才,都要大约十年左右的时间。成功的关键就在于刻意练习:不是一遍又一遍的重复,而是每次任务刚好超越你当前的能力,努力尝试达成这些任务,分析你的每一次结果,纠正任何出现的错误。然后不断重复这个过程。没有真正的捷径:即使四岁已是音乐神童的莫扎特,十三年后才开始写出世界级的作品。在另一个音乐流派中,披头士似乎是在1964年的 Ed Sullivan 表演上一炮走红。但他们从1957年起就开始在利物浦和汉堡的小型俱乐部中表演,在获得大众青睐之后,他们的第一个重大成功 - Sgt. Peppers 专辑的发行日期是1967年。Malcolm Gladwell 推广了这套理论,尽管其更多强调的是一万小时,而不是十年。

一万小时才是那个神奇的数字,而不是十年,或许还有其他类似的测量方式。Henri Cartier Bresson(1908-2004,摄影大师)说过,“你前一万张照片最烂。” 真正的专业技能需要花费一生的时间:Samuel Johnson(1709-1784,英国作家)甚至认为十年时间远远不够:“在任何领域想要出类拔萃,都要用毕生的努力方可获得,你不可能轻易成功。” 而 Chaucer(1340-1400,英国文学之父)则感叹:“人生短暂,学海无涯。” Hippocrates(公元前400年,现代医学之父)也因为其名言 “吾生有涯,而知无涯” 而闻名遐迩。当然,没有任何一个数字能成为终极答案。诸如编程、下棋、演奏音乐等技能,我们不可能要求掌握这些技能应该花费同样数量的时间,也不可能要求每个人花费的时间完全一致,这种假设既不合理,也不存在。

你想要成为一名程序员

以下就是我的成功秘诀:

  • 对编程发生兴趣,要为了乐趣而编程。确保你的编程之路充满乐趣,只有这样,你才情愿投入宝贵的十年时间或者一万小时。
  • 编写程序。最好的学习方式就是从实践中学习。用更技术的话说就是:“在一个给定的领域,个人的最大能力不是经验自动扩展的结果,而是刻意努力提高的结果” 以及 “最有效的学习需要目标明确且难度适当的任务、丰富的信息反馈、重复和错误修正的机会。” Cognition in Practice: Mind,Mathematics,and Culture in Everyday Life 一书就是这种观点的一份有趣的参考文档。
  • 与其他程序员交流,阅读别人编写的程序。这将比任何书本或培训课程都重要。
  • 如果你愿意的话,在大学呆上四年或者更长(在研究生院)时间。你能接触到 一些需要学历证明的工作,你对这个领域将有更深刻的理解。如果你不喜欢学校这种学习方式,你也可以从实际工作中获得与学校相似的经历。不管怎样,光啃书本是不够的。The New Hacker's Dictionary 一书的作者 Eric Raymond 说过,“计算机科学不可能把任何人变成编程专家,正如仅仅研究刷子和颜料不会使一个人变成画家一样。” 曾经受雇于我的最好的程序员之一仅有高中学历。他开发了很多优秀软件,他有自己的新闻组,而且,凭借股票期权,他购买了自己的夜总会
  • 与其他程序员共同开发项目。在一些项目中,你可能是最好的程序员。而在另一些项目中,你可能是最差的。当你是最好程序员时,你可以检验你的项目领导能力,用你的观点激发他人。当你是最差程序员时,你就能知道大师们正在做什么,还有他们不喜欢做什么(因为他们吩咐你去做)。
  • 接手其他程序员开发的项目。训练自己理解别人写的程序。当程序原作者不在时,搞清楚需要理解那些东西以及如何修复错误。思考如何设计程序才能方便后来者维护程序。
  • 学习至少半打编程语言。包括一种强调类抽象的语言(Java 或 C++),一种支持函数化抽象的语言(Lisp 或 ML 或 Haskell),一种支持语法抽象的语言(Lisp),一种支持声明式规格说明的语言( Prolog 或 C++ 模板),一种特别强调并行计算的语言(Clojure 或 Go)。
  • 不要忘了“计算机科学”中的“计算机”一词。知道计算机的相关开销时间:执行一条指令,从内存读取一个 word(分为有无缓存两种情况),从磁盘读取字符串, 以及在磁盘中寻找新位置。
  • 参与一门语言的标准制定工作。既可以是类似 ANSI C++ 委员会,也可以是应该缩进两个还是四个空格的编程风格决策。不管哪种方式,你都能了解到其他人在一种语言上的想法,他们的理解深度,甚至导致他们这样想的原因。
  • 选择合适时机尽快离开语言标准制定工作。

当你明白了这些,仅从书本学习就会让你心生狐疑。在我的第一个孩子出生前,我几乎读遍了关于育儿的指南书,但感觉依然像个手足无措的新手。三十个月后,我的第二个孩子快要出生时,我又重温了这些书籍吗? 当然没有。与之相反,我这次依靠我的个人经验,它比专家所著的厚达数千页的专著更有用、更可靠。

Fred Brooks 在他的文章 No Silver Bullet 中描绘了一个寻找优秀软件设计者的三步规划:

  1. 优秀的软件设计者需要尽早且系统地发掘和发现。
  2. 指派一位职业导师,负责他们职业生涯的发展。
  3. 为他们提供彼此交流的机会,并鼓励他们相互学习。

这项规划认为有人已经具备了成为优秀软件设计者的必要才能,我们的核心任务只是恰当地引导他们。Alan Perlis 对此给予了更加简洁的表述:“每个人都能学会雕刻:对米开朗其罗而言,告诉他不要做哪些事情反而更为重要。同样道理优秀程序员也适用。” Alan Perlis 想说的是,优秀的人都具有超越任何培训目标的内在品质。但是,这些品质从何而来呢?与生俱来的吗?或者是勤奋努力的结果?传说中的厨神 Auguste Gusteau 说过,“任何人都可以下厨,但只有无畏者才能成为大厨。” 我认为这主要应该归功于大量自觉自愿的刻意练习。但是无畏或许就是对这种方法的一个简单总结吧。正如 Gusteau 的批评者 Anton Ego 所言:“不是每个人都能成为杰出的艺术家,但是杰出的艺术家将来自四面八方。”

因此,尽管去买那本 Java/Ruby/Javascript/PHP 书吧。你或许可以从中学到点儿东西,但是这不会改变你的生活,或者,作为一名程序员,它不会在二十一天内或二十四小时内,改变你的整体专业技能状态。持续努力二十四个月怎么样?好的,这才是你开始迈向某处的一个真正起点...


作者:Peter Norvig,计算机科学家,人工智能大牛,Google 研究院院长。

原文:Teach Yourself Programming in Ten Years

参考:十年学会编程

感谢: Qingniu 帮助审阅并完成校对。