敏捷学习方法论

浅尝则止是正义!逃避困难也可以!论敏捷学习方法在编程学习上的应用。

0. 浅尝则止未尝不可

我们讨论学习方法的时候,常有的一个观念就是深入学习,认真钻研总是好的;不深入,肤浅,皮毛,浅尝则止都是贬义词。这篇文章我想说的一个观点是:

浅尝则止未尝不可。

特别是应用在编程的学习上,好读书不求甚解其实是一个不错的学习模式。再来我还会用敏捷思维来完善这种学习模式,形成一个学习方法论。

1. 想学好编程,想学多好?其实是学习的项目管理问题

这里引入一个项目管理的概念:“项目管理三角形”;

如图,想要追求质量,就要投入相应的成本和时间。如果工程范围再不进行限制,整个项目的成本将会爆炸式增长,最后根本收不了工。

要学习一门技能,完全可以套用相同的模型。

不管我在前面抖机灵说什么“浅尝则止未尝不可”,但学一门技能,谁又不想学得炉火纯青,达到一定造诣呢?

在编程领域能达到什么样的学习成果,就要像项目管理那样考虑学习投入的平衡问题。我们把三角形的标注换成这样应该很好理解:

完全套用这个三角形来建立学习方法又有些问题,因为在学习上我们的成本投入基本就是自己的时间,特别如果是通过阅读来学习,不是报各种学习班的话,金钱成本几乎可以忽略。

我们在学习上的投入具体有哪些呢?

  • 首先一定是时间投入,花的时间越多自然会产生更多的学习成果,学界公认,无可辩驳。
  • 接下来要看我们投入时间的质量,其实就是专注度,如果熬更守夜,导致学习专注度不够,投入再多时间,质量一定是低下的。
  • 最后,是兴趣,兴趣可以影响我们的专注度;如果兴趣浓厚,在没有学习的时候我们的大脑都在思考和处理;如果兴趣浓厚,坐电梯都会思考电梯的控制算法,相当于一直在利用碎片时间进行学习。

这三个投入是互相影响的,所以这个公式只好把三个因素乘起来:学习成本投入 = 时间专注度兴趣。给学习成本投入取个热血的名字,叫学力值吧,最终公式:

1
学力值 = 时间*专注度*兴趣

于是三角形中的两边就合起来,画成一个正方形:

那么还剩“范围”这一边,看看编程这个技能有可能涵盖的范围吧:

首先从应用范围来看,

学习编程可以用于数据分析与统计、人工智能、知识管理、游戏开发、文书处理、机械自动化控制……

或者打开你的手机看看有多少 APP 就有多少不同的应用。

而这些不同领域的应用需要的编程知识其实也不尽相同。

再来看学习编程有可能涉及的知识范围:

  1. 编程基础知识,就是我们在各种“从入门到精通“的编程入门书里面学到的那些知识。举例如:

    • 基本语法
    • 数据类型
    • 条件判断
    • 循环、递归、嵌套等过程控制
    • 面向对象的思想
    • 链表、二叉树等各种数据结构
    • 数据库的操作

    等等等等

  2. 数理知识,就像刚刚提到的各种应用领域,在不同的应用领域可能会用到好多不同的数学知识:

    1. 图论
    2. 离散数学
    3. 工程数学
    4. 逻辑学
    5. 统计学

    等等等等

  3. 计算机系统的相关知识,因为编程是在计算机上操作,一些计算机的知识总要懂吧,至少都要学个打字和一些基础操作,在当今网络时代,还要学一些网络知识才能做出实用的软件应用。

  4. 英语!是的,英语技能对于学编程非常重要。会一点点英语才能看懂程序语法。而会很多英语,就可以看英文文档了。偷偷说:在文档里学习才是高效呢。要是读者大大们英语好,写编程教程的人会丢饭碗的(这句划掉)。

综上,如果我们不注意控制学习的范围,我们需要投入的学力值就会去填无底洞了。

那么投入编程学习前,请参考这个模型,根据自己的兴趣、自己能够投入的时间、自己想要应用的范围做一个规划吧。

2. 要深度还是要广度?其实是投入与回报的平衡问题。

前面我们讲了一个平面的学习模型,似乎只要投入学力值就可以很顺利获得学习成果。可事实仍然是编程学习者众,学成者寥寥。其实除了学习者自身的规划与投入,我的观察是,很多编程学习教程本身对范围没有一个好的把握,典型如:《某语言从入门到精通》、《N天掌握某语言》。

