十年学会程序设计

本文转自:徐宥博客http://blog.youxu.info/21-days/


为何大家如此匆忙?


走进任何一家书店,你会看到书架上一排不见尽头的放着如 <7天自学Java语言> 以及几天或者几小时学会Windows, 因特网或者Visual Basic 这类书。我在Amazon 网上书店用一下的方式进行高级搜索:

出版年份: 1992以后 书名包括:“天” 和 “学习” 或 “自学”

得到了268条搜索结果,其中前78条都是计算机书(第79条是 30天学会孟加拉语)。 我用 “小时” 代替“天” 作为关键字,得到了神奇般类似的结果:这次有253本书,前77本是计算机书, 第78本是 24小时自学语法和写作风格。排名前200的书中有96%是计算机书。

由此可见,人们要不就是急着想学会计算机,要不就是计算机相比于其他事情太容易学会了。比如说把,没有书是写在几天弹奏贝多芬或几天学会量子物理,甚至也没有几天学会帮小狗打扮这样的书。

让我们分析一下 三天学会Pascal语言 [英文网页] 这样的标题表达了什么意思:

  • 学会:

在 三天内,你没有时间去写几个有意义的程序,或者从成功和失败中学到东西。你也没时间跟有经验的程序员一起工作,所以也无法了解在真正编程是什么样子。简短 的说,就学会而言,时间显然不够。所以这些书只是浮于表面的熟悉,而不是深刻的理解。如同Alexander Pope 所说,一知半解是危险的。

  • Pascal 语言:

三 天内你可能学会Pasacl语言的语法(如果你已经掌握一个类似的编程语言),但你无法学会如何合理运用这些语法。简言之,如果你是个Basic 程序员,你可以用Pascal 语言写出类似Basic 风格的程序,但你学不到Pascal语言的优点(还有缺点)到底在哪。重点是什么呢? Alan Perlis 曾说: “如果编程语言不能影响你的编程思维,那就不值得去学.” 另一个可能是,你必须学会一点点Pascal语言(或是像VB语言、Javascript等),因为你需要跟现成的工具组合完成特定的工作。不过这个时候,你实际上学的不是怎么写程序,而是要学着如何完成工作。

  • 三天

不幸的是三天根本不够;下面的章节会告诉你为什么


十年学会程序设计


研究者 HayesBloom 的研究表明,在几乎所有的各种领域,大约要十年才能培养出专业技能。这些领域包括下西洋棋、音乐作曲、绘画、钢琴、游泳、网球,及神经心理学和数学拓扑学。似乎没有真正的捷径--即便是莫扎特在四岁就展露出音乐天才,在他写出世界级的音乐之前仍然用了超过十三年的时间。

再看另一种类型的领域。披头士乐团似乎是在1964年的Ed Sullivan 剧场表演突然地火起来并成为第一乐队的。但其实他们从 1957 年开始,就在利物浦、汉堡等地的小型俱乐部表演。虽然他们很早就显现强大的吸引力,但他们决定性的成功作品 Sgt Pepper 也到1967年才发行。Samuel Johnson 则认为或许还不止十年才行,他说:任何领域的卓越成就都必须用一生的努力才能取得; 稍微低一点的代价都是换不到的。Chaucer 则感叹道: “生命如此短促,学习技艺却要这么地长”

