再论对计算机编程的学习(一)
朋友们可能会发现,我这类的文章已经写了不少,这其中有些写的很严肃,有些带些调侃,有些却直接烂尾了。

无奈,虽然我坚持认为计算机程序开发的门槛不断降低是垃圾软件层出不穷的罪魁祸首,但也很难改变我不断进一步降低这门槛的努力。这很矛盾,但也很正常,毕竟自己也是从一名弱菜成长起来的(现在还是很菜),也经历了不少坎坷,绕了不少弯路,走过之后就总想放些路标。所以似乎每隔一段时间就为普及计算机编程知识着急一次。

当然这也与我好为人师的性格比较相关,可能在中年之后,我会将科学普及工作作为自己的主业吧。

之所以会提笔写这篇文章,也有一些其他的因素。一方面我自己也在不断学习,观念也在持续的调整之中,回首之时也难免为自己过去文中的一些观点嗟嘘不已。可能待我再成长一段时间,还会回头再重写一遍同样的话题吧。另一方面,纵观自己过去的文章,总是带着比较强的立场性,带着些许扇动(非错别字,某些字不安全)的味道,比如这篇文章里喷一喷谭浩强,那篇文章里骂一骂教育,带着这类感情色彩,总是很难以站在完全理性的基础上写出足够可靠的文章来。于是这一次,也决心,只就事论事,不扯别的,不发牢骚,看看能不能写好这样的东西。

其实我一直坚信的一件事,就是一个好的学习方法是由两个因素左右的,一个是你的思维特征,另一个就是你要学的是什么。

现在很多关于学习方法的论点,都集中于“什么人适合什么样的学习方法”,而不是“什么学习方法应该运用于什么行业”上。其实也正常,毕竟正常人的各种性格特征,思维习惯可以“似是而非地”由粗线条划分成屈指可数的几类,但如果要按照行业分类那就很难确定会有多少种了。

事实上,特定的知识体系是存在通用的学习方法的,当你要学习某个知识的时候,你需要做的是按照这一类知识通用的学习方法作为框架,在这之上针对你自己进行细化,形成自己独立的学习方法。举个简单的例子,比如有人告诉你学某样东西要先拿哪些书入门,再在哪些网站上刷题,然后以哪些书作为提高,这就是你学习方法的框架,而每本书究竟是速读-精读-速读的阅读法,还是只用速读一遍,那就是你根据自己的阅读能力、理解能力、记忆能力,自己为自己量身定制的了。

像这样的一套学习方法论,我可以美其名曰:学习模型。至于这种学习模型的细节,就是下文中将要展开而论的了。

学习模型的底层应该被称为“通用学习方法”,是跨领域、跨人群的,可以说是所有人学习一切知识必备的——说方法似乎不大恰当——应当说学习素养才对。

这里的学习素养又可以继续细分下去,让我们先从分析、解决问题的能力开始。

学习之所以是一个充满坎坷的过程,是因为在学习的过程中会遇到各种各样的问题,其中比较显著的有,读书/听讲时遇到自己不熟悉或没听过的名词,在实践时结果和书中所述不一致,学习时的概念过于抽象,难以下手实践,等等。

有一类人,在遇到问题时的第一反映便是提问,无论问题大小,多少,什么性质,都一律原封不动地抛给别人,众所周知,这样的人俗称伸手党。伸手党固然是一种令人生厌的、难以进步的人群,事实上学习过程中对他人的过度依赖来自于懒惰——不愿自己解决问题——这样的学习态度一定是难以学成的——并且如果一位依赖他人那么也就永远无法超越他人。然而这并不是本章要讨论的重点。

我们要讨论的是另一群人,往往为了一个问题而纠结一下午,折腾一整天,最后为了这个问题浪费了许多不必要的时间,精力。打乱了自己的学习计划,导致进度缓慢,学习过程越来越艰难,最终完全失去兴致甚至放弃。这是我们身边长期存在的一个巨大群体,属于(可能)极度用心却难以进步的那一类。

我们称这种现象为难以恰当地分析并解决问题。

这类人群可以被归纳总结为如下几类:

