作者:阿莱克西斯

只着眼于学习编程是学不好编程的。

从来都不存在如何学好编程这件事,有的只是如何能成为一名好的程序员,和如何学会学习。

这是因为编程作为把思维变为实现的这个循环的最后一步(然后写好的程序会成为新的思考输入和基础,开始新的一轮迭代开发),它和一个项目一个系统的所有其他方面都息息相关:需求获取,问题抽象,测试,监控,部署,框架运用,系统间集成,灵活性,未来拓展性,易用性,系统健壮性,多版本实验性,高层业务决策等等,这使得编程变得无比重要(所有的一切都需要编程来最终落到实地),也毫不重要(编程被所有其他一切所约束和指导)。能够支撑这些所有上层思考的程序才是“好程序”,能够支撑所有这些思考的程序员,才是好程序员。学好/学会编程这件事是把所有需要思考的东西都弄明白都学好之后的自然结果。而把这些思考留给别人,自己只做思维和程序的翻译器,根本无法写出好的程序来。

关于自学计算机,我的看法恰恰和很多人相反,不是多练,多记,而是多看,多读,不怕忘记,不要怕用不到。(练习只作为探索,思考的延伸,而不是为了加强记忆)

简单来说:我的学习方式是基本上就是看书看论文, 记笔记。让知识自我淘汰,利用飞轮效应,让读书的飞轮转起来,看的多,所以学得快,学的快,就能看的更多,那么就学的更快,由于transfer learning的效应,甚至可以触类旁通。 思维,是比行为要快的多的,在脑内演练,在脑内做练习,在脑里写程序,run,判断结果,比真正写出来快的多。

读书的飞轮

  1. 没有看起来的那么快,别看我有时候一天就刷完一本书,一周就刷完一本砖块;其实真正花的时间是很多的。遇到能“抓住”我的书,看到夜里1,2点那是经常的。

  2. 碎片时间都利用起来了,我很多书都有电子版的,放手机里。平时坐车,吃饭,xxx,xxx等。有时间就拿出来看看。

  3. 看书的目标不是“记住”,而是看懂和打标记。这样以后需要用到了,能很快找到在“哪里看到过”;并轻松的把忘记的东西拾起来

  4. 读书的飞轮: 技术书会越读越快,大家读小说会比读技术书快很多。因为读小说不需要什么预备知识就能读懂。而技术书都需要预备知识储备(比如理解B需要理解A),和“理解储备”(即同一个类似的东西我已经在其他地方理解过一次了,所以对于当前的东西则触类旁通,话说有点像deep learning里的transfer learning )。而你读过的书越多,造成你理解困难的点就越少。比如最近案例的scala shapeless那本书100多页,给PLT和懂functional programming的真“大神”来看,不会花他们超过半小时的时间(我大概用了1天看完)

  5. 知识的价值是不同的,我们要判断重要性而选择性阅读,比如我对security这个问题很不感兴趣,而且一般这部分知识都是很独立的,所以比如在读(简评)Kubernetes In Action(大势所趋) 这本的时候,就把security相关的章节全都跳过了(真的需要用到的时候,我们有团队的security专家)。还有比如怎么安装,怎么在UI上一步一步操作,基本也是一扫而过,以后真的需要操作的时候记得这里有讲就好。我判断是否跳过的关键是:这段知识是否能成为我理解其他重要知识的踏脚石,当必须要理解A才能理解B,那么A这个知识的价值就根据B的价值大小有一个增量。即:B越重要,A则越重要。

  6. 读书飞轮的效果,不在于一朝一夕你学会了什么,能做什么,吃透了什么。而在于大量的阅读的一年一年的积累,创造让别人无法建立的知识壁垒去获得别人(同等智力)无法获得的理解力,推理力,知识联系力,从而提高自己学习,或者知识的效率和速度。

  7. 如果你不理解的一个东西在一年2年的积累阅读里都没有从别的地方得到灵感来解惑,要么是因为这个东西不重要,要么就是因为你还没有积累够阅读量,或者没有把相关问题的,散布在不同书里,不同角度的知识抽出来好好总结。读书的飞轮的一个威力就是通过增加新的知识来理解目前不理解的问题,而不是逼着自己一定要在知识不完全的情况下吃透一本书。

  8. 读书的飞轮在于把读书的目的变为更加速度的攻克/理解更多的知识,找出知识间的联系而更加效率的掌握新的知识,而不在于能立刻用现在学到的知识干什么. 如果一个人的知识状态是N个知识,那么你想增加一个知识点,让N+1,只能参考你已有的知识N和利用你的脑子,你的脑子恐怕没法变的更聪明;那么你只能努力让自己的N越大,你就越能更快的让N+1,这,就是读书的飞轮。

