哪种学习编程的方式更好,系统学习还是边做边学?

已经工作了,但发现有学习编程的需要,但是用到什么学什么,东拼西凑,总是形不成对编程的系统性的认识。但系统性学习的话,一个是时间资源不足,另一个就是面对浩瀚的学习资料难以提起足够兴趣。大家学习的过程是否有同样的问题?恳请大牛解惑!
关注者
1231
被浏览
109658

24 个回答

刚注册知乎就见到了这条问题,所以就留到晚上来回答了。
虽然才毕业一年,但是因为竞赛的原因从小学低年级的时候就开始学习程序设计,直到大学读了计算机,被各种老师教导过、自学过、教过学生。

什么是编程?
我刚开始学习那时,面向对象和互联网,至少在国内,还没推广开来,甚至不多人知道。直到现在,也就现在大家见到的这个时代了。
扯这历史要说的是,“编程”对我而言从一开始的竞赛,到现在的“创作”,已经是两个范畴的概念了;同样对于时代的需求,从从前的科学计算,到现在的各个行业各个角落的各种应用实现,已经不是一个同样的行为范畴了。
但是,编程的本质上跟当年课本上写的没多大区别,就是编写(广义上的)计算机可执行的指令(集合)。

这个领域的知识是什么样的?
然后要延伸一下时代问题。
从面向对象开始,互联网时代兴起,到现在的移动互联网时代,编程绝大部分的目的是在于创造“软件”,而创造软件也由于世界上最聪明的人群高速集中涌入,以及时代的需求压力,已经形成了一整套工程学,也就是“软件工程”了。
现在“编程”被集中在“软件工程”的需求中,产生的一个结果就是“工程化”,而“工程化”就是整个生产体系开始逐步分化以及逐步专业化,从而出现了这个领域中的各种针对性专业,比如“前端工程师”、“测试工程师”、“算法分析师”、“.NET软件工程师”。
在整个软件的开发周期中,我们都需要跟不同的人在不同程度的合作。即使是个人开发者,都会用到开源的代码、各种下载的人家做好的工具。

这就是工程化后的结果,也就是“编程”被和其他不同的专业,比如数学、医学、建筑、人文等科学结合在一起然后具体地分化成了各个关联的模块。这些模块有一个特点,就是整体上“临近相连”。
这什么意思呢?
举例说明就是,但从(某个)网站开发而言,就有客户、老板、美工、前端工程师、服务端工程师、数据库管理员、网络推广等等。这些角色两两间可能有工作上的直接关联,单指这个软件项目的开发工作的话。
无论哪个是因,哪个是果,现在的情况都是没两个角色间的知识必定关联和有交集。在往广度上看,整个软件工程领域以及世界都如此,只是软件工程领域如建筑领域一般,有比较大的定量的专业化,一切都是有根据有标准的。
而至此,形成的一个结果就是,没有人能掌握所有知识;所有知识都是有关联的,追寻着关联的路径学习产生的效果普遍情况下是最大的。
后面那条可以简单地证明,假设两样知识八竿子打不着,那么你就要等很久它们才能连起来,发挥加成效用。虽然乔帮主说过,总有一天这些dots总会连起来的,但是嘛......靠谱点也不是不好。

所以,学习这个领域的知识是这样子进行的
那么,回到学习上,就变得很明确了。开发的需求需要各种技能,各种技能都是相关的,而一个项目所需要的技术在一定期限内是大致有限的。如果你要开发某样东西,或者做某种用途(比如科学计算),都需要某个知识点进行切入,从哪里都好,切入某个知识点,然后用关联的方式扩充。如果在过程中见到新的不懂的名次,要么马上去“扩充”,要么就记下来,留待以后“点亮”这个天赋,总有一天这些dots......

以上是学习编程要要知道的第一点,这个领域的知识是怎么组织的。以下第二点,关于学习方法。