不堪一击型:在遇到问题后就开始心急如焚,心急则神乱,神乱则不能思考。不能思考则手足无措,手足无措则愈发不能为(这一点在实践、实验中尤为突出),不能为则心愈急,神愈乱,最终乃至抱头痛哭者时而有之。

无头苍蝇型:遇到问题之后完全按照自己的猜测去进行决断,不行重新猜测,如此往复不断,甚至同一错误方法反复尝试,可能解决问题然而效率极低

自断道路型:往往同属无头苍蝇型,特质在于当发现一个解决方案不可行时会随着自己的脾气删除该解决方案的一切信息(比如在反复调试程序后一气之下删除所有代码,或者在数学题解不出时怒撕稿纸),事实上很多错误的解决方案中潜藏这一部分正确的信息,这种行为会使得这些正确信息丢失,使自己与正确方案失之交臂。

偏执己见型:无法跳出自己的思维圈子,换汤不换药地尝试错误解决方案的各种变种(在竞赛党刷题时尤为突出——因为题做的多了总能总结出套路,套路不一定通用却很容易洗脑)。这一类人往往拥有的另一个特质就是:从不求助于人。

歪楼甚远型:这种情况很常见——在搜索资料时发现资料中自己难以理解的东西,或者自己感兴趣的东西,于是针对这些东西进行进一步探索,发现更多“新世界”,之后一发不可收拾,甚至完全忘记自己的初衷。

不会发问型:也是很常见的一个群体,在查阅自己需要的资料或求助于人的时候,不能很好地描述相关资料的搜索条件或者问题本身。

左右为难型:遇到多个资料或人给出的相悖的多种解决方案时,就不知所措。

这几类人群往往互相交叠,成就了一批又一批“XX真难啊”的言论发布者。

列举出了几类食物人群,也就潜在地指出了怎样才能够恰当地分析并解决问题。

对于由于心理素质导致的问题在这里我们不多做讨论。其实这个是最难解决的问题,是真正**没有任何人能够帮的了你的**,这里我只稍作点拨地抛出几个方法,一方面是多训练自己的心理素质,学会镇定,另一方面在头晕脑胀时做适当休息,做些别的事情,等精神状态恢复之后再重新思考往往会获得好的灵感。

让我们着眼于良好的、通用的解决问题的方式。

首先要相信不存在通用的解决问题的方式——一切都应当对症下药——正如之前所说,最终还要根据问题和你个人量身定制。

然而并不是我要自相矛盾,良好的解决问题的方式之间,确实存在着彼此相通的地方,可以称为解决问题需要的几大要素,或者说,解决问题方法的一套模板。

首先要学会猜,这里的猜并非胡乱懿测,而是有根据地分析出各种可能性。

那么就是猜什么和怎么猜的问题,对于不懂的东西,我们需要猜出其大致含义、到哪里找到对该事物的解答。对于实践中遇到的意外,我们需要猜的是什么导致了意外,以及如何让事情变得正常。

不懂,无非就是听不懂、看不懂,不懂的可能有词汇,概念等,主要成因有这么几种:知识功底不够,词汇或概念本身难以理解,你的学习资料/导师用语晦涩。

对于没能弄懂的词汇,一般采取的办法是先结合上下文以及词汇的字面意思进行猜测,通过猜测缩小范围之后查阅相关资料。对于没能弄懂的概念,一般采取的办法是根据该概念相关的应用(比如例题)来推断出此概念的使用场景,存在意义(这四个字着实太大,举个小点的例子,二元二次方程存在意义中的几何意义包含各类圆锥曲线),根据猜测结果缩小搜索范围之后查阅相关资料。

这里必须明确的是,猜并非获取知识的途径,猜测只是用来缩小你查阅文献的范围、为你寻找相关学习资料指明方向的。哪怕根据对上下文或应用案例的分析使你近乎百分百确定自己的猜测,依旧需要通过其他资料来证明自己的理解。这一点,如果用计算机算法分析中相关的话来说,就是“你的猜测永远是对局部最优解的近似,然而你需要的是全局最优解”。

