作为计算机专业的学生,我觉得大家很少认真地问过自己,我们究竟要学会什么,学成什么样。笔者曾经跟国内某985高校的某位数学专业准研究生交流,他认为计算机学的只是编程啥的,这样和培训班没啥区别,他觉得大学应该学一点更加通用,更加抽象一些的知识——比如数学。当时我还没踏入大学校门,计算机对我来说也可能只是写点代码来解放自己的双手。当时的我虽然对他的说法不认同,但也想不出什么来反驳。但当我完成了四年本科学业之后,我觉得这是非常有必要思考的问题,接受了完整的科班教育的计算机专业的本科学生,到底和培训班的学生有什么区别。
形而上者谓之道,形而下者谓之器。
——《易经·系辞》
关于“形而上”和“形而下”有两种常见的解释。一种说“大道于无形,故曰形而上;器用之物当有形,是曰形而下。”,另一种则是说,形而上是自上而下,形而下则是自下而上。在学习一个学科的时候,只专注于“形而上”或者“形而下”其中一个,都是不可取的,两方面一定是互补地发展。有想法没法落地实现,和代码仅仅停留在“能跑”的层面(甚至可能不能跑),都不应该是一个计算机科班学生的状态。
在计算机领域内,形而下的东西最直接的便是编程能力。编程能力我觉得并不是说熟练使用多少语言,能够使用语言的多少特性(比如神奇的C++)。而是能不能将脑子中想的清晰表达为电脑能够理解的东西。编程并不是简单记忆特定编程语言的语法、关键词、编译命令等,而是一种表达,用严谨、准确、优雅,并且尽量好懂的语言将自己所想的,通过特定的语言,告知电脑。编程是一门手艺,一定是越写越熟的,我们不能指望通过阅读大量的书本知识来替代代码量,纸上谈兵并不可取。
我记得网安专业的学生,大一有一门课叫《程序设计基础》,上课内容是C语言开发。我不反对用C语言作为教学语言来引导毫无经验的学生学习程序设计,但是上课往往会变成C语言语法讲解。在花了几节课教完了最基础的顺序、分支和循环结构后,大量的时间花在了数组、结构体、指针函数、函数指针、指针的指针等一系列内容上。大家课下只记住了某一个新的语法点,比如i++ + ++i
到底该等于多少,比如用open打开文件后要检查文件指针是否为空。但几乎不会去想,文件指针为什么会是空的,如何避免它为空,以及我在涉及文件读写的程序上要怎么设计才能减少这类情况的发生。
另外,一些同学可能语法记忆的非常娴熟,甚至有时能在我忘了判断文件指针是否为空的情况下提醒我一把,但当需要完成一些作业或者考试(实际是实现一个简单的系统)时,他们可能无从下手。并不是不知道程序的语法,而是不知道从哪儿开始实现这些复杂的功能。这种,我们一般认为是“代码写少了”。多写代码无疑能够解决这样的问题,但如果我们把“多写代码”这个事儿抽象一样,这更像是一种分解任务,并正确表达给电脑的能力。
形而上者谓之道,这些形而上的东西,往往是作为宏观规律,或者设计准则而存在的,一部分是科学规律,数理逻辑,还有一部分是前人的研究经验总结。在这边,笔者认为包括了一些学校里教了或者没教的知识,具体为:基本的数学基础,数据结构,算法,计算机网络,计算机组成,操作系统,编译原理,软件工程,数据库,分布式系统等。比如操作系统能告诉你,系统是如何调度进程的,当你编写多进程/多线程的程序时要注意什么,什么情况下能够提升效率;比如软件工程会告诉你,什么样的架构设计是合理的,可以写出更好维护的代码,哪些Code Smell可能导致代码难以维护,应当避免。当你写代码能够考虑到这些内容时,才是真正学懂了这些知识。如果你能借此发现一些问题,发现行业内的痛点,并尝试解决时,你可能已经摸到了科研的大门。
那么如果我们回到最开始的问题,到底是什么把“计算机科班”的学生,和一个“编程培训班”的学生区分开呢?要我来回答这个问题,我可能会做个不恰当的类比。如果我只是学会了写代码,就像我学会了切菜剁肉;而经历了一个本科学习之后,我们希望能够看到一盘菜,从原材料开始把它做出来。这种独立思考、设计并且实现的能力,才是我们在本科四年里应该学到的东西。
一个好的厨子不能不会切菜,而只会切菜也当不了好厨子。——出自 笔者