写给IT自学者的入门指南

在IT工程师和培训机构多如牛毛的时代,学习编程没什么大不了。但自学编程对于刚入门的同学来说可能是个问题,相信很多自学编程的朋友都有一把辛酸泪,然后逼得他们总结出一肚子的体会。科班出身或接受过培训的工程师可能体会不到,这不能怪谁,这取决于每个人的处境和选择,让我们编一个故事说开这个话题。

故事

某君在一个一般的大学读着自己不喜欢的专业,以打游戏、刷段子或装逼度日,突然有一天想学点什么,学编程好像挺酷,被IT江湖大佬的事迹感动,满满鸡血。在想象了以后自己成功的硅谷人生之后,决定得干。

那么第一个问题来了,我选择什么语言?

难道是世界上最好的语言PHP,还是语言之母的C,幸好还知道有个编程语言排行榜的东西,一看几十种不带重样,这要逼死天秤座的小朋友。选PHP吧上非诚勿扰都要被灭灯,而且就只能做个网页。经过了纠结之后我们选C吧,听起来既高级又底层,说不准还能考个计算机二级。

经过了这一轮的思想斗争之后,正式踏上了C语言学习之路,甚至问家里要了钱,配了台新机器,绝对不是为了游戏。说到这里有同学为了学编程纠结于选择什么样的电脑,这个得批评一下,GUN的创始人,自由软件之父Richard Stallman目前还在使用龙芯笔记本。除了特定平台的需求之外比如IOS和C#等,目前来说学习编程对计算机硬件和系统的要求确实不高了。

接下来得干正事儿了。当然对于网络非常便捷的时代来说,自学选择学习的方式非常丰富。除了在网络上收集一些几个G的电子书或视频教程资料,以及阅读了大量“干货”的攻略之外,某君咨询了一些前辈寻求自学的方法。

网络上流传的学习编程的方式有:

  • 看书,这也是最容易想到的方法
  • 观看视频教程
  • 阅读官网文档
  • 读源码
  • 到大学蹭课或者报名培训(不知道还算不算自学,没交学费都算吧)

某君又得纠结一番了,大学蹭课和培训条件并不一定合适,且不符合自学的气质,前辈们觉得观看视频教程比较low,对于阅读官网文档和源码来说,并不适合初学者。总得来说看书算是比较中肯的方法,至于看什么书呢,前辈推荐了《C Primer Plus》,网友也建议谭浩强自然是不能看了,据说是养成了坏习惯不好改。

cover-studying.jpeg

好吧,不在纠结,直接啃这本大部头,虽然有人说看原版好一些,但是实在能力有限还是看中文版吧。一口气花了一周时间读完了这本书,果然是经典啊,变量、语句、条件判断甚至指针都知道怎么回事了,好像充满力量。某君决定按照书中的说法实践一下了,于是打开了记事本,折腾很久装了GCC,把书上的第一个例子抄了下来,在控制台的小黑窗输出了Hello World,成就感满满。决定写点高级的的东西一试身手,合上书,咦。。为什么会报错,哦,原来少个分号。学了两个月为什么还是只能在这个黑窗口算算秋水仙数。对了,网友说的要看官网文档、要读源码、要看英文原版,我一样都不能做到,我一定是能力不够,编程果然是天才做的事情啊……

正经话

上面的故事是我编的,但相似的事情却在我或你身上发生过。我不算大师来写什么学习编程的方法论,考虑了很久才敢用这样如此大的标题,但是真的不是为了当标题党,那样的话题目应该是《震惊!原来编程该这样学》。
我只是害怕看到很多的初学者,在开始之前便给自己设限,没有选择更为接地气的学习方法,而认为编程是属于精英分子。又或者在各种选择的纠结和碰壁的过程后失去信心,告诉自己做不到,因为我们每个人,即使是行业内的佼佼者,都是曾今的门外汉。其实学编程很多时候就是一个趟坑的过程,但不是每一个坑都是有必要趟

IT世界的地图