在猜、查的过程中,如果发现相关的资料也难以理解,可以尝试换一批资料,如果仍然不能理解,那么可以尝试先跳过问题,继续学习。事实上对知识的更加深入理解可能导致你某一天对之前未能理解的事物“豁然开朗”,就像Braid这一解谜游戏中一样,有时一关的拼图媒体有拿全的时候,可能在下一关中可以找到相关的线索。

可是如果这类现象(资料同样难以理解)发生过多,那么说明你的知识功底不够,那么应该做的是转而去学习一些更加浅层的知识(为了在这期间保持自己的兴趣和热情,可以同时选读一些相关的科普书籍)。

另外如果经常出现“难以理解的东西在其他文献资料中变得容易理解”的现象,那么建议你立即更换你的学习资料/老师。

而实践中遇到的各种出乎意料的,难以解决的问题,我们应当首先“猜”问题的起因。

首先我们一定要相信的是,凡是异常事件发生,总会在发生之前留下些蛛丝马迹。所以我们应当向过去而不是现在看,回顾自己的每一步操作,以及每一步操作带来的结果。之后推断出大致的问题可能性,来判断应该查阅什么样的资料或者该如何着手去解决。这里需要非常细致的观察,以及强大的联想能力。至于在计算机程序出现问题的时候我们究竟应该如何去“猜”,以及如何解决将在后文中指出。

那么下一个问题,就是“猜”之后,应当怎么“查”。

首先我们探讨获取资料的途径

现在最最直观,最最容易的获取资料的途径便是在互联网上进行搜索。然而,似乎很多人并不理解应当如何进行搜索。

首先是搜索引擎的选用,这一点根据你所学习的知识具有比较强的方向性,将在稍后做更细致的解答,这里先简略进行提点:

1、搜娱乐八卦用百度,搜知识用谷歌(或者其他*靠谱的*搜索引擎)。

2、用好搜索引擎的聚合功能,如果你认为一张图表对于你现在需要解决的问题来说更有说服力,那不妨搜索图片;如果你在学习去社会学相关的东西(这和计算机也并非完全无关,比如说产品设计中的用户分析,体验设计,市场战略等等),那么可能新闻搜索比网页搜索更容易搜到你需要的东西

接下来,便是如何使用搜索引擎,这里的问题有可以分为两大类,如何输入恰当的搜索字符串,和如何筛选出靠谱的搜索结果。

搜索时我们必须注意的问题是,我们在搜索,绝不是向搜索引擎提问——虽然现在的科技正在努力使这样做成为可能,但至少现在看来,向搜索引擎提问依旧是一种极为不靠谱的搜索方式。

真正需要做的事情有两种:一种是告诉搜索引擎我们需要什么答案,一种是向搜索引擎描述我们遇到的问题。

在这里我比较推荐前一种做法,因为搜索引擎普遍返回的是“包含你输入的句子/词汇的结果”,那么当你输入大概的答案时,得到的就是答案。通常一个比较常用的做法是推测答案中可能出现哪些词汇或模式,将其输入搜索框。

比如,当你需要查阅tree-seq函数的用法时,应该输入“tree-seq函数用法”而不是“tree-seq函数怎么用”,当然这个例子并不好(我一时想不出更好的例子),事实上直接搜索“tree-seq”会获得更好的效果,这一点将稍后讨论。

然而,有时由于问题过于复杂等原因,我们会觉得“离答案还很远”,以至于无法向搜索引擎描述我们需要的答案。这个时候我们就采用后一种办法:描述遇到的问题——注意不是提问。比如“kde更新后gtk主题引擎失效”,而不是“为什么kde一更新我的gtk主题引擎就失效了?”。当然,输入“gtk doesn’t work after kde update”就更加好了,如果你用的是谷歌等靠谱的搜索引擎的话,他会把“doesn’t work”和”don’t work”, “not working”, “won’t work”一起查询,”update”和”upgrade”一起查询,等等。

必须注意的是,描述问题的时候必须将问题发生的背景条件尽可能详细地列举,以缩小搜索范围。

通过描述问题,我们获得的搜索结果往往是其他人提出或遇到过的相同/相似问题,如果幸运的话,我们可以在比较短的时间内找到合适的解决方案。