以下是我在编程上成功的秘诀:

  • 对编程产生感兴趣并因为乐趣而写程序。确信你自始至终都能乐在其中,这样你才愿意将十年光阴投入编程事业.
  • 与其他程序员交流;阅读别人的代码。这比任何书任何培训都重要。
  • 不断地编写。 最好的学习方法是在实践中学习 。从技术角度说,”在特定领域的个人最高效率并不因为经验够多就会自动获得;但若有意识的通过努力去提升经验,个人效率会变高”(第336页)而 “高效的学习一般需要明确的任务和因人而异的适当难度,以及及时的反馈和重复或者修正错误的机会”(20~21页)Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life (实践中认知:心智、数学与日常文化) 是这个观点的一本有趣参考书籍。
  • 如 果你愿意,你可以去读四年大学(或再读研究生)。这可以让你满足一些工作的学历要求,同时也可让你对这个领域有更深的认识。但如你不喜欢上学,你也能(得 有牺牲)通过工作获得类似的经验。无论如何,只读书是不够的。《New Hacker’s Dictionary》的作者Eric Raymond 曾经说过: “计算机的教育无法让人成为编程的专家,正如研究画笔与颜料不能让人成为专业画家一样.” 一个在我所有招聘过的人中属于最优秀之一的程序员只有高中毕业,但他写出很多很棒 的程序,他甚至有自己的新闻组。他获得的股票期权使得他可以拥有自己的午夜酒吧.
  • 跟其他程序员一起完成项目。在一些项目中成为最好的程序员;在一些中则充当最差的一个。当你是最佳的,你要测试自己领导项目的能力,并以你的能力鼓励他人。当你是最差的,要看看高手做些什么,他们不喜欢做什么 (因为他们会叫你去帮他们做).
  • 接手别的程序员完成项目。全心投入并理解别人的程序。当原作者不在的时候,看看在理解与修改时有什么要注意的。想想如何设计你的程序使得后来维护的人容易上手。
  • 至 少学会六门编程语言。一种要支持类/对象(class abstractions)的语言, 如Java或C++; 一种函数式(functional abstraction)语言, 如 LISP 或 ML; 一种支持语法抽象(syntactic abstraction) 的语言 如 LISP; 一种声明式语言, 如Prolog或 C++模版; 一种支持协同式(coroutines)编程, 如 Icon 或 Scheme; 还有一种支持并行(parallelism)的语言, 如 Sisal.
  • 记住在 “计算机科学” 中包括”计算机” 这个词。要知道你的计算机执行一条指令需要多久,到内存中取一个字需要多久(缓存是否击中), 到磁盘读取连续的字需要多久,而磁盘的定位又需要多久. (解答见文末)
  • 进行语言标准化的工作。可以像是由ANSI C++ 委员会,或由你自己的团队,来决定你们的编码风格,譬如说缩排是2或4个空格。不管怎样,你都能学到别人到底喜欢什么,对语言的感受有多深,甚至能了解到一点他们为什么有这样的感觉。
  • 并具备良好的判断力,也别老纠缠在语言标准化上.

谈 了上面所有的想法后,我不禁要问究竟能从书上学到多少。在第一个孩子出生前,我读完了所有的 “怎样…” 的书,仍觉得自己是个一无所知的(照顾孩子的)菜鸟。30个月后,第二个孩子出世,我要重回这些书好好复习么? 不! 取而代之的是,我开始相信自己的个人经验。这些难得的经验,比专家写的几千页手册还要有用,而且让我重新找到了自信.

Fred Brooks (译注: <人月神话>作者) 在他的文章 没有银弹 中指出,发掘卓越软体设计者的三部曲:

1.尽早尽可能地以系统化的方式发掘最佳设计人员。
2.给有潜力者指派生涯规划师,并谨慎地规划他们的职业生涯。
3.提供机会给正在成长的程序员,让他们能相互影响,彼此激励。

这里假定了某些人已具备成为卓越设计师的必要潜能;工作只是诱导他们前进。Alan Perlis 说得更简洁了,你可以教任何人学雕塑,但对米开朗基罗而言,要教他的
反倒是有哪些事不要做, 卓越的程序员也一样。

所以,尽管买那些 Java 书吧!你或许能从中找到点有用的,但是在24小时,几天或者几个月中,这些都不会改变你的人生,你也不能掌握一个真正的程序员应该具备的真正的综合的技能。


参考文献:

Bloom, Benjamin (ed.) Developing Talent in Young People, Ballantine, 1985.

