“十年学会编程”


为什么大家都这么着急?

走进书店,你会看到类似 24 小时教会你 Java 之类教你 C、SQL、Ruby、算法等的的书,都号称几天或者几小时教会你,在亚马逊搜索类似“几小时自学 xxx”之类的标题能搜到至少 512 本此类书籍,在最热销的十本里有九本是编程书籍(剩下的一本是关于记账的)。将关键词从“自学”换成“学习”,将“几小时”换成“几天”会得到相似的结果。 因此可以得出结论:要么是大家非常着急的想要学会编程,要么是编程要比其他东西容易学得多。Felleisen 等人在《如何设计程序》一书中赞同这一结论,他们说“糟糕的编程很容易。白痴都可以在 21 天内学会,即使他们是傻瓜。”这部讨厌的鹅漫画也受到了他们的欢迎。

让我们来分析一下类似 “24 小时自学 C++”这样的标题是什么意思:

  1. 自学: 在 24 小时内,你将没有时间编写几个重要的程序,并从成功和失败中吸取教训。您将没有时间与经验丰富的程序员一起工作,也没有时间了解使用 C++ 的感觉。简而言之,你没有时间学习太多。因此,这本书只能谈一些浮于表面的知识,而不是深刻的理解。正如 Alexander Pope 所说,半瓶子醋 —— 乱晃荡(233)。
  2. C++ 在 24 小时内,你可能学会一些 C++ 的语法,前提是你以前了解一些其他的编程语言,但是你不能学会如何使用这门语言。举个例子,你是一个 Basic 程序员,你可以学习用 C++的语法编写 Basic 风格的程序,但你没法学到 C++ 到底有什么好处(和坏处)。所以这里的关键是什么呢?Alan Perlis 说过:“一门不能影响你编程思考方式的编程语言是不值得学习的”。现实情况很可能是,为了与现有工具交互以完成特定任务,你必须学习一点 C++(或者更可能是 JavaScript 或面向过程的语言),。但是你没有学会如何编程,你学习的是如何完成这项任务。
  3. 24 小时 很不幸,这点时间是不够的,下面的章节我会说明这一点

十年自学编程

研究人员已经发现,在各种各样的领域,包括国际象棋、音乐创作、电报操作、绘画、钢琴演奏、游泳、网球以及神经心理学和拓扑学研究,都需要大约十年的时间来学习研究专业知识。其中的关键是刻意练习:不是简单的一次次重复,而是用一项超出你目前能力的任务挑战自己,尝试它,在练习的时候和之后分析你的表现,纠正任何错误,然后重复。然后继续重复。我们发现似乎没有真正的捷径:就连 4 岁时就被称为音乐天才的莫扎特,也花了 13 年多的时间才开始创作世界级的音乐。在另一个领域中中,披头士乐队似乎凭借一首热门歌曲以及 1964 年在 EdSullivan 节目中的亮相而崭露头角。但自 1957 年以来,他们一直在利物浦和汉堡的小俱乐部表演,虽然他们很早就出道了,但他们的第一次成功–Sgt. Peppers,是在 1967 年发布的。

MalcolmGladwell 将其变成了一万小时定律而使其广为人知。Henri Cartier-Bresson(1908-2004)有另一个衡量标准:“你的前 10000 张照片是你最差的。”(他没想到,自从有了数码相机,有些人一周就能达到这个目标。)真正的专业知识可能需要一生的时间:SamuelJohnson(1709-1784)说:“任何领域的卓越都只能通过一生的努力才能实现,不可能以更低的代价获得。”Chaucer (1340-1400)抱怨道:“lyf 如此之短,lerne 的飞船如此之长。(类似学海无涯?)”Hippocrates (约公元前 400 年)因节选“ars longa,vita brevis”而闻名,这是“ars longa,vita brevis,occasio praeceps,experimentum periculosum,iudicium difficile”的一部分,在英语中被表述为“生命短暂,艺术漫长,机会稍纵即逝,实验危险,判断困难。”当然,没有一个数字可以成为最终答案:假设所有技能(例如编程、下棋、跳棋和音乐)都需要完全相同的时间来掌握,也不意味着所有人都需要完全相同的时间,这显然是是不合理的。正如 K.Anders Ericsson 教授所说,“在大多数领域,即使是最有天赋的人也需要许多时间才能达到最高的绩效水平,这一点很值得注意。10000 小时的数字只是让你感觉到,我们所说的是每周 10 到 20 个小时的工作时间,是哪些最有天赋的人需要达到最高水平也要花费的时间。”

如果你想称为一名程序员

