从编程思维开始,聊聊学编程

近年来大学最热门的专业无疑是计算机,而在中小学基础教育这块儿,编程热也是方兴未艾,连奥巴马也提出“编程要从娃娃抓起”。

当我看到才小学二年级的女儿,都已经在学校学编程了,而七年级的儿子也才刚刚开始接触Scratch(MIT开发的简易编程环境),不禁有点按捺不住。于是靠教编程谋生的我,生平第一次动了让13岁的儿子系统学编程的念头。

为什么要学编程?

现在任何行业都离不开计算机,会编程这项技能,在求职时就如同90年代会英语一样抢手。

学编程,不是为了将来当程序员。

而是为在自己行业里获得更多的机会, 比如说做财务的,工作中少不了和excel表打交道,即使对每个菜单功能都很熟悉,还是有需要定制一些专门的查询功能,这时编程就是不可或缺的技能。

也是因为计算机对今天我们的生活而言,就如同汽车对出行的重要。开车即使有定期去车行保养,学习汽车相关的知识,万一出行途中汽车发生故障也不至于惊慌失措;而且说不定因此感兴趣了,钻研进去,自己尝试做个升级改装也未尝不可。学编程,也是同理。电脑或是手机无论硬件还是软件,总会有出问题的时候,会编程的人可以自己做简单故障定位,也可以作为兴趣爱好在闲暇时间里做个网页,写给APP什么的。 

【1】编程,学什么?

每次聊起学编程,被问到的第一个问题往往是“学哪种编程语言好”。

回答这个问题之前,我想问你,觉得自动档和手动档的车,哪种好呢?

当前初学者中最流行的Python和Javascript 就像自动档车,编写简单,强大库函数支持广泛应用;而最为经典的C语言就像手动档,难学难用,还需要通晓编译原理、操作系统和计算机体系结构,当然也最能体味驾驶的乐趣。

以前总觉得C语言对初学者太难了,这个想法今年5月在安大略省高中编程赛被彻底颠覆。一支由三个分别是五年级,七年级和八年级亚裔男孩组成的队伍特别醒目,年龄比其他选手小很多,却在由各个学区优胜者组成56支高中编程队脱颖且出名列第九。这三个孩子就是用C语言写的程序,C语言也是他们唯一接触过的编程语言。所以初学者具体学什么语言,因人而异。

思维指导行动。未来人人都会写代码,但程序设计是否简洁高效,就得在思维上见高低了。十年前,卡耐基梅隆大学计算机教授Jeannette Wing 提出Computational Thinking “编程思维”的概念,指出通过学习编程,内里培养的其实是认识问题和解决问题的思维方式,而这种思维方式可以跨界应用到其他领域的学习和实践中。

也就是说和编程语言相比,编程思维是内功心法,在此基础上,学习和使用哪种语言,犹如使用哪种兵器,只是工具层面上的东西

【2】什么是编程思维

编程思维的四个组成模块。图片来源于网络

编程思维本质上来说,就是能够把现实生活中的复杂问题,逐步拆分成可理解的小问题,(Decomposition 拆分),接着根据已有的知识和经验,找出新问题和以前解决过的问题的相似性,举一反三琢磨出规律(Pattern Recognition 模式识别),然后将问题里涉及的数据抽象(Abstraction)到数据结构(变量,数组,链表等等),把数据处理过程可重复执行部分抽象(Abstraction)成函数模块,通过循环执行,最后根据前三步的分析成果,设计步骤,写出算法(Algorithms),从而解决问题。

编程思维本身是一个非常抽象的概念,下面我举个例子来详细解释一下它的四个组成模块。

【3】编程思维1-2-3-4

我们都听说过这样一个故事:数学家高斯在三年级时候,老师要求从1+2+3开始一直加到100,其他同学都费劲的一个数一个数的加,只有小高斯注意到了这些数可以两两配对,相加和为101:

1+100=101

2+99=101 等等

一共有50对,最后的和可以用乘法来做:(50X101)=5050

高斯的上述解题思路充分体现了编程思维中的拆分和模式识别,再进一步延伸,就可以概括出求任意范围【a, b】连续整数求和公式:(a+b)x (b-a)/2。

把原题扩展一下:

假设你有100张扑克牌,依次编号,从1到100,打乱洗牌后,突然发现少了一张,怎么知道少掉的是哪张?

下面我们试着用编程思维一起来一步步的解决这个问题。