Brooks, Fred, No Silver Bullets, IEEE Computer, vol. 20, no. 4, 1987, p. 10-19.

Hayes, John R., Complete Problem Solver Lawrence Erlbaum, 1989.

Lave, Jean, Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life, Cambridge University Press, 1988.

________________________________

解答:

各种操作的时间,以2001年夏季,典型配置的 1GHz 个人计算机为标准:

执行单一指令1 纳秒
从L1 高速缓存取一个字2 纳秒
从内存取一个字10 纳秒
从磁盘取连续存放的一个字200 纳秒
磁盘寻址并取字8 毫秒

________________________________

附录 I: 语言的选择

好几个人问过我一开始应该先学哪个计算机编程语言,这个问题没有唯一的答案,不过选择的时候可以从以下的几个方面考虑:

  • 朋友在用的. 当 人们问我:”我该用什么操作系统的时候”, 我通常的回答是:“用你朋友用的”. 这样的好处是从朋友那儿学习可以弥补复杂的操作系统差异或者编程语言差异(给你造成的困惑)。这里也要考虑你未来的朋友:如果你一直使用的话,开发社区会 是你的朋友。你选择了一个具有有巨大的增长的开发社区还是一个小的快消失的开发社区的语言? 它有相关的书,网站和论坛可以获取解答么? 你喜欢那些论坛上的人么?
  • 保持简单. 诸如C++和Java 是为那些关心代码执行效率的有经验的大型团队的开发人员设计的。因此这些语言中有些为这些特殊场合设计的部件。你只是关心编程而不需要关心复杂情况。你需要一个为新学编程的人设计的容易学习和理解的语言。
  • 实践. 什么是学习钢琴的好方法呢? 是一边听音一边弹奏的“交互式” 的方法呢,还是全听完整首歌然后再弹奏的那种“批处理”方式呢? 很显然, 交互学习的方式能够让学钢琴变得简单–这也适用于编程. 选取一种交互式的编程语言并且坚持使用.

基于以上的这些标准,我对于第一次接触编程的人推荐 Python 或 Scheme. 但是情况各有不同,或许也有其他的选择. 如果你不满10岁,你可能会喜欢Alice 或者Squeak(年龄大的人或许也喜欢这些). 重要的是在选择后, 立即开始学习和使用.

附录II: 书和其他资源:

很多人问我该从什么书或者什么网页开始看起。我重申一句:“仅仅看书是不够的”,不过我也推荐一下的一些:

  • Oz: 计算机编程的概念,技术和模型(Van Roy & Haridi) 可以视为第一本书的现代版. 他是关于编程的一些总揽,包含了比第一本书更加广泛也更加容易阅读和理解的领域。这本书使用了一个不太为人所知的编程语言叫 Oz, 不过这个可以作为学习其他编程语言的一个基础。

________________________________

注: T. Capey 指出,在Amazon 的 问题彻底解决者 的页面上购买了这本书的人还买了: “21天学孟加拉语” 和 “自学语法和写作风格” 这两本书,我估计大部分是我这个页面带过去的用户.

Peter Norvig (Copyright 2001)

Eric You XU 翻译,2007年4月


译者附记:

这是一篇经典的揭示计算机学习和计算机编程领域浮躁苗头的文章。原有的中文翻译链接已经失效,因此特此重新翻译一次。在翻译的过程中,我参考了台湾网友的部分遣词造句以及个别我不能理解的句子的含义,特此向他表示感谢.

如果有什么地方因为个人水平疏漏翻译不到或者打字错误的地方,恳请网友不吝指出。 我的邮件地址是 youxu A@T wustl.edu, 把 A@T 换成 @, 我叫Eric You XU, 你可以直接叫我Eric.


