同学们好,我叫梁峻墅。今天想和大家分享的话题是:编程的技术|艺术|术术。这里的“术术”你可以理解为哲学。
面向开发者编程,与大家平常经常说的面向过程编程,面向对象编程等不太一样。我理解我们程序员编程面向的对象是人,是程序员,是开发者。用户并不看代码,看代码的都是我们的同行,所以我们要多一个面向开发者的思维角度来看待编程。
骨灰级程序员
我从15岁开始编程,现在已经整整编了35年了,算是骨灰级的程序员了。我小时候第一个编的程序是游戏,我相信很多程序员最开始编程都是从兴趣爱好开始的。我当时就是觉得别的游戏不好玩,自己编更好玩的。那个时候是80年代,最牛逼的电脑也就是苹果的Apple II,64K内存。而我们用的都是娃娃机,只有几K内存。所以那个时候编程序,都不是逐字节,而是逐位逐位地抠内存,考虑着怎么省,宁可用复杂且不易理解还容易出错的位运算,也要用1个字节的8位分别表示8个布尔型变量。到了现在,在设计数据库的表状态字段时,还习惯性地使用位表达,而不是连续自然数。那个时候的存储连软盘都没有,更别说什么硬盘闪存了,用磁带都是高级货。但家里录音机的磁带质量又不够好,经常存上去捞不回来。最后为了玩游戏,开机后都要自己把游戏代码再敲一遍,才能玩。这个开发环境真是惨绝人寰!但正是在这种艰苦的环境下,反而锤炼出在技术上精益求精的精神。一方面,为了能早点儿玩上游戏,不断地优化代码,愣是把200行BASIC代码优化到80行。另一方面,打字的速度也快速提升,没学过指法,但上大学时学五笔字型,我一个指头戳都比别人快。所以环境不好,不一定是坏事。现在的编程软硬件环境比以前好太多了,但很多程序都编得更加随心所欲了,内存分配都是大手笔,企图靠硬件来掩饰软件的问题。所以大家要珍惜自己当下编程环境,少抱怨,多用困难锤炼自己编程的能力。
1990年,我上了大学,终于能接触到真正的计算机了,图书馆里有几十本关于计算机编程的书籍被我常年霸占。那个年代电子游戏厅如日中天,里面有很多赌博游戏。正好有个同学的亲戚是开游戏厅的,我们趁他值夜班拆开游戏机,把里面的EPROM拿回学校用单片机仿真系统复制,但一看游戏机主板上的CPU,大家都傻眼了,是6502,APPLE II的CPU,这种高级货学生机房是没有的。幸好我们学校也是当时中国的13所重点大学之一,有多个国家重点实验室,我们在里面找到一台原子分光光度计,它的控制主机是台APPLE II,冒着被开除的风险,拆开主机,换上复制出来的EPROM,用APPLE II反汇编机器码,并打印了500多页的汇编程序,我们在针式打印机的怒吼中提心吊胆的过了一宿。最后愣是靠目视代码,从两万多行代码中找到了只有8行代码的变牌算法,然后横扫那个城市所有的游戏厅,后来游戏厅老板见了学生摸样的人都不让进。有些执着的同学干脆学也不上了,坐着绿皮火车逢站必下,扫荡了周边一个又一个小县城……但我们那时候还不知道有黑客这个词,认为破解系统是天经地义的,就像编程技术精益求精是理所当然的一样。
大学毕业后正赶上中国IT方兴未艾的时代,我搞的是单片机控制系统,还有MIS系统,就是信息管理系统,现在叫ERP,编程的范围越来越广泛,使用的编程语言和开发环境越来越多。没过几年,就到了上世纪末,中国迎来了互联网时代。1997年,我作为古城热线的第一批互联网用户,用19.8k的猫拨号连接到互联网上,那是激动万分,终于可以了解世界上其他程序员是怎么编程序的。同时,也了解到编程的顶级精英被称为Hacker,但中文被翻译为黑客,带点不正经的味道,后来在不理解编程技术的媒体推动下,这个词已经成了不折不扣的贬义词。到了本世纪初,电信数据增值业务,简称SP突飞猛进,像打开的潘多拉魔盒,放出无数洪水猛兽,大量技术人员天天琢磨着怎么让你回条短信就扣掉2块钱,再顺手给你订个15元包月业务,就是无差别抢劫。那个年代是技术人员的高光时刻,充分体现了那个时代的中国式标语——科技是第一生产力。黑客这个称谓已经不足以平民愤,直接叫白领黑社会。行业监管到位后,大家终于可以心平气和地干点正经事了。照抄美国,开始进入到虚拟化、云计算的业务领域,然后就是搞机器人和人工智能。现在的技术理念和手段越来越多,信息量越来越大,人们越来越急功近利,软件不行就用硬件堆,仅仅是为了完成交付,能懵就懵,能骗就骗,世风日下,很多顶级程序员的光辉思想都被淹没在星辰大海中。
现在的编程越来越没啥挑战,几乎所有的积木都基本造好了,绝大多数程序员都是在大量堆砌积木,稀里糊涂地就把功能完成了,如果没完成那就换块积木,没人仔细研究为什么。远没有小时候那种控制机器,挖掘机器潜能的乐趣。但不可否认,编程门槛的下降也繁荣了整个软件行业的生态,而开源的出现,能够促进代码从市井般的粗俗进化到贵族般的优雅。所以,现在的我在做一些开源的相关工作。
程序员文化和武侠文化
我理解程序员文化与中国的武侠文化有很多相似的地方。武侠经常提到在密林峡谷中练功修行,内力练到位后,一出江湖,就是血雨腥风。很多程序员年轻的时候也一样,研究代码经常废寝忘食,吃住在公司,回家就是为了洗个澡。每天晚上干到2、3点,经常把爱因斯坦的话挂在嘴边:“成年人睡4个小时就够了。”这些其实也是在修炼武功。我大学刚毕业的时候,Windows才3.0吧。那个时候没有互联网,MSDN也还没有,到哪里去找编程资料呢?所以大家手里都有一个API的手抄本,很多API的调用都是自己试出来的。很多参数也不知道是啥意思,就用穷举法一个一个地试,去探索,去发现。所以大家每次见面都会炫耀一下,这个函数你会调吗?一个小本,很牛逼的样子,就像武功秘籍一样。
再往后,微软出了MSDN,每期至少2张光盘起。被中关村的不法商贩看中了,就用MSDN的封面给日本动作片光盘套壳来躲避稽查。大家买到这样的MSDN,都会体谅不法商贩的良苦用心,默默地收藏起来,然后怀着忐忑的心情继续去淘MSDN,即希望买到真的MSDN,又希望不是。但不管买到啥,都有收获,所以程序员很早就有了平和的佛系心态。那个时候的MSDN,就是程序员的《葵花宝典》:一书在手,天下我有。想查什么随便查,想调用什么就去搜,内容详尽,还可以通过超链接无限拓展你的视野。那个时候已经不是会不会调用API的问题了,而是能知道调用哪些API能让你的程序更加精简、稳定。尽管大家常说,不要重复造轮子,但我想说这个比喻真是丧尽天良!程序员面对的绝不是使用几个轮子的造车游戏,而是使用成千上万个积木的拼图游戏,已经远远超出了正常人类的脑容量。由于API实在太多了,而且还在快速迭代,任何人都很难笃定哪些功能已有现成的API,哪些功能还没有。所以大家开始比拼的是知识面有多广,再后来就变成了玄学,根据常年跟微软程序员了解的调性,设身处地地猜他会怎么思考这个问题,我们怎么做才能成本最低。
随着API越来越多,软件规模也象滚雪球般越来越大,像求伯君老前辈那样凭一己之力写个字处理软件的时代一去不复返了。尤其是系统级的大型软件,需要很多人联合开发,就不可避免要去修改别人的代码。这个时候武侠的情节又出来了,同级别的程序员基本上都看不上对方的代码。你看看东邪西毒南帝北丐,谁鸟过谁?别人代码拿过来只是用旁光看一眼,然后就是“重构”。其实,对于中级程序员而言,写代码并没什么难度,想清楚编程思路之后就是体力活,所以这不算什么本事。但修改别人的代码,可要比自己写要难的多得多。首先别人的代码就像个黑盒子,你得一点一点地通过阅读代码,让大脑像计算机一样运行一遍别人的程序,还要抽象出来别人的设计思想;然后再把自己的思想和别人的思想进行巧妙整合,和平共处;最后还要对代码进行一次精准的外科手术,才能实现自己的目标。这绝对是个脏活、累活,但在外行人眼里,觉得你不就改了几行代码吗?很多程序员在按代码行计算工作量的世俗傲慢与偏见下,选择了用愚蠢对付愚蠢。而那些有思想的牛逼程序员不为所动,不断通过修改别人的代码,提高自己认知的边界,逐渐成长为一代宗师。而总是自己写代码的程序员,则永远在自己认知的范围内低水平徘徊。程序员的三六九等就是这样被拉开的。
等到了软件开源的时代,开源代码就更需要看其他人写的代码了,我理解这是编程技术追求更高更远的必然结果。在开源时代,参与代码共建的程序员之间必然产生共情,了解对方是怎么想的,理解人家的思路。但对于大多数人而言,理解他人是很难的,每个人都觉得自己是最正确的,这是人性的弱点。而开源能够让程序员的心胸和视野更加的宽广,把理解他人作为一种编程习惯,这种境界就不一样了。当然,开源代码看多了,可能武侠精神又会出来了,这怎么写的这么烂,还不如自己的代码开源呢。这个呢,就有点反武侠了。中国武侠,武林秘籍,都是自己门派的独门秘技,绝不外泄,不能让别人看。而开源代码,相当于把武林秘籍公开了。但我理解,看到源代码,到真正理解源代码后面的思想,还有好长一段距离。而且还要看你的段位,就像九阴白骨爪第一式,气沉丹田,你得先知道丹田是啥,在哪儿。还有欧阳锋练蛤蟆功走火入魔的呢,显然没理解对代码和思想的差异。所以开源代码并不一定能让所有获得的人真正获得,而真正获得的人就是你的同道中人,你就不那么寂寞了。开源时代之前,很多老板以为掌握了源代码,就是掌握了核心技术。而真正的核心技术其实是思想,而思想从来都是由人来掌握的。李白曾经写过一首《江湖行》,我就结合开源,共建一首《开源行》:
编程的思想境界
说了这么多,主要是为了给PUA做好铺垫。现在进入正题:编程的终极奥义到底是什么?我理解只有思想恒久远,代码才能永流传。因为编程就是把人类的语言给转换成计算机能执行的机器语言,本质就是一种翻译工作,但翻译的水平也是有高低贵贱之分。像电影《Sucker Punch》是一部非常有创意的内涵思想片,还能融合梦幻、魔幻、科幻、暗黑、伦理、动作、微色情、小萝莉、暴力美学、解谜等多种元素,还能做到雅俗共赏,不同层次的人都能从这部影片中获得不同的乐趣。我还专门给这部电影做了一个暴力美学特辑(Sucker Punch——美少女特攻队(暴力美学特辑)_哔哩哔哩_bilibili),有兴趣的同学可以去看看。但这部电影在华语区的票房惨淡,就是由于译名问题,该片的价值被严重低估。台湾翻译为《杀客同萌》,基本做到了意音具备,就是神还差点。但看看大陆翻译为《美少女特攻队》是几个意思,让人以为是二次元动画片。再看看香港的翻译《专扁衰仔》,你就知道没文化有多可怕,扎克·施奈德估计直接哭晕在厕所里。翻译的思想高度不同,对作品的理解深度不同,翻译的质量是天壤之别。而对于像编程如此缜密的翻译工作,那更是需要蕴含深刻的思想才能做得更好。
既然谈到思想,就要谈到思想的境界。我理解编程的境界有四层,借用孙子兵法,分别是:下兵伐城、中兵伐谋、上兵伐心和不战而屈人之兵为超然。
第一层——下兵伐城:很多程序员,一接到编程需求,就立刻启动开发环境,开始编程敲代码了。这就是没什么想法,先干起来再说,编到哪儿算哪儿。面向交付编程,只为完成功能,头痛医头,脚痛医脚。一路攻城略地,好不威风,但这只能算初级水平。
第二层——中兵伐谋:拿到需求之后,不着急动手,先开始思考,开始谋划,应该走什么技术路线,结合哪些已经做过的代码,还应使用哪些技术手段来快速、轻松地完成这个需求。这个层面的程序员已经开始不靠纯技术硬扛需求,而是开始艺术性地解决问题。大家拼的不是能不能解决问题,而是看谁解决问题的成本最低。像中医那样,并不直接治病,而是阴阳调和,打通经脉,调动自身免疫系统,四两拨千斤,这已经开始有中国式智慧的味道了。这种人经常在计算机旁边呆坐半天,即使表面上在和你说话,但其实脑子里在伐谋呢,所以经常表达古怪,被认为是书呆子。
第三层——上兵伐心:这种人已经能看到文人的清风傲骨,在更高的战略层面思考解决问题的时空成本,包括但不限于时间成本、分析成本、设计成本、编码成本、调试成本、部署成本、维护成本、用户的使用成本、资源的调配成本、社会的综合人文成本等等,得到结果后会产生一个灵魂拷问:“为什么要解决这个问题?能不能不解决?”带有原罪的需求都挺不过这个终极审判。比如很多需求,只是貌似合理,但实际上是伪需求,顶尖的高手能够抽丝剥茧,发现需求的逻辑矛盾和漏洞,并能综合运用各种手段,甚至包括非技术手段来及时纠偏。比如做MIS系统的时候,客户方的办公自动化系统需求很简单,就是把现有的管理规章制度全部用计算机程序实现一遍。这个需求貌似天真无邪,但实际上它忽视了人机之间的差异和特点。比如对人工作业,为达到作业合规的要求,管理规章制度中就要有反作弊措施,各个相关部门还都要有作业数据备份,以便将来发现问题倒查时可以对口供。但对IT系统,用户都有登录ID,作业都有事务ID,交互都有会话ID,存储都是一体化的,根本不需要那些画蛇添足的步骤。顶级的程序员就会庖丁解牛般地优化管理流程,引导需求合理化,节省了大量的研发资源、应用资源和社会资源。可能只需要修改管理规章制度的几十个字,就能少写几万行代码,bug能少几百个,部署维护能少几个月,用户每天能少点击数千次鼠标。通过少编程,甚至不编程就能解决问题,才是最牛逼的境界。
终于来到最最牛逼的境界——不战而屈人之兵。前面三层境界,也就是在满足需求、预测需求、引领需求上做文章,毕竟都是咱们这个世界可以理解的事。而最高境界已经跳出三界之外,不在五行之中,已经无法理解了。
看个场景先:小白最近代码输出太少,说机器频繁死机,耽误了工作。大牛对着机器,上去就是一脚,从此再不死机了…天理何在?小白不服啊,碰上死机的机器也来一脚,结果当天就去财务领工资了…天理难容!虽然都是人,但差别就这么大,找谁说理去。
再看段对话:
小白:“哥,我做的那个模块总是有bug,调试两三天了,一直找不到原因,您有空帮我看看呗。”
大牛:“go”
来到现场。
小白:“您看这…”
大牛:“别急,从头开始把错误给我演示一遍。”
小白:“好嘞!”
一个小时过去了…
小白:“我call,怎么不出来了呢?大哥,我发誓我找你之前还复现过一次错误。”
大牛:“没事,我已经习惯了,等再出错,保留现场,call我。”