一个学习的误区与结果
有句名言,是布鲁克斯(Frederick P. Brooks)说的吧,说过,最好的程序员和最差的产出差n倍。
为何?计算机科学基本上是由数学和机械类学科衍生而来,最大的特征就是两道门槛:能不能做出来、这个方法(算法或者设计)效率有多高。
前者不说,后者最明显的举例就是,用加法来计算和用乘法来计算效率差别极大。
这个领域的只是最大的特点就是它们的关系如果你想打通,是需要“理解”的,至少知道怎么用。你不懂得一个公式、一个技术怎么使用,你知道有,到需要的时候也用不了。所以钻研是一种必要的学习习惯。

看到以上内容的时候,你可能会觉得,一开始都设定好要做的目标,然后弄清楚这个范围需要的知识点,然后都从某点开始,全部学透,就能完成了。

这犯了个软件工程的一个极端化错误,在学习上也同样适用,因为每次开发都是基本上是一次学习过程,你又不是*讯,你所做的东西就算别人做过,你也一定没做过。如果别人做好了给你,也不用你做了,腾*也不用去抄了是吧?

这个错误就是将整个项目理想化,如果把这次学习视为一个项目的话。整个项目都是原本不存在这个世界上的东西,没人知道开发(学习)过程中会发生什么,怎有任何可以相信的精细的计划?

如果这么学,你会很容易陷入一个,拿了一本专业书(一个切入点),然后看,然后看着看着就看不下去了。然后?然后就没有然后了......

我们是怎么解决这个问题的
软件工程里是怎么解决这个问题的呢?敏捷开发(Agile Development),每个项目或多或少都能用到。
详细解释可能太多,毕竟我知道的也不多。不过其中最通俗的几点:将大计划切分为短周期,并且每个周期结束后调整计划,使得最近的一个计划可执行并且有效;计划中,将每次的产出进行具体化量化,每个周期都发布(生产出)有效的可用的产品,这个产品是在上一个产品的基础上的改进或者增加;在原有的产出已经难以再升级时,将原来的产品重构(重新设计、重新生产)。

细节的道理就不多说了,都出了多少本书了。
实际上现在你能买到的好的编程教学的书籍都是遵循这个教学模式,也是暂时被认为最有效的书本教学模式。这些书一般会教你从“Hello World!”(到时你就知道是什么了)开始,让你手把手做一次,然后逐步深入;有时候做了一次后,在后面介绍了新的技术,又会让你用新技术跟着做一次;看完整本书,你至少就达到了某个水平了。

要注意的是,你必须有心理准备就是,书上讲的,跟你做的根本有不同的产出,或者你根本做不到。比如书上说计算a+b会输出2,而你的输出3;书上说要点击某个按钮,但是你就是在自己机子上找不到那个按钮......这些都是不可避免的,而且一般都会浪费很长时间。莫名其妙的问题本身就是以上说的,不知道会遇到的问题的一部分,也是现代程序员加班的其中一主要原因。毕竟,你的机子跟作者的机子肯定不一样。

所以学习该是这样的
总的来说,说到了知识是关联的,学习是以不同的学习成本连接不同知识的过程。还有呢,值得鼓励的是,随着知识的增加,智力和经验会随之提高,学习成本也会降低,越来越容易学习。
虽然具体到某个知识点只有懂和不懂,但是具体到一个面,还有懂多少的问题。这就回到了刚才的引述,生产效率为什么会差n倍。因为这是一个广度和深度的综合比拼,而随着时间增长,会形成两个人知识的“马太效应”,差距会成倍增长。
不过放心吧,这个增长是有天花板的,无论是知识总量的有限还是需求有限导致的,至少从程序员的工资就可以看出来(哭)。