这里我们面临一个问题,就是如何在描述答案/问题的时候更好地表达。

答案就是关键字,在描述答案或问题的时候我们需要做的是通过尽量精简地描述自己的问题,多一句废话不可。这就需要确定我们搜索的时候应该输入哪些作为关键字。

这和抽象问题的能力有关,也和一些技巧有关,一个比较好用的技巧是用最精简的话描述答案/问题后只保留名词和动词,用空格分开输入搜索框。如果需要进一步的精简,那就基于你对于搜索引擎的理解,推测删除哪些词之后搜索结果会更加纯正(就是有用信息占的比重更大,信噪比更大)。比如那个tree-seq函数的例子,一个经验比较丰富的人应该能够预料,直接搜索函数名有较大的可能搜索到官方文档,而官方文档往往对函数的用法提供较为权威的解释。所以“tree-seq函数用法”不如直接输入“tree-seq”。

那么如何筛选靠谱的搜索结果呢,一般来说搜索结果按照来源可以分为这么几类:官方文档,学术论文,专业门户网站,专业问答网站,wikipedia,相关博客,专业论坛,普通论坛,普通问答网站,国内百科类网站。事实上信息的可信度也可以按照这个顺序来评判,而在出现可信度相似的不同信息的时候,我们可以通过三种方式评判:看信息下方的评论,看更多的资料支持哪边的信息,直接进行尝试(如果尝试的过程没太大危险性)。

另外学术论文往往具有比较强的方向性,除非你确信自己的问题搜索范围可以缩小到与相关论文对口,否则轻易不要使用论文搜索。尤其是,在任何情况下,不要使用国内的任何毕业论文作为学习资料。

接下来一个不那么方便的方式便是查阅书籍,比起互联网上的搜索结果而言,书中的信息是更加“良好组织的”(系统化),同时也更加偏向于可信(也看具体哪本书)。因此,查阅书籍的方法往往在网络上的搜索结果比较混乱的时候,或者是需要查阅的信息专业性过强的时候使用。

书籍查阅的具体方法可以归结为:
对问题分类 -> 相关分类下找书 -> 书名与问题/答案匹配 -> 查阅目录 -> 章节名与问题类型匹配 -> 阅读章节。

在查阅资料的时候我们必须控制住自己过度的求知欲——因为知识的背后总有更多的知识支撑着,如果我们摸着这条线索一直走下去是永远走不完的。这里我们就需要明确我们的问题来自那个领域。如果对问题解决方案的追踪超出了这个领域,那么我们应该重新转向问题本身。

事实上,很多问题都能通过猜-查-试的方式去解决,但是有时候,我们经过了好几轮猜查试都没能成功,那么我们就需要下一个办法:问。

提问的艺术足够写一本厚书了(其他的也是如此,比如猜的艺术,查资料的艺术),在这里我只进行简述,在之后的细化章节中会加以完善。

其实,问的艺术,归根结底就是什么时候问,通过什么问,问谁,和怎么问。

什么时候问,如上文所述,是在多次猜-查-试未能成功,或者相关资料无从查阅时的无奈之举。

通过什么问和问谁,建议是通过专业的问答网站进行交流,切记绝对不能在非专业问答网站(如百度知道,搜搜问问之类)进行提问。

至于怎么问,相关的问答网站一般都有提问手册,大家参照上面的规则即可。这里提一点通用的:一定要提供尽可能多的信息,问题发生的一切背景、你在问题发生前做了什么、得到了什么反馈。任何细节可能都是问题的关键信息,千万不要自认为“这个细节可有可无”,甚至“这个细节说出来丢脸”而不去透露。

有了猜、查、试、问,一个通用的分析、解决问题的模板就形成了,至于在计算机学习中如何使用,后文将会进行细化。

除了分析、解决问题之外,另一个能力也非常重要——在不同的知识体系之间建立关联的能力。

这是一个比较形而上的问题,说白了就是所有学科都是同一门学科,无所谓文理。

举几个比较直观的例子吧,

