追求神乎其技的程式设计之道(七)

编程入门 行业动态 更新时间:2024-10-06 16:19:16

追求<a href=https://www.elefans.com/category/jswz/34/1768211.html style=神乎其技的程式设计之道(七)"/>

追求神乎其技的程式设计之道(七)

追求神乎其技的程式设计之道系列:一 二 三 四 五 六

这次拖稿了很久,虽然下礼拜就要期中考了,但我决定还是要趁这个作业都刚交出去的忙碌低峰期来补上一篇,不然真不知道下一篇要等到什么时候了…(泣)

思考的高度

上一篇谈到了优秀程式设计师的第一要件:「热情」,这一篇我想要谈我觉得热情之外最重要的能力:「思考」,特别是抽象化的思考能力。

写程式可以说是一件进入门槛很低的工作,拜现代的GUI开发工具以及大量的open source library所赐,很多低阶、跟硬体和作业系统直接相关的细节都被隐藏起来了,所以说其实只要学会某种程式语言并且会把自己的想法巨细靡遗的转换为程式码,就可以说自己会写程式了。到达这个阶段并不困难,只要有心学习的话即使是国中生自己看看书或到巨X电脑上上课都能学会。那么究竟要如何跨过这个阶段,让自己能和巨X电脑的毕业生有所区隔呢?我认为关键就在思考的高度。

写程式需要的思考能力第一是逻辑思考,主要其实就是用正确、清晰的逻辑表达想法而已,说来简单但要做好也是需要一定时间的训练。第二是抽象化思考,这是许多人忽略掉的一点,也是我觉得区隔一个平凡与伟大程式设计师的重要特质。

我觉得所有的程式都可以看成一个巨大的金字塔,顶端是这个程式的最终目标,一个模糊的概念;底部是细节的程式码。而中间是一个经由不断切割与抽象化所构成的高塔,每一个程式都是切割为许多的元件、模组,再切为更细的class和function,再来是最底下的变数与逻辑判断式。

很有趣的是,不同的人看这个塔就会有不​​同的样子。初学者看到的塔只有两层,他们和人沟通的方法是巨细靡遗的描述程式码:「我在这里写个for,第一次把i设成0,在回圈内每次检查这个阵列的第i个元素…」,在他们眼中只有程式的目标和程式码本身,所以还可能会写出下面这种让人哭笑不得的注解:

 a = 1; // 把a设为1

有些经验后,会再多看到一层,利用function把一段程式码包装起来,赋予一个名字和独特的意义。学会这个后,就可以利用抽象化后的function名称来沟通,例如:「我在这个回圈里每次都用isCaptial来检查这个字串是不是都是大写…」再接下去呢,可以再利用class,利用design patterns,利用更大的模组、子系统来沟通,认真说起来,这其实是一个无止境的切割。

在资讯科学这个领域,抽象化是个无穷无尽的必要行为。因为世间万物实在太多太复杂,我们只好不断把东西归类,并赋予一个名称、一个意义,经由这样的过程我们才能用抽象的语言和符号来沟通,避免每次都要从最底层的琐碎细节开始说起。而平凡和伟大的程式设计师,我觉得他们之间的差别就在于能看到多少这个高塔中间的分层。厉害的高手都很善于切换自己思考的高度,一下能跟你讨论高阶的系统架构设计,一下又能深入到最底下的组合语言和二进位除错。他们脑中除了有这高塔每一层的详尽平面图,甚至也非常了解不同楼层之间的交互关系。而平凡的程式设计师大多只能专注于自己所开发的范围,对于其上的架构或其下的细节都不一定能理清头绪,万一出现bug也会搞不清楚到底是哪一层出了错,而被完全无关的细节绊住手脚。

程式语言决定了思考的高度

大部分资讯系学生接触的第一个语言是C语言,其实我觉得到了21世纪还从C语言开始教是非常值得商议的一件事。我在台大时曾当过两次计算机概论的助教,虽然大一学生同时还在修计算机程式设计(也就是教C语言的课),但我在课上也同时教他们学Python。

有人问我:「只学C语言不够吗?」。如果是为了毕业后能找工作,其实学C就够了,因为几乎所有公司都只考基本的C语言能力,也就是说他们认定只要会写C就能胜任日后的工作。事实上大部分大学都不太教程式语言的,会教C也只是因为大一总得选一个语言教,而C还是老得辣,加上大部分教授也只会这个,所以自然就决定是它了。近年来因为物件导向风行,所以大部分学校还会教个Java或C++,但这也是因为要教物件导向的概念,而不是以教这个语言为目的。除了这两种外,大概就剩下组合语言了,而这也是因为要教电脑最核心的CPU运作方式,所以才会顺便教到的。