读书学习应注意抓住知识间的联系

  1. 读书不要在意“记不住”的问题,担心记不住而反复停留在一本书或者一个知识点,是读书的飞轮能否转动起来的大忌,真正“有用的东西”会不断重复出现在你眼前。要么工作中需要,要么很火在知乎有人提问,要么这些知识被同一类的书再次提到,从另一种角度被描述,要么让你感觉“这个东西跟我学过的那个有点像”,或者书里写“根据A所以我们有B,然后给个参考链接”… 这些都是在一次加深理解这些知识的联系机会。因此,在读书的飞轮里,你不会记不住有用的知识,因为它们会被你反复用到来攻克其他的知识难关。当一个知识成为你理解另外n个知识的基础的时候,每当你遇到提到使用到这另外n个知识,你都间接复习了这个基础知识,这比反复练习,反复复习来记忆有效率的多。

  2. 紧接上一句,但是太重要了所以单独列一条:“知识的真正价值在于知识间的推导/类比/相关/连贯性”。“你自己独特的学习覆盖面将造就独特的你”。任何两个人,当他们的知识覆盖面不同,他们对同一个知识的看法也会有千丝万缕的不同的独特理解。比如双修DL和PLT,和双修DL和分布式系统的两个人,对DL的看法就会有点不一样。“知识的价值在于你懂的知识间,知识与事物间的联系”,这是我们应用知识(去解决问题,或是利用它的去学习更深的知识)的关键。

  3. 锻炼推理和想象能力,不要强记是什么,而要去理解“为什么”,锻炼用已有的知识,推理出新学的知识的能力,让理解水道渠成。锻炼去理解为什么,和正在学习的东西是怎么来的,这件事往往比“记住这个知识”更重要,理解新的知识产生的逻辑过程,或者说推理过程,有助于我们修正或者加强自己的逻辑推理思考能力;而推理能力越强,把知识联系记忆的几率越高,很多时候我们看书看不懂,是因为我们已有的知识和我们正在学的知识之间有一些点我们没有学过,而推理能力越强,则越能正确的脑补出“中间的这些点大概应该是怎么样的”,从而最终全盘理解书里的内容。

  4. 主动建立你自己的知识网络,让知识关联起来,甚至让你自己的知识起化学反应, 增量你的知识。(比如我在看Streaming System 这本书的时候。由于我之前也看过 Conflict-free Replicated Data Types 这篇论文,结合两者的知识,我可以推理出,DataFlow Model中的trigger和retrieve accumulation,其实只有processor的状态是op-based CmRDT才可以支持的;而这点书中是没有明示的)

用有限的大脑去记录无限的知识

  1. 人的记忆是有限的,就好比电脑有限的内存甚至cpu的cache;很多时候我们只要记住知识索引即可,而不必“背课文”。书,资料,文章,都是我们知识数据库的硬盘,而我们只要记住在哪里能找到自己曾经理解过的东西,把这些索引知识记录在我们的大脑的cache里即可。
  2. 知识是可以触类旁通的,也是可以抽象总结的,这样就使得我们可以记住一些知识的本质,然后很容易的在不同应用场景,推理出相关的知识。
  3. 当知识可以在你的大脑里形成联系网络,那么即使你忘记了某部分细节,你也可以很容易的利用你的其他知识推理出“这里的这个细节理当这样设计”,“由于A,B,C,所以这个D应该是这样来的”,“这个问题其实非常的generic,那么一定存在一个库,API可以泛化的解决这个问题”,这样的记忆将更佳有效。
  4. 锻炼对知识的想象力,对未知的脑补能力。推理和想象能力越强,需要记录的东西就越少。当你理解一个东西是怎么来的,那么就算你忘记了它,那么你也可以在需要的时候自己把它推理出来。

让知识自我淘汰

知识是否有用,取决于未来。

如果练习的目的是帮助理解,验证猜想,去探索书里没有讲明白的,那么我觉得应该去做。(比如我在学Shapeless这个scala库的时候,很多时候要去看源代码,还有什么地方没有理解明白的,或者自己有一些拓展的想法,想验证自己的理解和想法,那么变换一下例子程序看看结果。就非常有利于理解) 而如果练习的目的是记住API,记住细节,那么不建议去做。因为这会拖慢飞轮的转动。

因为:知识是否有用,取决于未来。去强化记忆无用的知识是对时间资源的浪费。

因为:你终将会忘记无用的知识。由于工作原因,我曾经在5-6年前精通Storm这个分布式流处理平台,由于Storm的文档实在太差,很多时候我是读源代码理解到底应该怎么用Storm的。然而多年没有使用Storm的现在,在flink,google dataflow,Spark Stream开始大放异彩的现在。关于Storm的枝末细节的知识早已忘却(也应该忘却)

