Terence
Terence

Let's geek and art.

为什么SICP要讨论那么多的初等数学

SICP: MIT的名著Structure and Interpretation of Computer Programs.

谈论/教授「软件工程」的一大难点在于它太过抽象,你必须辅之以相应的代码,才能较为清楚的表述某一条软件工程的原则。

(抽象不仅导致读者对概念难以把握,更糟糕的是,抽象能够从多个角度被理解。如果不辅之以实际的例子,你的的理解可能会变成误解。这就是为什么教材需要大量实例的原因。而很多大牛的书之所以难读就在于例子太少,导致不得不先消化概念的抽象,再把误解变为正解。)

筛选合适的例子可并不是一件容易的事情。代码量太少就无法体现出运用相应原则的必要性。学习者只会感觉做了一大堆“舍近求远”的工作,无法真心体会运用这些原则后会给自己带来哪些好处。可如果直接拿出一线的工程代码,其代码量又太大,以至于学习者无法把握重心,可能需要花费大量的时间才能辨别清楚一线代码的相关枝节与核心重点的差别。

而SICP采取的做法是使用「数学」中的问题来作为讨论的主题。初读SICP会给人非常多的错觉:

  • 为什么我要浪费大量的时间讨论四则运算?!
  • 这些东西不都是现成的吗,为啥要花功夫造轮子?
  • 怎么感觉所有的代码都是把一句口语变成了不同的格式?
  • 这是伪代码吗?真的可以运行吗?(这其实正是写得好的清晰代码的特点:代码本身就是注释)

为什么要讨论四则运算的实现?因为「数学」其实能够帮我们对齐认知、对齐对需求的理解。大部分的newbie developer没有意识到的一个问题是,写代码往往不是最困难的部分,最困难的部分在于对「需求」的拆解、对问题的精准理解。这也就是为什么experienced developer往往会说,遇到问题时首先不要奔向键盘,而是要奔向白板。在白板上、白纸上,先理清楚、拆解好你要解决的问题是什么、需求是什么,再写代码。往往,白板上的需求拆解,能够将进度往前推进80%。

但「需求拆解」这一步,又涉及到其它能力。但如果这里只是想要教授你「软件工程」的某个原则,直接给出一线的代码很可能会给学习者带来极大的挑战。并且,往往学习者意识不到这些困难并不是待学习的软件工程原则带来的,而是由需求拆解带来的。

幸好,世界上有一种东西叫做“基础教育”,对应到我国当然是9年义务教育。我们花费了9年的时间,对某些材料、需求和问题会达成高度一致的共识。毕竟,如果谁要是不认同这个「共识」,谁就会在中考、高考中败下阵来。而其中一个存储问题的宝藏区,当然就是数学。也即是,基础教育强制性地帮我们对齐了待解决问题的「需求」认知。从而大家根本就不需要拆解需求,这些需求的明细已经在无数的考试中深深地烙在我们的脑海里了。

但,熟悉的需求,并不意味着是简单的需求。事实上,跟随着SICP的脚步,我们会对数学中的很多初级概念有更深刻的认识和理解。那些我们再熟悉不过的函数操作,往往蕴含着大量不曾意识到的重复操作。于是,SICP带领你一步步地去识别这些重复操作,通过抽象、模块化,一步步为你引入软件工程的思考方式。你会发现,原来那么多风马牛不相及的函数,其实可以被一个统一的pattern来支配。而识别、提取出这样的pattern,能够为你增强代码的可复用性、加深对问题的理解。

因为有了「抽象」这个技术,它能帮助我们得以从更高的维度来处理问题,而不是局限在微观之中。很多developer,包括那些已经工作了十多年的developer,其实都不大明白抽象的作用。他们喜欢把一个函数写得巨长无比,好像如此就能体现自己的代码的高深。他们没有意识到,将一个长的函数拆成短小的函数(一个不错的短的标准就是函数的body部分刚好能够在显示器上全部展示完)是为了能够把细节压缩到一起形成新的抽象概念,从而能够运用这个新的抽象概念做更宏观的思考和解决方案的搭建。

又比如「有理数」这个概念,它其实是个复合的数据结构。虽然你可以把它拆成分子、分母,但为什么一定要把这两部分“粘起来”形成一个新的、被称作有理数的概念呢?理由是一样的,这样能帮助我们忽略不重要的细节,从而能够看到更宏观的本质,增强代码的复用性。SICP花费了大量的篇幅来重新讨论这些我们熟悉的材料。其重点就在于正因为这些概念是我们所熟悉的,所以可以更方便的引入新的视角和新的看问题的方式。而大部分人会因为所讨论的材料是自己所熟悉的,就会下意识地认为它毫无价值。

事实上,这种因为熟悉概念的引入而完全没有抓住学习重点的例子比比皆是。人们会因为材料的初等就放松警惕,认为所有的东西不过如此,从而被自己的“历史包袱”限定了自己前行突破的步伐。他们没办法抬起脑袋,从更宏观的视角来看清所要学习的重点到底在哪里。到底你所熟悉的材料是学习的重点,还是根据你熟悉的材料来阐述的新的看问题的视角和思考方式才是重点?无法区分「材料」和「材料所构筑的思想」是大部分处于认知初级阶段的学习者所有的通病。

所以,这里还会造成另外一个问题。有一部分人,可能凭借坚韧的毅力读完了SICP,但在一线写代码时却无法体现他在SICP中学到了相应软件工程技能。这大都在于他没有认识到,自己的学习重点不是早已熟知的数学,而是由熟悉概念构筑的视角和思考方式。


Appendix

另一个槽点是,从pragmatic的角度讲,lisp毕竟不是参与一线coding的主流。虽然Paul Graham通过Hacker News证明了它是可以被用来写生产代码的,但却依旧无法改变它不具备更强实用性的事实。

如此,学习SICP会给人有点暴殄天物的感觉。出色的思想,却无法直接被用到工作中。但幸运的是,新加坡国立大学已经用js来重写了SICP这本书。而js,随着node的发展,可谓是性价比最高的programming language。对产品的原型迭代和快速开发来讲,js无疑是首选。而如果SICP的所有思想都由js来展开,那无疑能够用更精简、更实用的语法来快速掌握SICP中传递的思想,并可以直接将其应用在实际工作中。

有兴趣的朋友,可以通过在微信公众号「GeekArtT」中回复「sicpjs」来获取下载链接。





近期回顾

绝命律师S05E06:托付终身的人

致富与黑客

当我们学习投资时在学习什么

 



如果你喜欢我的文章或分享,请长按下面的二维码关注我的微信公众号,谢谢!


  

更多信息交流和观点分享,可加入知识星球:


CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…

发布评论