程式语言的地位在资讯系其实一直很卑微,大部分教授觉得这只是一个基本工具,就像螺丝起子和铁锤一样。但我一直觉得程式语言是很重要的工具,它不只是让人用不同语法和电脑沟通,而是让人能用完全不同的思考方式来解决问题。简单的说,我觉得程式语言就是决定思考高度的一个关键因素,而这也间接决定了写程式的能力。

举一个简单的例子,高阶的script语言几乎都内建map这个资料结构。(也就是一对一的对应表,给它一个key,就能很快的找到其对应的value。有的语言称为dictionary、hash、或associative array。)如果写习惯Python或Ruby的人,一定会很直觉的用map来储存任何对应关系,甚至用来表示会动态变更栏位的struct。但是,在C语言里没有这种东西,这让很多只会写C的人直觉的用阵列加上linear search来存放这种对应关系。如果资料结构学得好的人,会知道这样写效率很差,但很多时候因为没有方便的library,也懒得自己写一个高效率的map(不过是存一个电话簿,我难道要先写一个红黑树吗?),就妥协于没效率的储存方法。

这就是一个被程式语言限制住的典型例子。在高阶语言用map存东西实在太容易了,所以这会变成思考时的一个小单位,跟人沟通或是规划架构时都能随时拿来用。但相反地,在低阶语言里,要有效率又简单的储存这种对应关系实在很麻烦,所以人们在思考时会倾向选择容易的方法来做,而自然忽略掉了以map为基础的解决方法。

除了script language外,functional language也是另一个进化到神乎其技路上必备的技能。functional language是以function为基础来思考的程式语言,典型的代表是LISP、Scheme、Haskell。(这边所说的function是higher order function,可以以其他function为参数的function,和C语言里的function是不同的概念。)在functional的世界最棒的特性是程式可以只靠function间的相互组合而生成,不用回圈不用if一样可以达成同样的目的。

举例来说,如果我要要从一个电话簿中挑出所有姓张的人,并传回他们的电话,用低阶语言(其实我指的是imperative language,但这里就不要这么讲究了)写起来大概是这样:

PhoneData contacts[N] = {.....};
String number[MAX_NUMBERS];
int count = 0;  
for(int i = 0; i < N; i++){if( !strncmp( contacts[i].name, "张", 1 ) ) // well, 让我们假设这个strncmp支援unicoderet[count++] = contacts[i].number;
}
return ret;

用低阶语言写程式必须不断处理琐碎的细节,像是要开多大的阵列、要弄一个额外的counting变数、要用回圈一个个检查阵列....。当脑袋里充满这些细节时,是很难切换到更高的角度思考的。而functional language提供完全不同的思考方式来解决同样的问题,以下我用Ruby的语法写同样的程式(Ruby具备许多functional language的特性,但不全然是个functional language):

contacts = [ { 'name' => '...', 'number' => '...' }, ... ]
return contacts.find_all{ |c| c['name'][0,1] == '张' }.map{ |c| c['number']}

是的,你没看错,就只有两行,而且真正做事的只有一行而已。这里用到的是functional language的基本工具:filter(Ruby里叫find_all)和map。这两个function特别的地方在于他们能用来取代一般需要回圈才能做的事,并赋予除了「回圈」以外更高阶的抽象意义。filter的意思是过滤,可以从一个阵列中用一个给定的function为条件来去除不合条件的元素;而map的意义是对应和转换,可以用一个给定的function作为规则把一个阵列中的每个元素全转换成另一个样子。

多了这一层抽象化后,写程式的思考方式会变得完全不同。回圈不再只是回圈,而是可以根据它的目的将之区分为map或filter(其实还有更多,这边只是先举两个做例子),思考时便能以组合这些小元件的方式来构思程式的写法。这里提供的不只是语法上的简便而已,而是整个思维的大跃进,以及思考高度的提升。

这就是为什么我要教大一新生Python。Python融合imperative language、object-oriented language、以及functional language,语法简单清楚威力又强大。虽然他们学过后不见得会继续用Python,但有了不同语言的概念后,思考的高度会完全不同,写出来的程式品质自然也不同。

(待续)

更多推荐

追求神乎其技的程式设计之道(七)

本文发布于:2024-02-28 03:40:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1768208.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:神乎其技   之道   程式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!