第一步拆分:通过一张一张的查找,先在这堆牌里找1,再在剩下的牌里找2,然后再找3,依次下来,最后总能发现哪张少了。这种方法的局限是如果牌张数少还行的通,如果张数多,费时费力的,但符合一般人的解题思路。

第二步模式识别:如果能联想到高斯的求和题,所有牌的面值总和应当是5050,将手上的牌一张接一张的加起来,假设得到的和是5040,用5050-5040=10,很快知道少掉的那张牌是10.这种方法比起前一种,明显棋高一着。

第三步抽象:扩展到现实生活中,假设有一副扑克牌,少了一张,如何快速定位少的是哪张?

一般情况下,我们都会重新理牌,先把4张Ace都找出来,再把四张2放在一起,依次下去,最后总可以看出哪张牌的哪种花色少了。

这种常规方法效率很低,如果联想到我们刚刚建立的求和模型,是不是可以用来更为快速有效的解决这个问题?粗看每个数字都有四种花色,不唯一,好像不适用。

但是如果我们能解决如何把扑克牌花色和数字映射到计算机可以处理的数据的问题,就可以试用刚才的求和模型了。这也是考验抽象的能力的时候了。

不妨按花色来,设红桃A 为1 , 红桃2 为2 ,依次到K是13,然后方块A为14,到方块K是26,以此类推,黑桃A到K是 27到39,梅花则是40到52。

这样一来问题就转化成了有52张扑克牌,依次编号,从1到52,洗完牌,发现少了一张,请问少掉的是哪张?是不是就可以很容易的套用第二步里总结的求和解题模型了?

再试想你有一千,一万,甚至上百万副扑克牌,每副都少一张(不尽相同),怎么能快速定位的少掉是哪些牌呢?

只要你能设计出快速定位一副牌里缺了哪张牌的计算方法,无论多少副牌,计算机都能在一眨眼的功夫,全部准确无误的给你找出来。计算机相对于人脑,有存储容量大和处理速度快的优势,所以计算机最擅长的就是重复劳动。能够让计算机从事高效的重复劳动的前提,是人先思考和分析怎样把复杂工作分解成多个可机械重复执行的模块,然后才可以通过程序让计算机来处理。而这步比写程序本身来的重要的多。 

第四步 算法:当要处理的数据映射到合适的数据结构,可复用的处理模块也都分辨识别出来后,下一步就是利用条件,循环,子程序模块,来规划出程序设计步骤,从而解决问题。

所以说,编程思维的核心,不是编程语言,也不是语法,甚至不是算法或数据结构本身,而是如何分解问题,从中发现规律,建立解决问题的模型,并映射到合适的数据结构和算法上,然后才能根据算法写程序实现。在此过程中,前两步分解和模式识别,其实完全隶属数学思维范畴,也是编程思维的基础。而抽象和算法才是编程思维所独有的。 也是在孩子学编程过程中,最需要强调的。 

【4】编程思维,怎么学?

从以上对编程思维的解析来看,培养编程思维的前提条件是有扎实的数学,尤其是代数基础。数学基础还没打牢,就开始学编程,无异于建造空中楼阁。

在孩子有一定代数基础的前提下,抽象思维和算法这两部分应该是编程思想的重点,也是难点,那么该怎么学呢?

如果对这方面有兴趣的话,我建议你了解AP College Board新推出的一门课程叫 AP Compute Science Principles,这门课过去四年在不少大学里已经试点开设,旨在教授编程思维和计算机科学中的核心基础内容。我打算让儿子自学的斯坦福的CS101课程也是因此而产生的。而AP Compute Science Principles这门课程从今年秋天起也会在高中开设,这是计算机教学领域里非常值得期待的一件事情。

回到学编程的话题,能够让孩子主动心甘情愿的学任何东西,大都满足两点要求:“有趣”和“有用”。因为有趣,才能激发其好奇心,去探索思考。因为有用,才能从中获得成就感,成为进一步学习的动力。

遵循以上两点,我给儿子制定了如下的编程学习计划。

第一周: http://lightbot.com/hocflash.html 这款基于Flash的可编程游戏,不用来学编程,单纯作为益智类类游戏来完也很有意思。 从最初的顺序执行指令,到后来引入条件,循环,和子程序,是训练编程思维的好工具。 其中子程序部分,非常考验孩子有效分辨可复用编程模块的抽像能力。

同时阅读Blown to Bits的部分章节 http://www.bitsbook.com/excerpts/  ,全书的PDF版可以在链接里免费下载。学习编程,首先需要回答为什么要学的问题?这本书通俗易懂的介绍了作为信息技术主体的计算机如何改变着人类社会的方方面面,引导孩子在信息爆炸的时代里辩证的看待各种新兴技术及其影响。 

