用十年时间学习编程

1 min read

最近在查找资料的时候,有遇到了此文章,对于文章中的观点真的是非常的认同,推荐给正在学习编程的朋友们。原文为:Teach Yourself Programming in Ten Years,英语好可以直接看原文,以下为译文(非直译):

为什么每个人都急不可耐

走进书店中计算机图书的柜台,你可以看到很对类似《30天学会JAVA》的书籍,类似的还有几小时或几天学会C,SQL,PHP,算法等,在Amazon.com按如下规则title: teach, yourself, hours, since: 2000进行检索,可以得到399本书,第一页的12本书中有10本是关于编程的(另外2本,一本为乐器,一本为阿拉伯语)。另外还有专门的编程学习网站Learn X in Y minutes。从上面的现象看,好像计算机技术非常的简单,学习起来不费吃灰之力。

针对Learn X in Y minutes/hours/days的现象,我们来分析下:

  • Learn(学习):在限定的时间内学习,意味着你不太可能去写一些重大的程序,也很难从成功或失败中得益,你不太可能与有经验的程序员一起合作,并理解在该语言环境下工作是怎么回事。整体来讲,你只能学到一些基础(肤浅)的内容,而不是深入的理解。
  • X(编程语言):在限定的时间内,你可能只学会了X语言的语法(如果你已经学过类似的语言),但你很难学习到更多如何使用这些语法的知识。假如你曾是个JAVA程序员,你可以学着用 Python语法写出JAVA风格的程序,但你不可能了解 Python真正的好处(和坏处)。真正的关键是什么? Alan Jay Perlis(美国计算机程序设计领域的科学家,首届图灵奖的获得者)说过:“一种不改变你编程的思维方式的语言,不值得去学。”另外一种情况是你必须学一点Python,因为你为了完成某种特定的任务,需要与一个现存的工具建立接口。不过那不是学习如何编程,而是在学习如何完成那个任务。
  • Y minutes/hours/days(时间):很可惜,这是远远不够的

用十年时间学习编程

研究人员(Bloom (1985)Bryan & Harter (1899)Hayes (1989)Simmon & Chase (1973))调查显示,在各个领域内,要想获得专业级别的水平,大约需要 10 年时间的努力。参与此项调查的领域包括:国际象棋,作曲,发报,绘画,钢琴演奏,游泳,网球以及对神经心理学和拓扑学的研究。若要在某一领域内达到专家级的水平,其关键在于“刻意练习”,也就是说,并非是机械地,一遍又一遍地练习,而是要不断地挑战自我,试图超越自身当前的水平,通过不断的尝试挑战,并在尝试的过程中和尝试之后对自身的表现进行分析和总结,吸取经验,纠正之前犯过的各种错误。把这一过程不断重复,才能取得成功。所谓的“捷径”是不存在的,即使对于莫扎特这种天才来说,也没有捷径可走,尽管 4 岁就开始作曲,可是他也花了 13 年的时间,才真正地写出了世界级的作品。再举一个例子,甲壳虫乐队(The Beatles),他们似乎在 1964 年凭借一系列热门单曲和其在艾德沙利文秀(The Ed Sullivan show)上的演出一炮而红,但是你也许不知道,他们早在 1957 年就在利物浦和汉堡两地进行小规模演出了,而在此之前的非正式演出更是不计其数。甲壳虫乐队的主要成名曲《Sgt. Peppers》,则是 1967 年才发行的。

Malcolm Gladwell在他的《异类:不一样的成功启示录 Outliers: The Story of Success》书中讲到了10000小时法则,尽管他的重点在 10000 个小时而不是 10 年。Henri Cartier-Bresson (1908-2004)说过,“你所拍摄的头 10000 张照片都是最糟糕的”。 真正的专业或许需要花费一生的时间。Samuel Johnson (塞缪尔 约翰逊 1709-1784)说:“在任何一个领域要想做到极好,势必穷尽一生的精力,否则根本无法企及。” Chaucer (乔叟 1340-1400)也发出过“生命如此短暂,技能如此高深”的感叹。Hippocrates (古希腊伯里克利时代之医师,约生于公元前460年)因写下了如下的句子而被人称颂:“ars longa, vita brevis”,该句是来自于一个更长的引用:”Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile”,这段话(拉丁文)翻译成英语就是:“生命很短暂,但是技艺却很高深,机遇转瞬即逝,探索难以捉摸,抉择困难重重”。

对于精通一项新的技能需要花费多少时间,显然没有一个单一的数字可以作为最终的回答。假定所有技能(比如编程,国际象棋,跳棋,音乐)都需要相同的时间来成为专家或者假定任何人都需要一样的时间是没理由的。正如K.Anders Ericsson教授所指出的那样:“在绝大多数领域,哪怕是最有天分的个人,他们达到最高水平所耗费的时间也是极为巨大的。10000小时这个数字只是想让你意识到即便是人们口中的那些最具天赋的个体想达到最高水平也需要年复一年的努力”