大多数的Java书籍,教完你基础的知识和秋水仙数的求法后并没告诉你接下来能干什么。我就是这样,曾经学完Java SE然后做了一个Swing的GUI demo,没有人告诉我Java一般是用来做企业级开发的,于是转去了相对简单的PHP。带着对Java的偏见,成为了一个忧伤的故事。
初学者遇到的一个典型的问题是对IT世界没有一个大的图景,关于这个话题,其实一本书都可能不够,我只能尝试分享一点目前正在流行的技术。

首先回到一些非常基础的知识,基础非常重要,,基础非常重要,基础非常重要!这部分属于计算机科学,也是计算机专业本科应该有的课程,不要伤心错过了这些课程,后面我会分享一些有用的资源。

这里我罗列了一些计算机专业的学生一般需要学习的课程,当然每个学校专业设计都不一样,以及名字也不一样,仅供参考。

《高等数学》《离线数学》《电子电路》《数据结构》《程序设计》《计算机组成原理》《编译原理》《计算机网络》《软件工程》《数据库原理》等。有些学校会有一些其他的《通信原理》《汇编语言》《线性代数》《C语言》《Java 语言》等。

学习这些知识是个枯燥的过程,可以看计算机经典丛书系列,比如托马斯·科尔曼(homas H. Cormen)的《算法导论》。推荐更容易的方法是观看大学精品课和去跟MOOC,比较好的有几个:

  • 中国大学精品开放课程 http://www.icourses.cn/home/
  • 中国大学MOOC。这个是中国大学MOOC和网易合作的,有大学经费支持,完成作业和考试后还能拿到证书
  • 果壳网的MOOC学院。这部分的主要内容来自于翻译全球的优秀课程,比如MIT的《Python》

比较难得的就是网易制作了一个计算机专业的课程体系:

计算机课表.png

图片来源于http://study.163.com/curricula/cs.htm

另外一些就是应用于设计软件或者开发网站的实践类知识,包括某个特定语言以及周边的库、框架和工具的等。
我们可以把特定需求用到的语言、库和框架以及其他的工具称为技术栈,这在技术选型上也是被这样考虑的,HR通常也根据技术栈来寻找需要的工程师。比如需要学习SSH 三大框架和Java的Java技术栈;为服务器web开发而生的PHP技术栈;在移动开发领域流行的IOS、安卓技术栈等。当然这里面有一些重合和共用的技术也需要学习,比如版本管理器Git、SVN就是每个合格的工程师需要去学习的。在计算机科学基础知识之外,教授编程以及怎么开发出软件,这正是大多数培训机构的市场定位。

更加详细的解释这些,这里有一些开源的技能图谱可以参考: https://github.com/TeamStuQ/skill-map

技能图谱.jpeg

图片来源 http://skill-map.stuq.org/

最后我整理了一个流行编程语言和用途的表,能在选择时对初学者有所帮助

语言 主要用途
C 操作系统、嵌入式、驱动开发
C++ 图形图像、科研、通信、桌面软件、游戏、游戏服务器
C # Window 桌面软件、.Net web、服务器
Java SE 跨平台的桌面, Android
Java EE 企业级应用、web 开发、服务器后端
Java ME 手机应用,流行于非智能机时代
Go 高性能的服务器应用,比较年轻
Erlang 高并发服务器应用,多用于游戏
Python Web、科学计算、运维
Ruby Web
Perl 运维、文本处理, 用的较少
Lisp 科研、一种逻辑语言,用于人工智能
Node 一个Javascript运行环境(runtime)
Haskell Haskell是一种标准化的、通用纯函数式编程语言,数学逻辑方面
Scala 一种类似java的编程语言,集成面向对象编程和函数式编程的各种特性
Javascript 前端,在node中可以做后端
HTML/CSS 标记语言,主要是给前端工程师构建页面使用

根据这些图谱,做到心中有数该学什么,希望你不在迷茫, 接下来我们聊聊选择合适自己的入门编程语言。

如何挑选你的兵器?

我们把编程语言比喻成兵器,是因为我们深知它仅仅是作为工具存在的,不是为了学它而学,学编程仅仅是学计算机语言,一般来说我们也不用知道赋值语句有“四种写法”。
当然语言之争从来没有停止过,如果我们把编程语言比喻江湖上的武器的话十分有趣。