回顾我们的学习模型:

这种教程想到达的学习成果是精通、掌握(我理解这两个词是一个意思)。

投入的时间是N天?一本书就从入门到精通?写书的是有多瞧不起自己的专业?

这种书翻开会发现,大同小异:比如先是教你输出一个“Hello World”,然后就是基础知识比如语法、条件判断、循环、数据结构;再讲到面向对象编程;再强行切入网络、数据库这些劝退新人的环节,可能作者都知道后面没几个人在看了就更加不注意对新人的友好度。最后扔几个编程实例,也许就是所谓的精通或掌握了。

我们要意识到的是,范围是广度和深度两个维度构成的。

而这两个维度对学力值投入的需求是不同的。

比方说,我花五天就可能入门五种编程语言(广度),但是要精通一门语言(深度)需要花五年。

学习的广度和投入的程度正相关,呈线性增长。如图所示:

学习的深度和投入的程度也是正相关,但是呈对数增长。如图所示:

而广度本身又会影响深度,这句结论有个很好理解的俗话叫做:

触类旁通。就像我们经常观察到很多人学的东西多不说,学习新东西还能很快理解,抓住重点,找到学习方法,精进自己的技艺。

因此容我再点题:逃避困难也可以。

因为我们以产出的成果为导向来看,程序设计是一个开放性的课题。

比如我们需要实现一个数据存储的需求,数据库可以,看起来很蠢的文本文件也可以。

新手很头疼的递归啊排序啊这些算法是能解决很多性能问题,但在不需要性能的时候,写个很蠢的嵌套循环也可以。

也许会有人质疑,想要把编程学好,认真,努力,迎难而上,为什么到你这就不可以了?

我在本文表达的意思,主要还是针对学力的保护和高效利用,保护我们的兴趣,专注力,更高效地利用学习时间。如果我们提前遇到了高等级的怪兽,先走别的路就好,等我们学了更多,再回过来,常常能意外发现过去的困难并不是困难。

因为程序的这种开放性特点,成了我们学习编程才享有的特权。我们为何不利用呢?

3. 拥抱敏捷:敏捷学习方法

本文开头提到,用项目管理的思维来学习编程。而项目管理的方法论是在上个世纪60年代建立起来的,适用于人类对各种工程项目进行大规模合作。

软件开发行业的出现显然是晚于传统项目所在行业的。到了2001年,一群软件行业大佬相约去滑雪,互相吐槽抱怨了几句终于发现大家都不太认同旧时代的章法,于是滑雪之余顺便签署了一份“敏捷宣言“。

敏捷宣言的原文以及配套的十二条原则可以在官网上看到(链接附后),经过多年的发展,敏捷方法已经形成了一套成熟的管理体系。这套体系大概长这样:

不是开玩笑,这真就是传统工程项目和软件工程项目的最大区别。

在传统工程中,如果要建造一辆汽车,需要一个零件一个零件生产,组装,最后完工才能投入使用。

敏捷开发是这样:我先做滑板车,不需要考虑路况、安全、燃油、性能,满足代步的基本需求先。下一步升级可以把轮子放大,加上把手,就变成了踏板车。

把用户正踩脚下滑着的滑板车轮子改大?每次软件更新不就是做类似的事吗?就是说每一个小的项目进度都可以单独成为一个独立运行的产品。

说了这么多软件工程的项目管理方法,我跑题了吗?

别忘了,我们在讨论编程的学习方法,编程的产出就是软件啊!

是的,编程学习完全可以采用敏捷思维来进行!

回顾我们上一节讨论的学习范围示意图。我们确实知道,一味的浅尝辄止和逃避困难,导致在一定范围内深度不足,就无法达成我们想要的学习成就。但经过本节的讨论,我们是不是可以试着,敏捷地,达成学习成就呢?

即使刚入门的新手,抱着“想要做一辆跑车“的心态去学习,有错吗?为了实现这个远大的目标,我们知道要一步一步的来。

那同样的一步,我们学着做一个滑板车还是做一个跑车的轮子?(也许直到放弃都用不上这个轮子)

敏捷方法给软件行业带来了巨大改变,我认为敏捷也能够让我们的编程学习得到效率的提升。