具体的学习建议
到这里,至上而下地给出学习建议:
  1. 先有一个想法,像学钢琴也有一开始想弹奏的曲子,提出一个想用生产出来的产品,或者买一本评价好的入门书,做出书中提出的“产品”为目标
  2. 将这个目标细化,可以找专业人士帮忙,梳理出知识的“切入点”以及周围的“关联点”,然后开始计划第一次迭代(做出第一样东西),可以是一段很短的程序或者一个作品,但必须有具体的产出
  3. 每次产出后都重新调整计划,重要的是自己或者专业人士要能具体地评估这次产出的价值。如果是跟着书就自然容易了,就是跟书上对一下就是了

如果要具体给到一个切入点,那么我的建议是两个选择:
  1. 从C语言开始,然后学习算法,走科班路线
  2. 从网页制作开始,然后学习网站工程,走产品路线,这是产品中最好入门的了

不必太担心学错,因为到达工程级别,你学过的八成知识都不会被作为工具使用,而它们的只是实现了它们的历史使命——成为你现有某个实用知识的中间点/桥梁、为你现在的学习效率做了一次铺垫。

实际一点地说,对于一个“毕业了”的程序员,学习一门新的编程语言,可能只需一周,而熟悉需要三周,熟练地用于开发是三个月,精通只需一年。这也是大概而已,严谨地说,不同的语言所关联的知识点的数量是不一样的。这也不影响举例,因为在这之前,一个大学生在学习他们的第一门语言,通常是C/C++,用了一个学期,还可能挂科呢(那是态度问题或者是Dota的问题)。

首先吧,别想速成。这要能速成,那么我们专业人士不就该喝西北风去了?

所以要真解决了学习范围的问题后,你下一个问题应该是“要实现**应该具备那些知识”一类的了。等你在某个点扎根后,想的就是利用这个学习能力,去另一个自己更喜欢的领域,还是就此为据点扩充范围,亦或者深入这个领域(也是扩充的一种吧,方向不同)。

最后重申的一点,就是软件开发本身就是一个学习的过程,只是产出的代码具备不同的价值而已。软件的特殊性已经导致了难以重复地写出两段相同的代码,一般只会改写重写,或者重用原来的代码(就是复制黏贴或者引用调用)。
不建议直接就系统性的学.
建议系统性的看一遍基础知识,对各种名词列表有个粗略的印象.
然后,针对你特别需要的深入学习.
深入学习一定要总结笔记,要进行知识的整理工作.
----
针对你的特殊情况,你已经有工作的内容,也就是可以确定你学习的目标了.
1,将自己的目标清晰化.准确定位你要做什么.
比如:你想做一名运维/测试.如果你还对测试平台,运行环境之类不熟悉,那么你的第一任务应该是熟悉环境,熟悉命令,熟悉各种工具(这个其实很有深度,很需要时间来磨练).然后才有可能去编程.不到必须用编程解决的问题,就不要去编程.
2,根据你的目标内容去学习
目标导向,目的明确,学习效率高.在知识的世界漫游啊.概率论的随机游走问题啊.
3,笔记
这个非常非常重要.我略早点时间学习的内容,已经全部都忘记了.记录笔记,累积笔记,以后碰到问题,可以从笔记里面去查询.这样的效率远高过于利用搜索引擎在信息海洋中淹死.
(只需要看到这里,如果想看吐嘈的继续...)
----
因为你可能就不知道自己要学习什么.
有很多东西都有用,太多的基础知识要学.什么数据结构,算法导论,你实在不能一个一个细细攻破.
这些东西,你并非全部都需要用到,可能那么多的数据结构,你只要明白个队列,栈,就够了.图这种结构,以及其上的算法,可能你压根就不会在实际中碰到.
而且那些东西,看多了,还是非常非常之枯燥的.
结合你所用的学习,这样才是有效的方案.特别对于知识爆炸的今天.
----
我接触开发工作有一段时间了,自己比较喜欢看书,看了一些资料.
结合自己的工作学习内容,列了一个<并发与并行>的提纲.
打算有功夫的时候,自己把这本书写出来.
其实来源是各种书,我只是选个专题,把资料结合自己的心得,整理起来而已.
这最后,只是为了促进我把这本书写出来而已.立此为证.