你真的想成为程序员吗?

以下为我为成为一个成功的程序员给出的方案:

  • 设法让自己对编程感兴趣,确保你编程时乐在其中,这样你才愿意投入10年/10000小时。
  • 编程实践出真知。《Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life》这本书中讲到“一个人在某个专业领域方面能够达到最高水平,并不是因为这个人经验增长了以后而自动获得的,而是这个人为了进步所做出了专门的努力之后产生的结果。”,“最有效的学习包括如下几个要素:明确并且难度适当的任务,适应学习者个人情况,及时的信息反馈,有重新开始和改正错误的机会”。
  • 与其他程序员交流,阅读优秀的项目。这比任何书本或训练课程都重要。
  • 如果愿意,去上四年大学(或就读研究生),你会接触一些毕设或发Paper的内容,这样你会对编程有更深的理解。如果你不喜欢学校, 你可以(会有所牺牲)依靠自身或在工作中获得相似的经验。在任何情况下,光啃书本是不够的。《The New Hacker’s Dictionary》的作者Eric Raymond说过,“学习计算机科学不能把任何人变成编程专家,就像光研究刷子和颜料不会使人变成画家一样。” “我雇佣过的最好的程序员仅有高中文凭;他做出了许多优秀的软件,有他自己的新闻组, 而且通过股票期权买到了自己的夜总会。” (作者说的这个人是Jamie Zawinski,他是网景浏览器(Netscape)的早期开发这者之一,也是开源项目Mozilla和XEmacs的主要贡献者,他开了一家叫做DNA_lounge的夜店,位于旧金山的SoMa区)
  • 和其他程序员一起做项目。在某些项目中你会表现的很好,而在另外一些项目中你会表现的很差。当你表现好时,你可以激发别人,提升自己的领导能力。当你做的不好时,你学习杰出者是怎么做的,了解他们不喜欢做什么。
  • 接手其他程序员的项目,尝试去理解其他人所写的代码。看看如果你无法找到代码的作者本人的情况下,理解和修正他写的代码需要花费什么样的代价。同时也思考,如何规划你自己的程序代码,让它们更容易被其他人理解和维护。
  • 学习至少半打的编程语言(不同编程范式)。一种面向对象的编程语言(如Java或 C++),一种函数式编程语言(如Lisp或ML或Haskell),一种支持语法抽象的编程(如Lisp),一种声明式编程的语言(如Prolog或 C++的模板)以及支持并发编程的语言(例如Clojure或Go)
  • 牢记“计算机科学”中包含着“计算机”这个词。了解计算机需要花多长的时间执行一条指令,花多长时间从内存中获取一个数据(包括缓存命中和不命中两种情况),如果连续从磁盘中获取数据,时间消耗如何?以及需要花多少时间才能再磁盘上定位一个新的位置?
  • 尽量参与语言的标准化过程。往大了说,你可以试着加入ANSI C++委员会这样的专业组织,往小了讲,你也可以从自己的代码规范入手,限定代码缩进是需要2个空格宽还是4个空格宽。无论采用哪种方式,你都需要了解其他人对于语言的喜好,以及他们的喜好的程度,甚至你要知道他们为什么产生这样的喜好的原因。
  • 具备良好的判断力,能尽快地从语言标准化的纠缠中脱身

要掌握上面所说的所有内容,光靠看书学习应该是很难做到的。当我的第一个孩子出生的时候,我几乎阅读了市面上所有的《如何…》(关于育儿的)指南书籍,但是我读完了以后还是觉得自己是个菜鸟。30个月以后,我的第二个孩子快出生时,我难道还要做一个书虫么?不!相反,我此时更依赖我的个人经验,这些经验相比于那些上千页的书籍,则更加有效和让我放心。

Fred Brooks所著的著名的论文《没有银弹 No Silver Bullets》里向我们揭示了发现和培养软件设计人才的三步骤:

  • 有组织地辨认顶尖的软件设计人才,越早越好
  • 为他们指派一位职业导师,负责他们技术方面的成长,仔细地为他们做好职业规划。
  • 为成长中的他们提供相互交流和学习的机会。

即使一部分人已经具备了成为优秀软件设计人员的潜质,也需要经历工作的慢慢琢磨,方可展现才华。Alan Jay Perlis(美国计算机程序设计领域的科学家,首届图灵奖的获得者)则说得更加直接:“任何人都可以被‘教’成一个雕塑匠,但米开朗基罗则被‘教’如何不要成为一个雕塑匠,因为他要做的是雕塑大师。这个道理放到编程大师身上同样管用。”伟大的软件开发人员都有一种内在的特质,这种特质往往比他们所接受的训练更重要。但是这些特质是从哪里来的呢?是与生俱来的?还是通过后天勤奋而来?正如Auguste Gusteau(动画电影《料理鼠王》里的幻象大厨)所说,“谁都能做饭,但只有那些无所畏惧的人才能成为大厨!”我很情愿地说,将你生命中的大部分时间花在审慎地练习和提高上,这很重要!但是“无所畏惧”的精神,才是将促使这些练习成果凝聚成形的途径。或者,就像是《料理鼠王》里那个与Gusteau作对的刻薄的美食评论家Anton Ego说的那样:“不是任何人都能成为伟大的艺术家,不过,伟大的艺术家在成名前可能是任何人。”