下面是我编程的秘诀:

  1. 对编程保持兴趣: 做一些你觉得有意思的东西,不如我觉得折腾 vim 很有意思,确保你有足够的乐趣,这样你才能在编程上花费 10 年或者一万小时。
  2. 写代码: 最好的学习方式就是从实践中学习,更严格地说,“个人在特定领域的最高水平并不是类似放置游戏这样自动达到的,但即使是经验丰富的人也可以通过深思熟虑的努力来提高水平。”和“最有效的学习需要一个定义明确的任务,该任务对特定的个人具有适当的难度,充分的反馈,以及重复和纠正错误的机会。”《Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life》是这一观点的有趣参考。
  3. 和其他程序员交流: 阅读他人的代码,这比看书或者上培训班重要的多。
  4. 读大学(或者研究生): 这将使你有机会获得一些需要证书的工作,并使你对该领域有更深入的了解,但如果你不喜欢上学,你可以(凭借一定的献身精神)在自己或工作中获得类似的经验。无论如何,光靠书本学习是不够的。《The New Hacker’s Dictionary》的作者 EricRaymond 说:“计算机科学教育不能让任何人成为专家程序员,就像学习画笔和颜料不能让某人成为画家一样。”。我雇过的最好的程序员之一只有高中学历;他制作了很多很棒的软件,有自己的新闻组,并且有足够的股票期权来购买自己的夜总会。
  5. 和其他程序员一起做项目: 在某些项目上成为最好的程序员;在某些项目上成为最差的程序员。当你是最好的,你就可以测试你领导一个项目的能力,并用你的想法激励他人。当你是最差的时候,你知道大师们做什么,你也知道他们不喜欢做什么(因为他们让你为他们做)。
  6. 维护老项目: 理解其他人编写的程序,看看当原来的程序员不在时,如何理解和维护它。想想如何设计你的程序,让那些在你之后的人更容易维护它们。
  7. 学习至少 6 种编程语言 包括一种强调面向对象的语言(如 Java 或 C++),一种函数式语言(如 Lisp 或 ML 或 Haskell),一种支持语法抽象的语言(如 Lisp),一种支持逻辑编程语言(如 Prolog 或 C++ 模板),以及一种强调并行的语言(如 Clojure 或 Go)。
  8. 深入理解计算机: 了解计算机执行一条指令、从内存中提取一个字(有无缓存未命中)、从磁盘读取连续字以及查找磁盘上的新位置所需的时间。
  9. 参加一门语言的标准化工作(这个好难): 这个可以是 C++ 标准委员会,它可以决定你的 C++ 代码是 2 或 4 个空格缩进级别。无论哪种方式,你都可以了解其他人对一种语言的喜好,他们的感受有多深,甚至可以了解一点他们为什么如此感受。
  10. 有良好的品味可以尽快完成语言标准化工作。

考虑到上面这些,仅仅通过书本学习你能走多远是值得怀疑的。在我的第一个孩子出生之前,我阅读了所有的入门书籍,但仍然觉得自己是一个无知的新手。30 个月后,当我的第二个孩子出生时,我是否又回到书本上复习了一下?没有。相反,我依靠我的个人经验,这对我来说比专家们写的数千页书更有用,更让我安心。

FredBrooks 在他的文章《没有银弹》(No Silver Bullet)中提出了一个由三部分组成的寻找优秀软件设计师的计划:

  1. 尽早系统性的确定顶级的架构师
  2. 指派职业导师负责指导职业规并仔细保留职业档案
  3. 为成长期的架构师提供交流的机会。

上面这些假设一些人已经具备成为一名伟大架构师所必需的素质;工作就是适当地哄他们。 AlanPerlis 说得更简洁:“每个人都可以学会雕塑:米开朗基罗必须学会如何不雕塑。伟大的程序员也是如此。”。Perlis 说,伟大的球员有一些超越他们训练的内在品质。但这些品质来自哪里?它是天生的吗?还是通过勤奋来获得?正如 Ratatouille 所言,“任何人都能烹饪,但只有无所畏惧的人才能成为伟人。”我认为这更像是一个人愿意将一生的大部分时间投入到深思熟虑的实践中,但也许无畏才能更好的说明这点;或者,正如 Anton Ego 所说:“不是每个人都能成为伟大的艺术家,但伟大的艺术家可以来自任何地方。”

所以,去买那本 Java/Ruby/Javascript/PHP 的书吧,你可能会从中得到一些好处,但你不会在 24 小时或 21 天内改变你的生活,也不会让你获得程序员所需的经验。或许你应该在 24 个月的时间里努力工作,不断提高,怎么样?好吧,现在你开始有所进展了…


听说过这篇文章很久了,因为自己学习编程算起来也有 7 年了(大学+研究生),但是始终觉得自己依然处于入门阶段,甚至于有些陷入舒适区的感觉,所以才去看这些经典的文章看看能否或得一些启发。这次翻译(百度翻译)了这篇文章,感觉自己确实有很多错误的认知,以前过于注重知识的学习,有时甚至陷入一种看完这本书我就完成了一项任务,就理所应当的学会了一项技术或者语言,现在想来是学习和实践严重脱节了,上面 10 个秘诀最后两个对我有些太难了,第 5 点是我目前最为缺乏的,接下来学习任何一门技术或者语言,最好都找一个开源项目搞懂,最好能够参与开发,改改 bug 之类的就很不错。