第二周:介绍编程思维,可以用我上面所举的找扑克牌的例子,看看孩子能否结合他玩lightbot游戏的经历,对编程思维有所认识。

第三周开始:使用斯坦福大学的CS101在线课程开始自学。 

https://lagunita.stanford.edu/courses/Engineering/CS101/Summer2014/about

该课程以Javascript作为工具,教授编程思想和计算机技术中的核心基础内容, 课程以视频和在线练习结合的方式,自学模式下,预计六周完成。而这门课虽然不是专门教编程的课,但是涉及的编程都是孩子们普遍感兴趣的数字图像处理实验,相信不少孩子会喜欢。

下图是一些学生在学这门课程过程中,用JavaScript写的程序生成的Fractal(分形)图像。

图片来源:Richard Kick

顺便提一下编程语言,我一直比较倾向于初学者学JavaScript,JavaScript作为Web客户端的主流编程(脚本)语言,可以在浏览器里直接运行,孩子写几行代码,就可以在计算机或智能手机上查看效果,即简单直接,又有用有趣。

以下为该课程涵盖内容:
  The nature of computers and code, what they can and cannot do
  How computer hardware works: chips, cpu, memory, disk
  Necessary jargon: bits, bytes, megabytes, gigabytes
  How software works: what is a program, what is "running"
  How digital images work
  Computer code: loops and logic
  Big ideas: abstraction, logic, bugs
  How structured data works
  How the internet works: ip address, routing, ethernet, wi-fi
  Computer security: viruses, trojans, and passwords, oh my!
  Analog vs. digital
  Digital media, images, sounds, video, compression

我把每章节内容从头到尾过了一遍,总体难度适中,如果家长能够给予适当的指导和帮助的话,初中生自学不成问题。如果孩子通过以上两个月课程,对编程产生兴趣的话,那么下一步,就该系统的掌握一门编程语言了。

【5】学了编程思维,然后呢?

没有实践的思维,只是空想。学完编程思维之后,还是有必要深入的学习一门编程语言,在实践中应用编程思维解决问题。学习编程语言,网上有大量优质资源,孩子可以用来自学。

我在教学中常用的有以下几个网站:
Codecademy 好处是常用的编程语言的教程都有。缺点是Bug不少,明明按照要求输入完全正确的代码,服务器端老是显示代码错误,让孩子非常沮丧。遇到这种情况,多试几次,如果还是不行,鼓励孩子到Q&A论坛上看其他人是如何解决这样问题。
https://www.codecademy.com/ 

滑铁卢大学计算机系的CS Circles, 也是相当不错的学习Python的资源。
http://cscircles.cemc.uwaterloo.ca/

Codingbat是我很喜欢的在线Java和Python的练习网站。
http://codingbat.com/

虽然编程可以自学,条件允许的情况下,几个程度相当孩子一起学,互相交流,互相帮助,共同进步的效果会更好。前文提到我在省高中编程竞赛时遇到秒杀很多高中生的三个用C语言的小男孩,当时很感兴趣的追问他们是在哪里学的编程。原来他们每周课后两次到附近的高中Woburn CI,参加由那里学生组织的编程俱乐部。编程俱乐部以师傅带学徒方式运作,大孩子教小孩子,有经验的帮助新手。虽然没有老师指导,但是这种以共同兴趣为基础的互助氛围里培养出来的孩子居然完胜那些经过两三年正规编程训练的大孩子,真是很让人深思的事情。

推荐阅读更多精彩内容

  • 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及...
    dle_oxio阅读 10,654评论 6 244
  • UI设计行业目前来说发展前景还是不错的,所以这是现在很多人想要转行UI设计的原因,成为真正意义上的白领,拿着过万的...
    UI设计司阅读 335评论 0 0
  • 我们在致歉中成长我们在成长中致歉 我们在反省中成长我们在成长中反省 一生太长太短,我们总是会犯很多错误,有大有小。...
    一人青争阅读 282评论 0 0
  • 你的脸怎样,其实代表了你的生活状态。如果你经常感觉压力山大,你眉头肯定紧紧的;反之,如果内心舒畅,就经常眉笑眼开,...
    潇雨姑娘阅读 218评论 3 2
  • 这些天跟着电视追剧,看了几集《欢乐颂》。在这些女孩子各自的苦乐人生背后,除了价值观、阶层差异和固化、职场规则、拜金...
    西川紫阅读 633评论 1 1