所以尽管去书店大买Java/Ruby/Javascript/PHP书籍吧,

你可能会从中学到点儿东西。但作为一个程序员,你不会在 21 天内或 24 小时内改变你的人生,或让你在整体经验上有什么提高。光靠读书可读不出来。你尝试过连续24个月不懈努力提高自己么?呵呵,如果你做到了,好吧,那么你开始上路了……

问题答案

典型PC系统各种操作指令的大概时间

execute typical instruction

执行基本指令

1/1,000,000,000 sec = 1 nanosec
fetch from L1 cache memory

从一级缓存中读取数据

0.5 nanosec
branch misprediction

分支误预测

5 nanosec
fetch from L2 cache memory

从二级缓存获取数据

7 nanosec
Mutex lock/unlock

互斥加锁/解锁

25 nanosec
fetch from main memory

从主内存获取数据

100 nanosec
send 2K bytes over 1Gbps network

通过1G bps 的网络发送2K字节

20,000 nanosec
read 1MB sequentially from memory

从内存中顺序读取1MB数据

250,000 nanosec
fetch from new disk location (seek)

从新的磁盘位置获取数据(随机读取)

8,000,000 nanosec
read 1MB sequentially from disk

从磁盘中顺序读取1MB数据

20,000,000 nanosec
send packet US to Europe and back

从美国发送一个报文包到欧洲再返回

150 milliseconds = 150,000,000 nanosec

附录:如何选择语言

很多人曾经问过我,应该选择什么编程语言作来入门?我想这个问题很难有一个确切的答案,但是下面几点可以用来作为选择的参考。

  • 随大流。当被问到“我应该使用什么系统呢?Windows, Unix还是Mac?”,我的回答通常是:“看你的朋友们用什么你就用什么。”这么做的好处是,有了你朋友的帮助,你就能有效地回避操作系统固有的一些差异,对于选择编程语言来说,也是同样道理。同时,你还要有点儿战略眼光:如果选择了一种编程语言,并成为其编程社区的一员,那么你选择的语言和社区是正在不断壮大?还是奄奄一息?如果你有编程方面的问题,能不能从相关的书籍,网站以及在线论坛中得到解答?你是不是跟论坛里的人合得来?这些都是要考虑的。
  • 简单实用。诸如C++以及Java这样的编程语言都是非常专业的开发语言,适用于有经验的大型团队进行开发,需要时常考虑代码的运行效率。所以,这类的编程语言就适合于那样(复杂)的编程环境。如果你是一个初学者,那么就不要搞那么复杂。你所需要的是一种简单易学的编程语言,你靠你自己就可以搞定的语言。
  • 交互式。给你两种选择去学钢琴:第一种,常规做法,也是互动的做法,也就是你每敲一下琴键就能听到琴音;第二种,批量模式,等你把所有该按的琴键都按了一遍,然后再一次性放给你听。你选择哪一个呢?显然,交互式的方式对于钢琴学习来说更容易,对于编程学习也是如此。那么就坚持使用交互式模式学习编程吧。

基于上述观点,我所推荐的编程入门语言应该是Python或Scheme。另一个选择是 Javascript,不是因为它对初学者友好,而是因为有大量的在线教程。如果你的年龄还不到两位数,那么你们应该考虑Alice或Squeak或Blockly(很多成年的初学者也认为他们很有趣)。当然,做出选择并开始行动,这个最重要。

附录:书籍和其他资源

不少人问我,他们该从什么书籍或网页开始学起。我重申“仅从书本里学习是不够的。” 但我还是推荐:

打赏作者
微信支付标点符 wechat qrcode
支付宝标点符 alipay qrcode

C语言学习:size_t

在学习C语言的时候,遇到了一个新的数据类型size_t,截止目前也没有完全理清这个类似的具体场景及出现的原因。
44 sec read

C语言学习:main()函数的正确写法

C语言虽然是一门古老的语言,但是其标准一直在完善,所以很多以前支持的语法在到当前已经不能在使用了。 C语言的版
41 sec read

Scipy数学函数的Scala实现

最近在推进项目的时候,遇到需要将线下的Python代码转化成线上的集群代码,由于机器代码环境是Scala,所以
4 min read

发表评论

电子邮件地址不会被公开。 必填项已用*标注