C语言是M1式加兰德步枪,很老但可靠。C++是双截棍,挥舞起来很强悍,很吸引人,但需要你多年的磨练来掌握,很多人希望改用别的武器。Perl 语言是燃烧弹,曾经在战场上很有用,但现在很少人使用它。Java 是 M240 通用弹夹式自动机枪,有时它的弹夹是圆的,但有时候不是,如果不是,当你开火时,会遇到 NullPointerException 问题,枪就会爆炸,你被炸死。JavaScript 是一把宝剑,但没有剑柄。 -- 来自网络

老实来讲IT行业最终目的是交付可用的软件,编程语言也是适应市场的。这对于初学者来讲或许有些残酷,因为工作多年以后我们发现最好的语言是用来处理工作上的任务或者构建合适的应用,并不是出于爱好或者某种Geek精神。

对于初学者选择合适的入门语言我想你需要考虑至少两点:

  1. 是否能合适的用来构建你想要的应用。如果你的目标是创建一个运行在IPhone上的APP,那么我想你最好选择 Object C 或者 Swift,学习web开发可以选择PHP 或者JAVA, 别急着说你知道还有很多其他方案,最通用的方案永远是久经考验的,而且学习资源众多, 去图书馆的书架上看看就知道啦。
  2. 是否容易学习。编程语言往往能做很多事情,这是因为图灵完备性,我们可以用汇编做出网页,也能用Javascript写APP。在满足第一点的条件下请尽量选择容易学习的语言。容易不仅仅指语法简单,包括环境搭建、部署等都需要考虑在内,以及能不能容易找到好的学习资料。

非常重要一点别忘了,学习编程语言还包括平台提供的API,比如Win 32 之于C++/C#/VB,以及周边的库和框架。IT历史上甚至出现框架和库引领了编程语言走向的情况。JQuery 和Angular 改变了前端开发的思想; Rails 抢走了Ruby的名气;而SSH三大框架一度代表了Java世界。

不要在编辑器和IDE上喋喋不休,他们只是用来盛放你锋利兵器的架子,也不推荐使用纯文本编辑器,这看起来像赤手空拳。

推荐一些编辑器和IDE

IDE/代码编辑器 适用平台 推荐用途
Vim/Emacs/Textmate/Sublime/Atom/Notepad++ 支持大部分平台 纯文本编辑器,理论上支持任何语言
Visual Studio Windows C/C++/C#
Codeblocks 跨平台 C/C++/C#
Eclipse 跨平台 Java
Intellij Idea 跨平台 Java/前端
Xcode Mac OS IOS
PhpStorm 跨平台 PHP
WebStorm 跨平台 前端
NetBeans 跨平台 Java/C++/C/PHP
Android Studio 跨平台 Java(安卓)

图难于其易 - 一把自己够得着的梯子

任何人拿到自己心仪兵器后,只有勤学苦练才能笑傲江湖。我们在形容某项技术是否容易被学习时,我们常常碰到有人用学习曲线很陡峭来形容,这是一个形象的比喻,越陡峭的地方你得选择更合适的方法,不是吗?

我不认为看视频教程有什么不对的,虽然我已经听到不下5个人声称是靠阅读官方文档或者看源码学会编程的,而且认为观看视频教程见效太慢。这个思想对初学者很危险,不得不承认阅读文档和源码能更准确找到自己想要的信息,这对深入技术原理非常有用,但视频比文字传达出更丰富的内容,有更直观的演示和细致的讲解,我想没有别这个更适合初学者了。如果只是因为观看视频教程很low,那也只能说很可惜浪费了非常宝贵的一大块资源,而且往往广泛传播的视频教程都有很高的质量。