古典音乐中有一种不断叠加更加丰富的自身主旋的作曲技法叫做“卡农”(没错这是一种作曲技法,只是有时特指比较著名的那首曲子),如果主题自开头单一演奏,之后交错叠加自身就称为赋格。这种作曲技法归纳为图形可以视作分形几何,归纳为计算机程序设计方法可以视作递归。

经济学中的平衡机原理和化学中的溶液平衡有着惊人的相似,而如果我们观察电路中的自感效应,也会发现相同的模式(环境的变化导致被研究对象产生逆变化的趋势)

在使用模仿自然进化的进化算法中,程序的运行会显现出动力学特征。

如此等等,事实上,这一现象在数学上称为同构。

其实很好理解,(至少大多数观点认为)我们生活在同一个宇宙中,宇宙由最简单的法则主宰着,所有事物都遵循这些法则。而小事物组成大事物的过程中,法则不断相互组合叠加,形成了千变万化的宇宙,也诞生了五花八门的学科。

所以说,产生不同的学科仅仅是由于人类的大脑不够装下整个宇宙的信息,所以我们就把对宇宙的观察过程和结果进行分类,一个分类代表一门学科,一个学科解释宇宙的一部分。(这里之所以说观察而不是说分析,是因为分析是理性的,而观察不仅仅可以诞生数理化,还能造就诗书礼乐)

接下来我们就遇到一个问题,如果我们需要仔细研究一门学科,那么我们一定会受该学科的边界所制约——就如瞎子摸象一般,摸象腿的瞎子若是想要理解为什么象腿在被刺了之后会哆嗦,那就非得摸到象的脊柱不可了。

所以,保持这种“所有学科都是同一门学科”的形而上思想,将会对你的入门和深入大有帮助。

那么,我们究竟该如何将这种思想用于我们的学习当中呢?

最重要的,便是联想,联想的本质是“从一个事物想到具有共同点的另一个事物”。

在学习的时候,当我们遇到难以理解的问题或概念,不妨从我们熟悉的领域找到相似的问题/概念,举个例子,理科生在学习诗歌平仄韵律的时候完全可以将这些规则归纳为一个有穷自动机,反之亦然。(其实“道本是一”这一概念太大了,在这里比较难以讲清楚其应用,稍后的针对计算机的部分将会给出更详细、更具备说服力的例子。)

一旦我们能够根据自己熟悉的领域,来学习不熟悉的领域的内容,能够在各类知识体系间相互联想,那么我们的记忆力也能够得到提升,事实上,我们只需要分别记忆不同知识体系之间的共同点和不同点,就能够更好的记住更多的知识(这也是计算机中常用的一种压缩存储算法,比如对音频左右声道进行这样的处理,可以获得将近50%的无损压缩率)。

顺带提一下,这篇文章写到现在,从学习模型的提出一路讲完该如何分析解决问题,而后跳出分析解决问题这一分支,再讲知识间的同构,这一过程在写作技法中叫做递进(层进),在计算机算法中叫做深度优先,同时,在这个深度优先书中有一个节点(关于几种不良的分析解决问题的人群的讨论)内部包含一个通过广度优先方法构建的图,这种在节点中包含图的现象在图论中可以称为超图。而文中很多问题留待下文细化时进一步探讨,这种学习方法叫做螺旋式上升,计算机中称为递归。

(其实觉得这一段写的并不成功,道本是一这个概念需要更多的是自己的领悟,而不是谁如何去讲述的问题,当然,和这个话题摆在通用学习方法这一块也有关系——一时很难找出足够好的说明方法,后文中圈子缩小到计算机的学习,可能会将得更深更好一些)

接下来,学习通用方法的第三部分,是关于学习规划的问题。

在这里我们暂时只谈学习顺序的规划。

我个人认为,层级性很强的,所谓“先打基础再学上层建筑”的学习方式并不合理。因为事实上,很多“上层建筑”的概念比基础要容易理解,并且有趣的多。

其实我觉得,很多人提倡先打基础的原因并不是这样学习速度快,而是可以避免学习的时候只痴迷于上层的东西而导致知识体系不扎实,最终学些似是而非的东西甚至沦为神棍。