---EOF---


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
国外著名高等院校信息科学与技术优秀教材:本书以Scheme语言为基础介,绍计算和程序设计的一般理论,具体讨论了程序设计、基于数据驱动的程序设计基础、程序设计中的抽象问题等。 第一部分 简单数据的处理 18 第1章 学生,教师和计算机 18 第2章 数、表达式和简单程序 19 2.1 数和算术运算 19 2.2 变量和程序 20 2.3 字处理问题 23 2.4 错误 23 2.5 设计程序 25 第3章 程序就是函数加上变量定义 27 3.1 函数复合 28 3.2 变量定义 30 3.3 复合函数练习 31 第4章 条件表达式和函数 32 4.1 布尔类型和关系 32 4.2 函数和测试条件 34 4.3 条件和条件函数 37 4.4 条件函数的设计 39 第5章 非数值信息 42 5.1 符号的手工练习 44 第6章 复合数据之一,结构体 45 6.1 结构体 结构体 45 6.2 补充练习:绘制简单图形 47 6.3 结构体定义 49 6.4 数据定义 52 6.5 设计处理复合数据的函数 53 6.6 补充练习: 圆和长方形的移动 57 6.7 补充练习:刽子手游戏 61 第7章 数据的多样性 62 7.1 数据混合与区分 63 7.2 设计处理混合数据的函数 66 7.3 再论函数复合 69 7.4 补充练习:图形的移动 72 7.5 输入错误 72 第8章 语法和语义 74 8.1 Scheme 的词汇 74 8.2 Scheme 的文法 75 8.3 Scheme 的含义 76 8.4 错误 79 8.5 布尔值表达式 81 8.6 变量定义 82 8.7 结构体的定义 83 第二部分 任意数目数据的处理 86 第9章 复合数据类型之二:表 86 9.1 表 86 9.2 任意长的表的数据定义 89 9.3 处理任意长的表 90 9.4 处理自引用数据的函数 92 9.5 更多关于简单表的例子 94 第10章 表的进一步处理 97 10.1 返回表的函数 97 10.2 包含结构体的表 101 10.3 补充练习:移动图像 105 第11章 自然数 106 11.1 定义自然数 107 11.2 处理任意大的自然数 108 11.3 补充练习:创建表,测试函数 110 11.4 自然数的另一种数据定义 111 11.5 更多与自然数有关的性质 115 第12章 三论函数复合 116 12.1 设计复杂的程序 116 12.2 递归的辅助函数 117 12.3 问题泛化与函数泛化 120 12.4 补充练习:字母的重新排列 123 第13章 用 list 构造表 125 第三部分 再论任意大数据的处理 129 第14章 再论自引用数据定义 129 14.1 结构体中的结构体 129 14.2 补充练习: 二叉搜索树 135 14.3 表中的表 138 14.4 补充练习: Scheme 求值 140 第15章 相互引用的数据定义 141 15.1 由结构体组成的表,结构体中的表 142 15.2 为相互引用的定义设计函数 146 15.3 补充练习:网页再谈 148 第16章 反复精化设计 148 16.1 数据分析 149 16.2 定义数据类型,再改进它们 150 16.3 改进函数和程序 152 第17章 处理两种复杂数据 153 17.1 同时处理两个表:第一种情况 153 17.2 同时处理两个表:第二种情况 155 17.3 同时处理两个表:第三种情况 157 17.4 函数的简化 160 17.5 设计读入两个复杂输入的函数 161 17.6 处理两个复杂输入的练习 162 17.7 补充练习: Scheme 求值之二 165 17.8 相等与测试 166 第18章 局部定义和词汇的范围 172 18.1 用 local 组织程序 172 18.2 辖域和块结构 183 第四部分 抽象设计 187 第19章 定义的相似性 187 19.1 函数的类似之处 187 19.2 数据定义的类似之处 193 第20章 函数也是值 196 20.1 语法和语义 197 20.2 抽象和多态函数的合约 198 第21章 抽象设计的例子 201 21.1 从实例中抽象 201 21.2 抽象表处理函数的练习 205 21.3 抽象与唯一控制点 206 21.4 补充练习:再论移动图像 207 21.5 注意:由模板设计抽象 208 第22章 使用函数设计抽象 209 22.1 返回函数的函数 210 22.2 把函数当成值来设计抽象 211 22.3 图形用户界面初探 213 第23章 数学方面的例子 218 23.1 数列和级数 219 23.2 等差数列和等差级数 220 23.3 等比数列和等比级数 221 23.4 函数曲线下方的面积 223 23.5 函数的斜率 225 第24章 定义匿名函数 229 24.1 lambda 表达式的语法 229 24.2 lambda 表达式的辖域和语义 230 24.3 lambda 表达式的语用 232 第五部分 生成递归 233 第25章 一种新的递归形式 233 25.1 为桌上的一个球建立模型 233 25.2 快速排序 236 第26章 设计算法 239 26.1 终止 240 26.2 结构递归和生成递归的比较 243 26.3 做出选择 243 第27章 主题的变更 246 27.1 分形 247 27.2 从文件到行,从表到表的表 251 27.3 二分查找 254 27.4 牛顿法 258 27.5 补充练习: 高斯消去法 259 第28章 回溯算法 263 28.1 图的遍历 263 28.2 补充练习: 皇后之间的相互阻碍 267 第29章 计算的代价、向量 268 29.1 具体的时间和抽象的时间 269 29.2 “阶”的定义 272 29.3 向量初探 274 第六部分 知识累积 283 第30章 知识的丢失 283 30.1 一个关于结构处理的问题 283 30.2 一个关于生成递归的问题 286 第31章 设计带累积器的函数 288 31.1 认识累积器的必要性 289 31.2 带累积器的函数 289 31.3 把函数转换成带累积器的变体 291 第32章 使用累积器的更多例子 298 32.1 补充练习:有关树的累积器 298 32.2 补充练习:传教士和食人者问题 302 32.3 补充练习:单人跳棋 304 第33章 非精确数的本质 305 33.1 固定长度的数的算术运算 305 33.2 上溢出 309 33.3 下溢出 309 33.4 DrScheme 数 310 第七部分 改变变量的状态 312 第34章 函数的记忆 312 第35章 对变量赋值 315 35.1 简单的、能工作的赋值 315 35.2 顺序计算表达式 316 35.3 赋值和函数 318 35.4 第一个有用的例子 320 第36章 设计有记忆的函数 322 36.1 对记忆的需求 322 36.2 记忆与状态变量 323 36.3 初始化记忆的函数 324 36.4 改变记忆的函数 325 第37章 使用记忆的例子 329 37.1 状态的初始化 329 37.2 与用户交互并改变状态 331 37.3 在递归中改变状态 338 37.4 状态变量的练习 342 37.5 补充练习:探索 343 第38章 最终的语法和语义 345 38.1 Advanced Scheme 的词汇 345 38.2 Advanced Scheme 的语法 345 38.3 Advanced Scheme 的含义 347 38.4 Advanced Scheme 中的错误 357 第八部分 复合值的改变 361 第39章 封装 361 39.1 状态变量的抽象 361 39.2 封装练习 368 第40章 可改变的结构体 369 40.1 由函数得出结构体 370 40.2 可变泛函结构体 372 40.3 可变的结构体 374 40.4 可变的向量 379 40.5 改变变量,改变结构体 380 第41章 设计改变结构体的函数 383 41.1 为什么改变结构体 383 41.2 结构体的设计诀窍与变化器之一 384 41.3 结构体的设计诀窍与变化器之二 392 41.4 补充练习:最后一次移动图像 401 第42章 相等 401 42.1 外延相等 401 42.2 内涵相等 402 第43章 修改结构体、向量和对象 404 43.1 关于向量的更多练习 404 43.2 循环结构体的收集 415 43.3 状态的回溯 423 结语 425 计算 425 程序设计 425 与时俱进 426

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值