当然,得区分一下知识和技能了,这是两样东西。我们来回忆一下我们遇到的挫折,读完了整本书,搞懂了很多道理,打开书无所不能,但合上书无能为力。甚至有时候不能根据自己的想法略微修改书中的例子,因为总是报错。对于IT类的书通常和考试的时候读法是不同的,对于初学,需要选择更接地气的并且能告诉你最终能做出什么案例的书籍。你不需要通读整本书,而是需要搭建好和书中的版本一致的环境,然后把书中的每行代码敲入电脑,观察这些代码怎样被运行。一本书一个月可能才被读完,但慢点并没什么坏处,敲过一遍的代码才能算是你的,否则永远存在于纸上的代码清单中。知识也许是存在脑袋里,但是写代码能力却在手里,我相信很多过来人相信“无他唯手熟尔”这句话,也赞同“代码三天不练手生”的道理。

一个学习的误区:攫取的知识太多。 程序员谁没有个资料库呢,满满一架子的书,超大容量的网盘的资料,有视频有电子书,囤积资料的脚步永远停不下来。有很多文章谈到过这个毛病了,我也是,但是最终发现真正能让我学到东西的是挑一本合适的书或者视频教程(不要花时间找到最好的那套教程,天底下哪有完美的东西啊),然后一步一步跟完,尽量坚持到底不要换, 慢比快好。学习东西通常的方法就是少量取用,然后实践,这不同于做学术研究,在开始的时候不要求你有多深的理解和所谓的”编程思想“,帮你一步一步向上爬,步子不能太大,这便是梯子的作用,不是吗。

胡萝卜和大棒 - 持续自我激励

没有小伙伴和老师,自学无疑是寂寞的。学习编程往往需要花费一个长的时间,如何保证这个阶段能继续坚持?如果把学习比喻成驴子拉磨,我们可以给驴子喂胡萝卜正向奖励,也可以拿棒子抽。当然我们自学者没有老师拿棒子抽,可以采取前一种方法吧,况且没多少人有必要真的要卧薪尝胆。

心理学已经证明,设定一个目标然后实现它,给予适当的奖励,可以奖励一个有效的正向激励机制。学习编程来说,实现一小段程序然后运行起来带来的成就感,足以让人感到满足,这有点像玩游戏杀死一个怪物然后得到一些金币。定期给自己一些目标和任务,听起来是个不错的主意,如何确定这些目标的难度?给自己设定一些有实际意义但是不太难的目标,太难会让人失去信心,太简单又很无聊,而是设定一个跳起来刚好摸得着的任务。每每实现一个目标给予自己奖励,可以是完成任务的成就感,也或者是其他一些设定的物质奖励。这看起来有点像训狗,只要它做出了你期望的行为,马上给予奖励,然后形成条件反射。那我们就可以可以起个名字叫做“巴甫洛夫学习法”,就像巴普洛夫实验的那样。请不要怪我拿驴子和训狗来举例子,我只是想更容易的说明这些问题,虽然看起来有点乡村气息。

那如果真的遇到一些麻烦的任务呢,如何解决它们,而不至于知难而退丧失信心?我来卖弄一点学问,在笛卡尔的《方法论》中告诉了我们研究问题的方法和步骤:

  1. 不接受任何我自己不清楚的真理,避免鲁莽和偏见。
  2. 要研究的复杂问题,尽量分解为多个比较简单的小问题,一个一个地分开解决。
  3. 小问题从简单到复杂排列,先从容易解决的问题着手。
  4. 问题解决后,再综合起来检验,看是否完全,是否将问题彻底解决了

在敏捷开发这种工程思想中我们正是这样做的,我们需要把业务需求进行拆分然后评估工作量,不仅可以直观的看到任务的进展,手上的工作也不会看起来庞大得难以完成。

高山仰止 - 对编程大师的迷思

我相信大多数人都听过比尔·盖茨,计算机专业的学生和IT行业的从业者一般都知道图灵和冯·诺依曼,但是C语言/UNIX之父丹尼斯·里奇(Dennis Ritchie) 却很少人知道。 说明有的时候,其实一个人的名气和他的贡献关系并没那么大的。

说个比较尴尬的事情,我曾经在一些社区或者Q群里回答初学者的问题,竟然有人把我当做大神崇拜,以为我什么都知道,但你应该能想象到,不可能每次的回答或帮助都让他们满意。一旦某个问题不能被解决或者任务完成,他们便非常失望,觉得没有遇到一个真正的高手。

