1998年在大学课堂上学习的微机原理和汇编语言,是我最早接触到的计算机语言,由于缺乏上机实践,书本上的那些指令,除了枯燥、晦涩之外,我至今想不出更好的形容词。如果不考虑单片机(或微芯片)的研发领域,那时几乎所有程序员都在转向使用高级语言编程,这是无可置疑的事实。短短1年后,我就有了“C语言”“Fortran语言”课程的学习经历,以及宝贵的Windows 95桌面操作系统的上机实践机会。当时作为电子工程专业的学生,我是真没有想到未来会与计算机软件开发打半辈子交道。
因为只有这些肤浅的了解,除了感受到“靠课堂和书本效率太低,必须要摸键盘”之外,那时对计算机语言可能没留下多少有意义的思考或者总结。相比之下,在心中留下的问题还是不少,例如,C语言比Fortran语言流行、好用,用C语言就能完成所有Fortran语言能做的事情,那么Fortran语言还有什么存在的必要?再例如,有没有关于语言类型的定义?这两种语言是什么类型?除了这种类型还有其他类型么?另外,语言之间除了语法之外,本质的差别到底是什么?
仔细回想一下,这些问题背后体现的思维和思考力,还是有几点是值得称道的。问题虽然已经不再重要,但是作为宝贵的精神财富,至今回味无穷。2002年开始接触Java语言时,这些问题在心中应该已有答案:C语言、Fortran语言都属于面向过程语言,不同语言特征不同,虽然C语言最为主流,但是Fortran在数学计算上很好用,使用Fortran的人如果养成了使用这种语言的习惯,只要够用,没有必要放弃它而改学C语言。
相比于C语言,Java语言更加抽象。对于语言来说,越抽象就会越接近人类的思维,最具抽象性的语言类型,就是面向对象语言。Java语言核心优势有二:其一,完整演绎面向对象的“继承、封装、多态”三大特征;其二,进一步屏蔽操作系统和硬件,降低开发人员门槛,并借跨平台之势走遍天下。
应该使用哪种语言,是软件开发人员之间喋喋不休的话题,作为真正的宿主语言霸主,C语言在资源占用、进程运行等性能方面占据压倒性的优势,而且不能被反编译。偏爱性能或是具有黑客精神的人员一定站在这一阵营,他们迷恋C语言的指针,陶醉于通过钩子函数实现回调功能。在硅谷编程语言开发者的眼中,有些人认为编程语言应该防止程序员干蠢事,Java当然是这个阵营的代表;而另外一些人的观点恰恰相反,他们赞成让编程语言做一些可以做的事情,当时,这说的正是C语言。
2003年读研时,室友在外接到一个项目:给货运公司做一套货车监控管理系统,货车上安装的GPS终端会发送自己的位置信号,监控系统上将接收到的货车位置及行驶信息以图形化方式,绘制在包含全国所有省、自治区、直辖市道路信息的ActiveX地图控件上,这套系统要运行在Windows操作系统上。有趣的是,接到这个项目后我的第一反应是,计算机有时候干的是坏事,有了这个系统,大货车司机再也没法偷懒了。现在来看,这个问题还是值得思考的,人类发明了计算机,它一方面提升了生产力为人类造福,另一方面确实让很多工作越来越卷、竞争压力越来越大。对此话题,8.1节会给出笔者的一些观点。
在继续谈论这个项目之前,笔者要插一段感想。这是一个GUI客户端,以图形化操作为主,而非以Console控制台(或是命令行)方式交互的系统。当时我能感到的明显变化是“单击鼠标对敲击键盘的逐步替代”,图形界面系统会成为未来的主角。但未曾预料到的是,图形化系统的载体悄然发生了巨变,若干年后,GUI所依赖的(需独立安装的)客户端,在零售市场上节节败退,取而代之的主角是通用浏览器。个人终端轻量化、图形界面跨平台才是大势所趋,对行业发展产生了深远的影响力。在求学时期,我很热衷于对此类话题做些前瞻性判断,现在回想起来,并非我当时目光短浅,能看透技术发展、预测未来趋势实则太难。
这是我接触的第一个真正意义上的软件项目,室友和我立即开展了语言选型的技术决策,毫无意外的是,我们从未考虑过使用Java语言。对于真正要挣钱,并且追求完美代码的我们来说,C语言的纯粹性明显更具吸引力。相比之下,Java语言只是弱者的游戏。从低效的编译到蹩脚的Applet客户端,Java语言简直一无是处。
这样的问题在任何与技术沾边的领域可能都存在,例如汽车和手表领域。老车迷喜欢汽油车,懂表的人士酷爱机械表,新生一代则早已认同电动车的易维护优势和电子手表那花花绿绿的功能。老司机
与新生代之间总是缺乏相互认同感,很少握手言和。
语言选型的故事当然还没有完结。如果使用C/C++语言,那么室友首选的开发平台必然是MFC,但是对这个选择,我明显底气不足。玩转MFC对我而言并没有那么难,倒是那本Windows API的书真是让人敬而远之,书中有上千个生僻、拗口的Windows操作系统函数,函数参数的复杂程度更是令我“不寒而栗”。我的水平如此,在真实的项目面前,这样的差距无法弥补,我只能认怂,退而求其次。
没有什么能难得倒那时的热血青年,我提出了一个折中的选择,使用C#语言和.NET开发平台。为了说服室友,我将两种语言在性能、上手难度、后期维护等若干评价项方面做了一个二维比较表画在黑板上,结果C#语言几乎在上述方面都介于C/C++与Java之间。在以后的工作中,每次想到决策矩阵,我立即就会想起这张表。
但是,几年之后,像“卡通玩具”一样的Java语言明显成为主流,位列全球第一大语言,编程极客和老一代程序员们虽然心有不甘,但是只是接受事实,因为新生代才是未来的真正主人。任何认为C语言优于Java语言的论点,都敌不过两点:第一,C语言执行效率高,但Java更容易上手,程序员的时间成本远比计算机的时间成本高得多;第二,Java的取胜之匙是借硬件高速发展之东风,JVM在性能方面的劣势,逐渐不再被视为一个巨大短板。如果摩尔定律不成立,或者只是不完全成立,那么多数人的计算机硬盘可能还只有8GB
,C语言与Java语言的命运必会完全反转。Java的发展得益于硬件世界的发展,不仅如此,软件架构的发展、人工智能的发展,都是如此。
室友与我沟通选择什么语言和开发平台,这是我人生第一次正经八百地面对一项技术决策。在此项目之后,我自己也随波逐流、转换阵营,选择Java语言作为开发方向。
反观C#,当时的选择现在看起来有些令人唏嘘。运行C#程序,需要.NET开发平台,这与运行Java程序需要使用JVM虚拟机是一样的道理,牺牲了一定的纯粹性和运行效率,但又没能换来跨平台的便利。现在C#的市场份额之低,足以说明远未(如微软公司所设想)得到市场的认可,看来折中之道并非永远是正确的。
除了语言选型的深刻印记,这个项目还带给我另外一个震撼:算法是个狠角色。在地图对应的道路上,实时显示货车的移动,在主频1.6GHz的Windows操作系统中,货车图标像是在道路图上一格一格地跳跃,而不是连续平滑地移动。在计算机配置不变的情况下,卡顿问题对GUI体验度的问题该如何解决?当然是利用算法,室友熬夜2周,几乎废寝忘食。每日白天写功能代码,下半夜在台灯下看超级厚的影印版《算法导论》,选定算法,将“所有车不断变化的GPS坐标数据转换为图形上轨迹显示”的处理程序,使用算法进行优化。这个提升被证明是惊人的,毫秒级别的位置更新速度即使在最低比例的放大图上,也无卡顿感。通过算法,这个模块程序处理效率提升大概500倍。这样的经历,让我们从心底真正理解“数据、算法、算力三分天下”的思想。能在人工智能三要素中占据一席之地,可见算法的影响力之大。
回忆一下当时所学课程的两个层次,第一个层次是程序语言和数据库类,这当然是基础的,也是必备的;第二个层次的代表是密码学和算法,这需要更多的自我挑战,不论是区块链共识算法、隐私计算同态加密,还是机器学习中的各类复杂模型,都需要在数学、线性代数、统计学方面有更高的造诣。在那时,算法绝非一个工种,只是少数精英才能涉足的高端领域,这与现在的情况形成了鲜明的对比,当今很多软件公司都拥有一支数量庞大的算法大军。近20年来工作分工方面的变迁,足以证明软件开发不断向(以AI为主的)高端领域推进的趋势。
正是鉴于这段经历,在后续工作中我十分关注性能优化领域,在银行的日终批处理程序计算个人贷款程序中,算法的优化将计算速度提升了上百倍。不论是否使用算法,实际工作中的大部分软件应用都存在巨大的可优化空间。这样的认知,形成一定的辐射效应,例如,面对昂贵的数据库存储资源,充分利用数据库的数据压缩功能,通常可节省出大量的存储空间。
每次使用打车软件,看到汽车在地图上缓缓移动,我就会想起2003年的那个项目。对于那些说网约车平台的技术很简单的人,我觉得他们是井底之蛙,这可是算法密集型系统。
编程最像什么?在本质上与程序员最接近的是个人艺术家,例如画家,个人创造性对于编程语言的发明十分重要,伟大语言的发明团队多是一两个人,这与绘画很相似。客观来说,编程无疑是个硬技术。但是,如若从心灵拷问的角度来看,源于其内在的创造力,以及对审美追求,编程高手更像是艺术家。优秀的编程者对软件之美都有近乎狂热的追求。
架构最像什么?与架构师最接近的应该是设计师,最典型的,可以将软件系统设计类比建筑设计,设计也需要个人创造性,但是必须遵从主流的标准,使用主流的技术,符合大众的审美并接受苛刻的检测。绘画应该是私活,而建筑设计更像是公事。这是那个时代的我对软件领域的理解,这个理解一直伴随着我,至今未变。
多数领域的伟大作品诞生于很早之前,例如15世纪的绘画杰作,至今仍无法被超越。当然了,还有莎士比亚时代的戏剧,将戏剧这种艺术提升到了难以企及的水平,令后世剧作家只能望其项背。不仅绘画、戏剧,几乎每个领域都有自己的文艺复兴时代,在这个领域刚诞生的时候,人们热情高涨,短短几十年就会挖掘到这个领域的精华,很多人将毕生的大部分精力聚焦于此,将高水平的智力、强大的能量付诸于此。可以有点武断地说,本章所述的这个时期,正是我国软件编程语言与编程技术的文艺复兴时代。
与编程相比,架构的发展有何特征呢?架构的高速发展期比编程要晚10年左右。前面所述四个时期中的第二个时期,才进入架构发展的黄金期。另外,架构的演进更源于整个行业的推动,是趋势作用下的结果,而非个人创造。架构的个人标签,远没有编程那么强。架构本身是一门杂学,时而关注具体的开发技术,时而体现为设计模式与风格,时而像是在做布道
工作。从学科上讲,架构的内容重心应该在质量属性,但是架构完全可以摇身一变,体现为抽象的思想。还有很多从业者,只是将架构感性地理解为架构图,这也没有错,工作中,一旦说要做某个系统的架构,交付物正是架构图。
我们
掌握了哪些高级语言?我们自己发明过哪些语言?
那个时代的我,对于VB、Pascal有一点接触,但是真正学习的只有C/C++、Java。国内的程序员们,技能同质化问题严重,大家多是在浪潮里面匆匆赶路。在当时,我们并没有创造性地发明真正属于我们自己的语言。当时的一次硅谷的游学经历,让我见识了与软件发达国家之间的巨大差距,回国后,我将游学心得做了一些整理,20多年后的今天,我拿出来并整理分享给读者。这样做的原因在于,这些内容依然有效。
我们怎样看待编程语言?好的语言应该是怎样的?下面内容能够回答这两个问题。
Alan M.Davis于1995年编写了 201 Principles of Software Development 一书,2021年出版了翻译版《软件开发的201个原则》,作者在自序中写道,“26年后的今天,当我审视这201条原则时,我很高兴地宣告,几乎所有原则都经受住了时间的考验,就像物理学的基本原理一样”。时隔20多年,我们惊奇地发现,软件架构与开发技术发生了革命性的提升,软件产业的规模和迭代速度不可同日而语,但是核心的原则和方法并未发生根本性的改变。C语言、Java语言的核心特性,同样经受住了岁月的洗礼,经久不衰,主流的设计模式也具有同理规律。技术可以过时,思想是不朽的。
软件开发包括需求分析、程序编写、软件测试等环节,这些原则没有变化,意味着软件工程的主要内容一直稳定。虽然比软件工程的活跃性更高,但是编程语言的实际进化速度也是缓慢的,这的确是不争的事实。按照这个速度,当代的编程语言高手可以预测30~50年后的语言,或许这并非是虚无缥缈的狂想。
游学期间,我有幸向这个领域的专家请教过这个问题,他的观点可谓高屋建瓴,核心意思大抵如此:编程语言本质上是一种表达方法,这种表达方法的核心载体是字母和数学符号,而字符和数学符号的进化是极其缓慢的,键盘的按键是固定的,英语的词汇也是基本固定的,因此编程语言的演变也是缓慢的。
这是令人折服的答案。如果现在问我如何改变编程语言进化缓慢的局面,我倒是有了新的答案:用中文编程。但这个问题没有意义,因为这个局面并不需要改变。如果一定要改变,那最好的方式已经不是发明一种中文表达方式的编程语言了,而是让大模型这样的智能体去给我们做转换,让其作为中文和英文之间的桥梁。
再来谈谈什么是好的语言。在当时,国外编程语言发明专家心中的答案是:内核最精简、最干净、最纯粹的语言。1.1.1节其实已经提到了这样的观点,当时我和室友根本没有考虑使用Java语言开发项目,原因基本在此。好的语言必须是简洁、抽象的,编程者不应当考虑怎样用更少的语法单位。Java语言的抽象程度毋庸置疑,但却使用像英语一样又长又啰唆的语法,好处是容易理解,但与简洁背道而驰。因此,在业务逻辑中尚可接受,但在算法领域,语法更加简洁的Python明显更胜一筹。好的语言不应该有一大堆的声明,这一点上,Java语言又得被我吐槽。即使要计算1+1,也要声明整个Class类和main函数。
关于这些方面的认知,与国外先进理念相比,我们不占下风。但是令人啼笑皆非的是,大家都预测错了结果。笨拙语言依靠算力走上了舞台的中央,这在当时,对于很多编程语言专家来说是不敢想象的结果。正因为他们是专家,所以才会错,因为太过于留恋编程语言自身特征了,而忽略了社会性以及其他方面的因素。
Java语言不仅糟蹋算力,而且语法像英语单词一样冗长(甚至可以把驼峰式写法也纳入被批判范畴),还需要一大堆的声明。那它如何能够流行,成为第一大编程语言?是因为面向对象、跨平台,还是因为设计模式?这些答案都对。但是我更愿意从另外一个视角看问题。
语言必须有根基和土壤,更具体地说是系统环境,语言流行与否,决定胜负之手正是系统环境。Cobol来自早期IBM的大型机,UNIX系统是C语言的宿主系统,Tcl是Tk的脚本语言,VB是Windows系统的脚本语言,PHP是网络服务器的脚本语言,Java和JavaScript则分别是Web语言和浏览器脚本语言。在那个时代,什么类型的应用系统的市场最繁荣(或者说发展最快)?无疑是Web应用及浏览器,其成为全球最通用、最轻量级的客户端。那么Java和JavaScript得以流行的原因也就显而易见了。
另外补充说明一下,评价编程语言并不简单,需要关注语言的各方面重要特征,例如在安全性方面:一切对象由虚拟机托管,Java语言等于给程序员“戴上了手铐”;而以指针为核心的C语言,则让程序员有更多自由发挥的空间。因此,没有哪个黑客会选择Java语言。开发高手常说,C语言的设计目标是自己,而Java则是设计者为了给别人使用而设计的,它们的目标用户大相径庭。开发高手对C语言和Java语言的感知,好像基本到此为止,更能吸引他们的(或者说更令他们感受到威胁的)编程语言,可能是Perl、Python,或是其他轻量级脚本语言。
这次游学,我在硅谷目睹了编程语言的“百家争鸣、百花齐放”,不仅Cobol、Basic、C/C++、Pascal、Ruby、Smalltalk、PHP、Perl、Python已经大有名气,而且1970年以前开发出来的Fortran、Lisp语言仍然活跃。更令人惊讶的是,程序员在咖啡馆闲聊时所探讨的语言远不止这些。他们评价一门喜欢的语言,会提到使用这门语言编程时很少用到Shift键。他们当时已经明确指出,未来几十年,编程语言的进步与函数库的发展息息相关,建设函数库才是语言再发展的真正空间。从与他们的谈话中,我深刻认识到,好的程序语言,不能是来自委员会式的设计。与用高价打造一套篮球场上的豪华阵容不同,主流语言大部分源于自然成长式。
虽然说这是编程语言的文艺复兴时代,但是我清楚认识到自己只是兴盛之路上走马观花的游客。在语言的多样性、纯粹性、原创性、活跃性,以及思辨方面,国内多数从业者同我一样,只是充当分母角色的行业陪跑者。
现在回过头来看这些过往,当时感触用两个词形容最为贴切,一是望洋兴叹,二是时不我待。在这之后,我们这代人奋起直追,经过短短20年,现在已经在智能时代成为全球的重要参与者,甚至是很多细分领域的技术引领者。任何人的职业都只有一次,无论从事何种职业,这样的发展机遇都是可遇不可求的。不负韶华,在这样的大潮中乘风破浪,当然就是最完美的职业生涯。