即使不断去学习新的知识,读心的书,真正“有用的东西”会不断重复出现在你眼前 => 从知识的海洋中提炼精华,才是我们人类用有限的生命去理解和掌握无限的知识的有效手段。而由于知识的联系性,交集性,因果性,会重复看到的的知识,那么一定有一些精髓的地方作为共性,那些知识才是最重要的地方。我们要学会保留,会和其他和很多知识起化学反应的知识,和其他知识互为因果关系的知识,是学习其他知识的前提的知识。

而当你读书的飞轮转起,你看到的“未来”就比别人多,那么你就更加能用“未来”验证“过去”。即=》在“未来”反复出现的知识,理解“未来”的知识所需要的知识,是珍贵的应该保留的知识。

解耦你的工作和你的学习

  1. 很多同学有一个误区是,希望通过做相关的工作来学习相关的知识。这样你的知识就被你的工作,你的经历,你的团队,你的项目,你的公司所主导了。你应该根据自己的兴趣主导自己的学习,而不是依赖于不受控的东西。
  2. 这样对你的团队也有好处,这样你就不会用项目练手,用过度设计,或者不合适的tools坑害自己的项目。
  3. 当然,如果要学习的东西和工作要用到的东西完美契合,那当然是最好的。可惜并不是任何时候我们都能找到完美的项目。

自满是自学的大忌

知识爆炸,和知识飞速进化的今天,觉得学会了一点东西就沾沾自喜,觉得比所有不会“这项技术”的人强,这将是阻碍自我进步的大忌。因为你往往会爱上你的学的这些知识。。。。

不要爱上你学的技术,带入了感情,就会让判断失去冷静。一个人的toolbox越大,一项技术在他的toolbox所占的比率就越小。他就会越博爱而不是偏激的爱上一项技术。对某项技术投入过多的感情是眼界太窄的一种体现。

不能用新的自己淘汰旧的自己是很可怕的一件事情,世界进步的这样迅速,不自我杀死,就会被别人干掉,而你的知识和技术总会被世界所干掉的。 这样你的知识反而让自己变成了旧世界的卫道士,拖累了自己,想想我之前学过的东西: oracle,mysql, SQL调优,activemq,aspectJ,enterprise integration pattern,enterprise design pattern,SOA,BPEL,camel, QL4j ,naked Object, design pattern,UML,storm,hadoop,hbase,hibernate,spring,guice… 如果我只停留在哪里,那么。。。我不敢想。。。

如果你寄希望于用3年掌握一样秘籍,然后吃一辈子。那么你不适合计算机程序这个领域。3年所搭建起的优势和壁垒,别人也能用3年搭建起来(甚至别人可以利用后发优势利用更短的时间来搭建更好的优势和壁垒),你的知识暂时比别人多这并不是什么优势,利用你的环境,利用你已经有的基础,利用你不断锻炼出的触类旁通的能力,归纳总结的能力,来得到高于别人的获取知识的速率,这才是你的真正优势,你的飞轮优势。

开阔自己的眼界,才知道自己真的喜欢什么。

计算机领域实在是太博大精深了,所以我建议还没有找清楚方向的同学,不要过多纠结书里的细节,多看看不同的领域,先找到自己喜欢的方向 。

当研究到一定广度,就会需要深挖,但是过早地觉得广度几这样了,据造成“过早深入”,甚至为细节所累,把生命浪费在琐碎的事情上。不要“过深”,到头来才发现,这根本不是自己喜欢和擅长的领域。

注:有些生来就知道自己应该干什么的,知道自己命中注定是要成为XXXX的幸运儿不适用于这个论述

看不懂怎么办

要做判断,是预备知识已经足够了,自己没有理解,还是由于需要理解当前知识的“预备知识”不足。到底应该多读几遍,直到脑补出到底怎么回事?还是思索到死都想不出来?还是let it go,然后去看别的。因为很多时候,答案其实就在别的书里。比如很多很多年前我学JMS和ActiveMq的时候,我完全不能理解书里宣扬的消息的extact once processing是怎么保证的,知道后来我对分布式系统足够了解,这个问题才在DDIA这本书,FLP和End2End Argument的论文里得到解答 => (根本不存在什么extact once msg processing,有的只是effective once msg processing)

关键的关键:你可以不记住细节,不记住思路,不记住设计,但一定要记住自己的问题!!!

看书的时候,记住你不懂的东西有时候比你学会的东西更重要。把没理解的东西记在本子里,因为这样才不会让解答,在你以后的阅读里滑过你的指尖。而当你通过另外的书理解的你以前读的书。两本书的知识就联网了。你很可能对以前的东西更佳融会贯通,也可能用更有效率的方式记住2本书的知识,甚至让2本书的知识产生化学反应,生成自己独特的理解。

什么是编程,编程的目的,什么是好的程序

你要知道学习编程的目标,才能走正确的路,编程不是体力活也不是越年轻越强。也不是30岁了就要抛弃编程转管理。