同样在学校我们把老师当做大师,如果有些东西他不知道便被认为对这个专业不精通,不是一个合格的老师;在公司我们对CTO和技术经理又抱有极大的期望,被当做顶梁柱,没有什么问题不能被解决的,否则就是对不起这个头衔;同样把知名博主和经典书籍的作者当做权威,他们的思想又被当做为“社区的最佳实践”。如果我们把对待宗教的狂人用到了编程上,那这应该发生在欧洲文艺复兴前的中世纪,程序员都应该跪在教皇跟前。

计算机科学已经发展到了非常庞大的阶段,每天都有数以万行的代码被提交到开源社区。 社会分工和专业细分得以让这个行业持续发展,没有人能对计算机科学和软件工程领域的所有了如指掌。我们无法讨论比尔·盖茨和图灵那个厉害,一个是厉害的工程师,而另外一个是优秀的科学家,我们无法找到一个合适的标准评判他们。

以前时常能听到一些人一个月写出操作系统,或者因为对某个框架厌恶而自己写了一个,这是多么理想化的Geek精神。但是工程师的个人英雄主义时代已经过去了,林纳斯·托瓦兹写出Linux 也需要开源社区的完善才能被使用;民族软件的旗帜WPS也不仅仅是求伯君和雷军完成的,大量的代码提交于不知名的工程师,硅谷和中关村的传说离我们越来越远。

IT行业内充满了吹捧和互黑,值得庆幸的事,大多数工程师往往通过脚投票选择合适的技术和方案,而不是选择站队。我们应该学习保持技术热情,但在实际工程应用中,技术选型是一个严肃的话题,应该考虑可靠性、好维护性以及周边生态等。很多情况下技术产生于特定的历史背景下,谭浩强在他的C语言书中讲的编程方法,被人们诟病为“坏习惯”,但是事实是谭浩强版《C语言》成书于C语言形成标准之前;PHP被人们认为是脚本语言,大师不屑于使用,但是PHP被设计出来是为了解决高级语言的CGI编写web页面非常痛苦的情景;我们知道DOS操作系统已经被淘汰很多年了,而如今的路由设备依然运行着类似DOS的操作系统。

衡量一个大师往往看他的作品,而不是他说了什么,或者他的名气与头衔。一位著作颇丰的工程师,Borland Delphi 产品专家,曾经的支付宝架构师周爱民(他的书很硬,很值得一看)接受采访时,记者问他:“您是如何成为一名架构师的?” 周爱民的回答让我记忆深刻,“真正的架构师是没有title的。”原因是他并没有在简历上写上架构师的头衔。仅仅是他在Delphi圈子里比较资深,发了简历给盛大,盛大给发offer的时候,觉得高级工程师已经不太适合了,就只能是架构师。

最后多说几句

非科班出身的工程师入门是有一定痛苦的,不像武侠世界里面的名门正派的弟子,又没有机缘遇到骨骼精奇的世外高人,如何选择合适自己学习方式和自我管理是很重要的一方面。没有任何Low的学习方式,只要是直接而又高效就行,更要能达到我们的目的。以我的例子,从大专学校毕业并没有机会参加本科课程,曾经也在网上攫取各种视频教程,去别的学校蹭课,甚至带上礼物去一个老师那里登门拜访补课。

另一方面是如何上桌,吃上编程这碗饭。学习的东西如果无处施展便成为屠龙之技,参加一些开源项目和一些公益活动,谁不喜欢一个热心的人呢。甚至即使是自己想出来的小项目,有了一些项目实践后去找一个公司实习应该不算难事。

我不知道算是有幸还是不幸经历了这一个过程,矫情一点来说是有一些曲折,但是我知道聪明从来不是这个行业的门槛。引用流行于知乎的一句老话“以大多人的努力程度,还轮不到拼天赋的程度”。丰富多彩的IT和网络世界不是天才们的馈赠,而是无数工程师微小又平凡的贡献,学一些,做一做,就是千里之行的起点。