也即是我们探寻好的编程学习方法的最终目的:

在一定学习范围内,用更少的学习投入,获得更多的学习成果。

4. 学习成果的积累

敏捷学习方法还会给编程学习者带来一个非常重要的好处。就是学习成果的积累!

如果是按照传统的编程学习模式,从入门直到放弃,我们都没有造出一辆跑车,最后硬盘里会散布着堆积着一辆永远不可能完成的跑车的零件。

如果按照敏捷方法来学习,我们一开始就能造出一辆滑板车,等我们最终造出跑车的时候,我们已经造了自行车、电瓶车、摩托车。

是的,编程学习特别适合积累学习成果:

  1. 软件不会占用物理空间。

放硬盘里,仓储成本不要太便宜。

要是做木工,学徒时期做的东西只能当柴烧了。

  1. 代码可以复制粘贴。

每一次产出学习成果都可以复用原来的代码做一个新的版本,并且保留上一个版本。

要是做木工,做好的板凳不光很难改,就算修改也只能在原来的板凳上改。

  1. 可以修改更大的成熟的项目,放大我们的学习成果。

举例如 Github,我们的学习成果甚至可以提交成为某个项目的贡献,我们也可以 fork 别人的项目作为自己的项目在上面修改。

要是做木工,师傅是不会把他做好的成品家具给你练手的。

  1. 更容易应用自己的成果。

我们可以把自己做的东西放到自己的网站上,打包放到手机上,就可以用了。就算是发布到应用商店也是我们可以承受的价格。

要是做木工,我们做好的板凳也是可以自己用的。做得好的挂淘宝上卖?好像也可以?(划掉划掉)

总之,应用敏捷学习方法,我们可以积累更多的学习成果,我们投入的宝贵学力可以取得更多的收获,更多的收获又可以激励我们的学习兴趣。

怎么实践我们的敏捷学习方法呢?我模仿滑雪场那群大佬拟了一份敏捷编程学习宣言,包含了一套价值观和一些原则性的方法,希望对各自努力前行的自学者们有所帮助:


敏捷编程学习宣言

作为自学者,我们身体力行地实践和探索更好的编程学习方法,提高了自己的学习效率。为帮助更多的人,我们建立这样一套价值观:

保持兴趣和专注地高效学习 高于 大量投入时间的学习

平衡学习范围的深度和广度 高于 大量投入学力追求深度

在小范围内及时产出成果 高于 对知识点的全面掌握

响应变化 高于 遵循计划

以上,尽管右项有其价值,我们更重视左项的价值。

敏捷编程学习方法

基于以上的学习宣言,我们总结了一些可以遵循的原则来实践适合自己的敏捷学习方法:

我们最重要的目标,是产出学习成果。

寻找容易产生学习成果的编程语言入手。而这样的编程语言容易产生学习成果:开发环境搭建简单;编译和打包简单;发布和运行简单。

寻找社区很活跃的编程语言入手。社区活跃意味着有很多方便的库可以用,很多热门项目可以参与,很多问题都能 Google 到答案。

不用局限于一本书,可以同时阅读多本书籍。因为不同的书籍目录结构不同,学习范围的广度和深度都不同,我们可以根据自己的需要来搭配书籍。

尽量选择电子书这类非实体的教材。便于我们用 Ctrl+F 来检索书籍,还可以 Ctrl+C Ctrl+V,大量提升学习成果的产生效率。

用好官方文档,因为教材覆盖的范围有限,官方文档可以帮我们兜底,补充我们实现学习成果所需的知识点。编程语言基本上都有自己的官方网站,而官方网站基本上有官方文档。找到它们,在不懂的时候先搜索一下官方文档。

用好 Google。在教材、官方文档都解决不了我们问题的时候,Google 是最后的兜底手段。希望你能尽量用 Google 来搜索自己需要的知识点,实在因为网络原因用不了,还可以试试 Bing。如果用某度,只会给我们带来学力的损失。

遇到上面的办法都解决不了的困难,先绕开困难。条条大路通罗马,甚至小路也可以。实现一个可运行的程序有非常多的方法。

最后,简洁为本,以最小可运行的产出为目标来学习,大胆略过书中用不上的知识点,减少不必要的学力投入。


附:

敏捷宣言 https://agilemanifesto.org/