最近打算重学编程,搜索资料中发现萧大的这篇文章,觉得很适合初学者或者重学者,遂将原文和笔记分享在这里。
文章链接:https://zhuanlan.zhihu.com/p/19959253
前言
如今编程成为了一个越来越重要的「技能」:作为设计师,懂一些编程可能会帮你更好地理解自己的工作内容;作为创业者,技术创始人的身份则会让你的很多工作显得更容易。而作为刚想入门的新手,面对眼前海量的信息,或许根本不知道从哪里开始;入门轻松度过初级材料的学习后,发现学习越来越困难,陡峭的学习曲线又让你望而却步;你知道如何在页面上打印输出一些文本行,但是你不知道何时该进行一个真正的有用的项目;你不清楚自己还有哪些不知道的东西,你甚至搞不清下一步该学什么。
这篇文章的内容对此不仅会有一些方向性的建议,还会包含一个基础核心向的编程入门导引。当然,Step by Step 的路线是不现实的,并且每个人都会有自己的特点,所以给出的这个编程入门导引更多的是为了引发读者的思考,最终帮助你形成适用于自己的学习路线。
但要注意:这篇文章是写给那些真心想学编程的人看的——那些憋着一股狠劲儿,一定要做出个什么真东西,不学好不罢休的人;而不是那些「听说编程好玩」的人,在我看来,这种人永远都入不了编程的门,更别提做出个像样的东西来了。
我想重学编程是因为我将来想做一个硬件工程师,需要编程能力。而我在本科编程能力很弱,暑假是个加血的好时候。
心态调整
确定目标
You can code. They cannot. That is pretty damn cool.
– Learn Python The Hard Way
在你学习编程之前思考一下你的目标,当你有最终目标时道路会更加的清晰。那么,你想要写什么?网站?游戏?iOS或者Android应用?或是你是想自动化完成一些乏味的任务让你有更多的时间看窗外的风景?也许你只是想更具有就业竞争力找个好工作。所有的这些都是有价值的目标,这些目标都是你编程学习推动力的一部分,没有推动力的人,是无法在略显枯燥的漫长学习之旅中走远的。
不要浮躁
Bad programming is easy. Even Dummies can learn it in21 days. Good programming requires thought, but everyone can do it and everyonecan experience the extreme satisfaction that comes with it.
不管是在线下还是线上的书店,满目都是《21天学通Java》这种速成书目,它们都承诺在很短一段时间内就让你能够学会相关技术。Matthias Felleisen在他的著作 How to Design Programs, Second Edition 一书中明确指出了这种「速成」的趋势并予以了以上的讽刺。
所谓的「捷径」或者说「银弹」是不存在的,智者说过,精通某个东西需要10年或10000个小时,也就是汉语中的「十年磨一剑」,所以不用着急,功不唐捐。
根据一万小时定律,如果我想在一年内成为专家,每天需要花27个小时在编程上。这显然是不现实的。若把目标定为五年,则需要每天五个半小时。若算作只在工作日学习,则需要七个半小时,若每周学习六天,则需要六个半小时。这在现阶段来说才稍显现实,但一旦开学时间就很难保证,所以不妨假设每年有一半时间是可以完成学习目标的,则需要十年才能成为专家,但我觉得太长了,年轻时精力体力的优势应当充分利用才是,尽可能每天能学习编程(或硬件的其他知识)六个小时。日日如此,若某日时间不能保证,应当提前学习或者补回来。
培养兴趣
Most good programmers do programming not because theyexpect to get paid or get adulation by the public, but because it is fun toprogram.
– Linus Torvalds
沉醉于编程,编程更是为了兴趣。兴趣是推动力的不竭源泉,保持这种充满兴趣的感觉,以便于你能将其投入到你的10年/10000小时的编程时间中。编程很有趣,那是探索的喜悦。那是创造的喜悦。看到自己亲手完成的作品显示在屏幕上很有趣。有人为你的代码而惊叹很有趣。有人在公共场合称赞你的产品、邻居使用你的产品、以及在媒体上讨论你的产品很有趣。编程应该十分有趣,若并非如此,就找出导致编程无趣的问题,然后解决之。
这个问题应该会在具体学习中遇到,先放在这里提醒自己。同时,我也在写我的博客,尽力融入专业社区,相信会有帮助。
开始学习
令人警醒的故事
刚上初中时我便开始了编程学习,很不幸,我读完了好几本当时普遍存在的诸如《21天精通C++》这类的垃圾书,当时读完也无大碍,甚至还能写点小程序。但是软件出故障了我不知道为什么,稍显庞大的编程问题无从下手,碰到现有的库做不到的事也只能两手一摊。虽然我每天不停地编码,但我发现自己的编程能力却是提高的如此缓慢,对于「迭代」与「递归」的概念只有极其有限的了解,可以说只是把计算机当成了计算器来使用。
进入大学后,我主修了物理学,最初的一段时间里我一直在记忆背诵那些物理公式,却不理解她们是如何得出的,她们之间有什么联系,亦或是她们的意义。我不停地学习如何计算解答一些常见的物理问题,却对在这些Hows背后的Whys一无所知。
而在我尝试做一些基于物理行为的电脑游戏时我再次遇到了之前的的困难:面对新问题时无从下手,面对新问题时的恐惧不断累积滋生,我开始主动逃避,不去真正地理解,而是幻想能通过Google搜索复制粘贴代码解决问题。幸运的是,大二时的一堂课完全改变了我的学习方法。那是第一次我有了「开天眼」的感觉,我痛苦地意识到,我对一些学科只有少的可怜的真正的理解,包括我主修的物理与辅修的计算机科学。
关于那堂课:那时我们刚刚学习完电学和狭义相对论的内容,教授在黑板上写下了这两个主题,并画了一根线将他们连了起来。「假设我们有一个电子沿导线以相对论级别的速度移动…」,一开始教授只是写下了那些我们所熟悉的电学与狭义相对论的常见公式,但在数个黑板的代数推导后,磁场的公式神奇的出现了。虽然几年前我早已知道这个公式,但那时我根本不知道这些现象间的有着这样潜在的联系。磁与电之间的差别只是「观察角度」的问题,我猛然醒悟,此后我不再仅仅追求怎么做(How),我开始问为什么(why),开始回过头来,拾起那些最基础的部分,学习那些我之前我本该好好学的知识。这个回头的过程是痛苦的,希望你们能就此警醒,永远不要做这种傻事。
----我不再仅仅追求怎么做(How),我开始问为什么(why)。
警醒后的反思
问题来了,怎样才能尽可能多的获取每个层级的信息?或者换句话说,该怎样学习复杂领域(诸如编程)包含的众多知识?
教育与学习过程中普遍存在一个关键问题:初学者们的目标经常过于倾向整全觀而忽略了基础,举个常见的例子,学生们非常想做一个机器人,却对背后的
理解物理模型 → 理解电子工程基础 → 理解伺服系统与传感器 → 让机器人动起来
这一过程完全提不起兴趣。
在这里对于初学者有两个大坑:
如果初学者们只与预先构建好的「发动机和组件」接触(没有理解和思考它们构造的原理),这会严重限制他们在将来构建这些东西的能力,并且在诊断解决问题时无从下手。
第二个坑没有第一个那么明显:幼稚的「整体论」方法有些时候会显得很有效,这有一定的隐蔽性与误导性,但是一两年过后(也许没那么长),当你在学习路上走远时,再想回过头来「补足基础」会有巨大的心理障碍,你得抛弃之前自己狭隘的观念,耐心地缓步前进,这比你初学时学习基础知识困难得多。
但也不能矫枉过正,陷入还原论的大坑,初学时便一心试图做宏大的理论,这样不仅有一切流于理论的危险,枯燥和乏味还会让你失去推动力。这种情况经常发生在计算机科班生身上。
为了更好理解,可以将学习编程类比为学习厨艺:你为了烧得一手好菜买了一些关于菜谱的书,如果你只是想为家人做菜,这会是一个不错的主意,你重复菜谱上的步骤也能做出不赖的菜肴,但是如果你有更大的野心,真的想在朋友面前露一手,做一些独一无二的美味佳肴,甚至成为「大厨」,你必须理解这些菜谱背后大师的想法,理解其中的理论,而不仅仅是一味地实践。但是如果你每天唯一的工作就是阅读那些厚重的理论书籍,因为缺乏实践,你只会成为一个糟糕的厨子,甚至永远成为不了厨子,因为看了几天书后你就因为枯燥放弃了厨艺的学习。
总之,编程是连接理论与实践的纽带,是计算机科学与计算机应用技术相交融的领域。正确的编程学习方法应该是:通过自顶而下的探索与项目实践,获得编程直觉与推动力;从自底向上的打基础过程中,获得最重要的通用方法并巩固编程思想的理解。
----正确的编程学习方法应该是:通过自顶而下的探索与项目实践,获得编程直觉与推动力;从自底向上的打基础过程中,获得最重要的通用方法并巩固编程思想的理解。
作为初学者,应以后者为主,前者为辅。
启蒙
「学编程应该学哪门语言?」这经常是初学者问的第一个问题,但这是一个错误的问题,你最先考虑的问题应该是「哪些东西构成了编程学习的基础」?
编程知识的金字塔底部有三个关键的部分:
算法思想:例如怎样找出一组数中最大的那个数?首先你得有一个 maxSoFar 变量,之后对于每个数…
语法:我怎样用某种编程语言表达这些算法,让计算机能够理解。
系统基础:为什么 while(1) 时线程永远无法结束?为什么 int *foo() { int x =0; return &x; } 是不可行的?
启蒙阶段的初学者若选择C语言作为第一门语言会很困难并且枯燥,这是因为他们被迫要同时学习这三个部分,在能做出东西前要花费很多时间。
因此,为了尽量最小化「语法」与「系统基础」这两部分,建议使用 Python 作为学习的第一门语言,虽然Python对初学者很友好,但这并不意味着它只是一个「玩具」,在大型项目中你也能见到它强大而灵活的身影。熟悉Python后,学习C语言是便是一个不错的选择了:学习C语言会帮助你以靠近底层的视角思考问题,并且在后期帮助你理解操作系统层级的一些原理,如果你只想成为一个普通(平庸)的开发者你可以不学习它。
下面给出了一个可供参考的启蒙阶段导引,完成后你会在头脑中构建起一个整体框架,帮助你进行自顶向下的探索。
完成 Learn Python The Hard Way(“笨办法”学Python(第3版)
完成 MIT 计算机导论课(如果你英语不过关:麻省理工学院公开课:计算机科学及编程导论http://www.xuetangx.com/courses/MITx/6_00_1x/2014_T2/about,目前这个网址无法上课,可以去网易公开课看)。MOOC是学习编程的一个有效途径。虽然该课程的教学语言为Python,但作为一门优秀的导论课,它强调学习计算机科学领域里的重要概念和范式,而不仅仅是教你特定的语言。如果你不是科班生,这能让你在自学时开阔眼界;课程内容:计算概念,python编程语言,一些简单的数据结构与算法,测试与调试。支线任务:完成《Python核心编程》
完成 Harvard CS50 (如果你英语不过关:完成哈佛大学公开课:计算机科学 cs50。同样是导论课,但这门课与MIT的导论课互补。教学语言涉及C, PHP, JavaScript + SQL, HTML + CSS,内容的广度与深度十分合理,还能够了解到最新的 一些科技成果,可以很好激发学习计算机的兴趣。支线任务:
阅读《编码的奥秘》
完成《C语言编程》
[可选] 如果你的目标是成为一名 Hacker:阅读 Hacker's Delight
PS:如果教育对象还是一个孩子,以下的资源会很有帮助(年龄供参考):
5-8岁: Turtle Academy
8-12岁:Python for Kids
12岁以上: MIT Scratch (不要小看Scratch,有人用它写3D渲染的光线追踪系统)或 KhanAcademy
目前打算买“笨办法”学Python(第3版) (豆瓣)),看MIT 计算机导论课
之所以不选择英文版是因为这会增加学习难度,不是我能轻松读懂的原版书。专业书籍我试过读C++primer,阅读速度很慢。(我四级550,六级495,考研英语70,一直以阅读见长,阅读速度也比较快,但是离能阅读英语专业书还很远。)