就像你学一门乐器,你真正想要做的是演奏自己喜欢的曲子,然而老师让你做的是每天端正拿乐器的姿势,练习音的准、稳,练习长短音,音阶,琶音,这是很少有人会喜欢的。事实上,只要你有一些基础(比如能够以正确的姿势演奏出常用的(通常是中音区)的一些音符),那么你就可以私下里尝试演奏一些曲目了,只要你不因此废弃了基本功的练习即可——否则你的水平可能与街头乞讨之人没什么两样。

其他学科也是一样,基础帮助你构建稳固的知识体系,而上层建筑帮助你保持对这一知识的兴趣——同时,有时对于上层建筑的科普式的学习,有助于启发对基础的理解。

事实上,这一点在计算机、物理、数学等较为抽象的理科类学科中更为凸显,继续举例子:

第一种学习路线:先学万有引力,圆锥曲线方程,再学行星运动轨迹
第二种学习路线:在科普书上了解行星的椭圆运动,再去学万有引力、圆锥曲线方程,之后重新去分析行星的椭圆运动
这两种学习路线哪一种更好?

我相信多数人会接受第二种,因为在第二种学习方式中,我们先根据对“上层建筑”的一些了解,获得了部分对基础的启发。这时再去学习基础,事实上便是同时获得了知识与认同感,同时也能够对于基础知识的“意义”有自然的理解。

这里便提出了一个比较重要的概念:认同感。

我个人认为,认同感是学习中最重要的角色之一,非常典型的例子就是:符合直觉的知识容易学,而不合直觉的知识难懂。

认同感往往诞生于“我早就有这样的想法,只是书中挑明了”,或者“这个东西一直隐隐存在我的脑海里,只是我一直没有发现,这本书把他总结了出来”。

一个良好的学习过程,事实上并不是单纯的汲取知识,而是在学习的过程中,通过概念获得潜在的认同感,通过认同感理解概念之上更精确的描述(比如公式),再根据这一过程获得更多的启发,而这些启发可能在深入的学习中带来更多的认同感。

这样基于认同感的学习,不但能够保持兴趣,还能够使你在学习的过程中,时刻知道自己在学的究竟是什么,有什么用。

所以我个人比较提倡碎片化的学习方式,在学习的过程中可以比较随意地、科普性地接触一些更上层、高层的概念,同时学习较为底层的基础,在学习底层基础的时候,你会发现这些知识最终如同粘和剂一般,逐渐将碎片化的上层概念粘和起来,变成逐步完整的知识体系。当一个又一个上层概念由基础知识而得到解释,你一次又一次大呼“原来如此”的时候,那么你的知识也将变得逐步扎实起来。

然而,如同前文所说,这种碎片化的学习方式要求你能够足够了解:哪些知识你只知皮毛,哪些知识你相对深入了解,哪些知识你已经可以运用自如了。如果自己很难把握对各类知识的熟悉程度,那么还是层级式的学习方式比较好。(关键还是戒骄戒燥)

通用学习方法,大体上就这三点了(当然还有不能懒惰,精益求精等等非常重要的陈词烂调在这里就不提了,因为一方面说的人太多,另外一方面这个属于比通用学习方法更基本的素养已经超出本文探讨范围了)

时间不早了,我先歇一阵子,接下来的第二部中,我将渐渐引出如何在通用学习方法之上构建针对计算机学习的初步学习模型。
来自 软件综合
2013-1-7 10:28:58
1楼
好文章,赞个。。。。。。。。。。。。。。。。。。。。
折叠评论
加载评论中,请稍候...
折叠评论
2013-03-31 12:18:18
2013-3-31 12:18:18
2楼
打了这么多字都快累死了吧。太辛苦您了[s:271]
折叠评论
加载评论中,请稍候...
折叠评论
2015-10-29 21:46:14
2015-10-29 21:46:14
3楼
说实话内容我没太详细看,顶个。
折叠评论
加载评论中,请稍候...
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
ID:{{user.uid}}
{{user.username}}
{{user.info.certsName}}
{{user.description}}
{{format("YYYY/MM/DD", user.toc)}}注册,{{fromNow(user.tlv)}}活动
{{submitted?"":"投诉"}}
请选择违规类型:
{{reason.description}}
支持的图片格式:jpg, jpeg, png