Linus Torvalds谈代码品位:重写代码,排除特例

Linus接受了Ted演讲的采访:林纳斯•托瓦兹: Linux 操作系统之父, 采访中,主持人和他谈到代码品位的问题。展示了两段代码:

第一段,没有品位的代码:

code_no_teast

第二段,有品位的代码:

code_have_teast

这是从单向链表删除元素的函数,区别在于,第一段代码要判断“要删除的元素”是不是元素的头,而第二段并没没有做这个if判断。

原因是:如果要删除的是中间元素,那么只要把上一个元素的next指针指向下下一个元素就好了;如果要删除头元素的话,第一段代码所做的是,重新建一个头,指针指向下下个元素,然后把链表的头换成新的头;而第二段代码直接将原来的头的指针指向下下个元素了。

除了没有新开辟空间,第二段代码还好在:兼顾了所有情况,也就是不存在特殊情况的判断了。

Linus说:

这一个比较好。 它没有if语句。 这完全不影响—— 你不必了解这里为什么没有“if”语句, 你需要了解的是 有时候你可以换个角度看问题, 重写代码,排除特例, 完美覆盖所有情况。 这就是好的代码。 同时也很简单。 这是最基本的原则。 其实这都不重要—— 当然,细节非常重要。

对我来说,我愿意与之共事的人, 必须有好的品位,这就是如何…… 我举的这个例子很傻, 没什么意义,因为实在太短。 好的品位体现在更长的代码里。 好的品位体现在能看清全局 甚至有一种直觉, 知道怎么把事情做漂亮。

我在写代码时,喜欢写很多if。现在看来,这样不仅并没有提高安全性(自以为自己考虑了大多数情况),而且还变得更加繁琐。以后应该注意一下。


2018年1月2日更新:

在软件设计中,有一个原则叫做“最小惊讶原则”(Principle of Least Astonishment),可以参考这篇:http://lucumr.pocoo.org/2011/7/9/python-and-pola/ 和这篇 https://akaedu.github.io/book/ch03s03.html

 

django数据库migrate失败的解决方法

Django是一个MVC架构的web框架,其中,数据库就是“Module”。使用这种框架,我们不必写一条SQL语句,就可以完成对数据库的所有操作。在之前的Django版本中,我们像操作本地对象那样操作数据对象,在更改保存之后,执行python manage.py syncdb命令来同步数据库,在我使用的1.9.2版本中,需要依次执行一下步骤:

  1. python manage.py makemigrations (这个命令会根据你对数据库做出的更改生成操作数据库的python脚本)
  2. python manage.py migrate (这个命令会执行python脚本)

我遇到的问题是,执行makemigrations没有问题,但是执行migrate的时候有问题。于是我修改了modules.py中错误的代码,再次执行,却一直出问题。提示如下:

我删掉了makemigrations生成的代码,然后重新使用makemigrations生成脚本,还是出错。

原来,这是由于出错的时候,migrate命令已经执行了部分脚本,也就是说,to_user_id属性已经被操作过了,在数据库中,已经无需再操作了,所以执行migrate命令重新更新makemigrations的脚本会出错。

解决办法

重新生成makemigrations不行,执行migrate也只会全部执行。那么我们只好把数据库恢复到出错的那次执行前面的样子。

migrations

 

恢复方法:在project/app/migrations下有每次对数据操作所生成的脚本。找到出错那次脚本,打开脚本,可读性还是很高的,将所对应的数据库更改还原(当然得使用mysql语句了)。

然后删掉这次migration,重新make 然后执行。

实在不行,还有一个万不得已的办法。几乎所有的数据库错误都可以用这个方法解决:

将migrations文件夹下的文件除了__init__.py全部删掉,然后将数据库drop掉,重新建数据库。然后make,migrate,就可以使用一个新的数据库(但愿你永远用不到这个方法)。

 

在德国生活的感受

来德国一个月了,在这里生活的感触很多,让我觉得,我们国家在很多地方做的差太多了。总得来说,我觉得这是一个民主、友好、严谨的国家,但也只是目前的看法而已。我的历史老师说:当你在这里生活一段时间,回家之后,别人问你的印象,你说出来的只是对Reutlingen的印象,而不是德国。我大多数的时间都生活在Reutlingen,所以这篇博客可能有些狭隘。

25710667152_191b4fddad_k

德国的人民

这里的人非常友好。刚到这里,有点不习惯的是,在路上陌生人会主动跟你打招呼。拍照的时候,大家都会等你,没有一个人会从你的镜头前面走过去。超市的收银员也每次都会说Hallo。这里(Reutlingen)很多地方的十字路口没有红绿灯,但是会车的时候大家都特别谦让。路口有人,车总会等着人。一开始非常让人不习惯,你明明离路口比较远,他可以过去,但是却停下来等你。也许不习惯是个好事,万一习惯了车总是等人说不定回国会被撞死。我从没有听过有人按喇叭。

德国人的严谨是出了名的,我觉得名副其实。公交车站都会有时间表,而且几乎一点不差。在公交车上,大多数时间都很安静,很少有人说话。刚来的时候,去注册跑了几个办公室,一个比一个整洁。

25437927421_93de0e60b2_k

关于历史。德国挑起的一站和二战,而且有纳粹的黑历史。不过我觉得,他们有点矫正过了,谈起希特勒的时候,他们都很敏感。不认可希特勒对战后德国的贡献。一个朋友告诉我:“千万不要问一个德国人,‘你喜欢希特勒吗?’”。

德国的网络

这里的网速非常快,昨天更新Java的时候,64M只花了三四秒就更新完了。成人网站Pronhub,YouTube都可以毫无压力播放高清版本。当然,这和企业的配置也有关系。但是到国内的网速非常慢,我ssh到阿里云的服务器,特别难受,打个字甚至要1s才能看见。

很多人警告过我,千万不要在这里下载音乐和电影。德国对盗版的打击非常大,一首音乐可能面临700欧元左右的罚款。其实,德国人自己也对此耿耿于怀。有次在酒吧,他们(都因为下载音乐受到过罚款)吐槽这个说:你说你因为这个抓去坐牢,大家介绍自己。“我杀了人”,“我抢了钱”,你说“我下了首歌”,卧槽他们肯定吓死了——“这人敢下歌?”肯定让你当狱霸了。

关于监控。德国的网络自由在世界上好像排第四。我没有见过被屏蔽的网站。

德国的游戏

主机游戏的情况感觉和国内差不多,不过掌机不是很好。游戏商店老板说PSV nearly dead了。游戏品位上也偏好欧美类型,比如生化危机,dark souls之类的。LOL在这里也比较流行。总体来说,这里玩游戏的人(单机+网游)并没有国内的人多。

德国的游戏没有审查,有分级制度。但是有些游戏的敏感内容也是有删减的。比如在使命召唤6现代战争4大名鼎鼎的“不准说俄语”的关卡中,玩家是不允许射击平民的。我觉得也算是矫正过妄的一种表现吧。

norussian_feature


norussian2

德国的食物

非常难吃。这里有很多土耳其餐厅,有一种看起来像汉堡的东西比较流行。平时德国人花在做饭上面的时间非常少,他们竟然还震惊,中国人花很多时间来做饭,明明自己吃的东西和屎一样。如果你来过我们学校餐厅,你就知道上一句话不是在吐槽。在外面吃饭要付消费,而且菜单也不便宜。自己做要便宜很多。

WeChat_1458981872

垃圾分类

垃圾分为塑料、纸类、厨房垃圾、衣物、玻璃、其他垃圾。其中玻璃还分颜色。而且非常普及,我们村很小的地方,都是三个或四个垃圾桶。朋友告诉我,在日本和新西兰更厉害,茶包都要分是什么材料做的。分不好就罚款。

25831542695_80fe12c90c_z

这样很麻烦,因为你不可能在房间里放四个垃圾桶,但是好处也显而易见。这里有非常非常多的车,但是,下图是这里的天空。

25440156724_48774c8896_k

市中心的一条河。

25952393342_2dd8c842c8_k

政治

德国是有很多民族组成联邦制国家。我的感受是,自治意识很高。州有自己的旗帜,很多活动都会看见自己地方的标志。我们学校很多人穿着印有校旗的衣服,学生组织都会有印有标志的袋子、笔、本子。

这个月经历了州政府的选举,遇到过一次游行。

25805603936_d0fe3412ce_k

人们可以选出自己支持的党派。

还有一些习俗,比如吃饭之前德国人会说:祝你好胃口。打喷嚏了别人会说“Bless you”(好像欧美都这样)。很有意思。

Again,这可能只是Reutlingen。可能这就是旅行的意义吧,多去一些地方,才不让自己的看法局限在这样一个小村子里。言语就像风,很多事情只有自己见的才是真的。有人说,往北往西,那里的德国人不像这里这么友好;也有人说,那里的城市更大,人们更加开放。就像我来德国人之前,有人说德国人很排外,因为中国人抢走了他们的工作机会。但是很多人告诉我,德国人憎恨的是从土耳其和其他国家来的人,白白领社会福利,而不做出贡献。像中国来的程序员,他们是欢迎的。

25810684581_186cef36c4_k

 

盗版之危害

最近”引力波“这个名词流行起来之后,出了一个民科“诺贝尔哥”。现在几乎可以确定的是,郭英森做的不是真正的科学,而很可能只是知道哗众取宠的名词。很多年来,中国的社会一直很容被民科诱导,再加上无良媒体总想搞大新闻,夸大事实煽风点火,很容易出现某种反智主义。我几乎已经习以为常了,对很多媒体也是一笑置之。但是惊讶的是,我看到了姚晨这样一条微博:

yweibo-of-yaochen-praicy

我觉得一个与自己领域不相关的、受人关注的明星转发这样一条信息,动机很值得怀疑。当然,肯定不是从中的到了广告费,这不太现实。我觉得是明星是因为需要保持一种“受关注度”。

一直以来,我们对公众人物的期望太多了。比如出现灾难事故,我们期望他们捐款,觉得没有别人多,去微博骂,不捐,更要骂,给国外捐,还要骂。国庆,你要表示爱过,不然,骂你。出现这样一种情况,可能和明星们来钱的方式有关,靠着出歌卖CD赚钱实在太少了,更多的收入要依靠粉丝的支持和出场费用。一旦受到封杀和抵制,打击巨大。

正式因为正版产品卖不出去,才造成了这样一种不健康的状态。这种危害也可以见于别的行业,例如游戏。

对于单机游戏来说,良心开发一款游戏,需要巨大的开发时间和成本。回本就靠发售的时候出售正版。然而国内正版风气实在太差,导致基本不可能赚钱。所以国内发展的基本上是手游,网游,依靠在线道具出售盈利,然而很难见到里程碑式的作品。

还有电影。现在的时代,即使不去电影院,在线买个会员或者一次性为电影支付在线费用,也就几块钱,这也会支持导演和演员们,但是人们更倾向于用种子来下载。

盗版如此猖獗,错不全在群众,很大意义上,这是政府的过失。一方面,我们对盗版的打击力度太小,导致使用盗版的成本和风险都太小了。我们随处可以下载到音乐、电影和游戏,当然不会有人付费。我之前买过一台二手的PS3,本想买几盘游戏补补课,但是到手之后,发现这是一台破解机。一盘游戏上百,禁不住诱惑就去玩盗版了。后来想从正的时候发现被索尼ban了,损失惨重。这也给了我一个教训,以后再也不碰盗版游戏!现在很多游戏厂商不愿意开发PC版本的游戏,甚至不愿意移植,就是因为PC平台的盗版严重。而PSN平台对正版保护力度很大,就有很多经典的作品。

101087684

另一方面,我们对正版的支持力度太小。众所周知,我们国家有着非常严格模糊的审查制度。这其中有很多不好说的因由。这就造成什么能在大陆上,什么不能,有着很模糊的定义,法律上完全是空白,一切广电说了算。像欧洲和美国都有一套电影和游戏的分级系统,对于血腥、色情和暴力明文划分。而在中国,有很多优秀的作品因为文化部一纸禁令不能发行。即使要封杀什么东西,请明文规定,指出其违反了什么法律,我们无法可说,可是稀里糊涂遭到封杀,让人接受不了。更糟的是,前几年国内出现一款游戏,尺度很大,因为没有分级系统,很多低领人群可以轻松玩到,其画面非常色情、血腥,让人担心。这些作品的封杀,导致我们想要像国外的玩家、观众一样得到他们,只能使用盗版。

打击盗版,支持正版不能是一句空话,很大程度上,取决于国家的态度。希望早日能有法可依,执法必严。不要等到没有人再去够买正版,没有人再去写歌,不要大众对明星暴力的期待持续下去,不要让我们的人民不能从正当的劳动中得到一分钱,反而靠着偷鸡摸狗(是我就是在说破解网站,操你妈的)之事才能获利,不要等到人们丧失了创造的热情和信心的那一天,不要等他们不能再创作的时候说“我们欠谁谁一张电影票”,现在就用行动支持他们。

 

将编程视作艺术

《ACM通讯》在1959年发行的时候,其社员发表过以下评论,在后来成为了ACM的追求:

编程如果能在计算机研究和发展方面成为一个重要的部分,必然存在着从艺术到一门严谨科学的过渡。

这个目标在接下来的几年中不断重现。例如,1970年“将编程从艺术过渡到严谨科学的第一步”发表了。同时,我们也成功地以最简单的方式将规则变成科学,称之为“计算机科学”(computer science).

一个领域一旦被归为艺术,就会产生一些让人不愉快的东西,在具备实质性的声望之前,必须先被认作科学。另一方面,我花了十二年写的系列丛书就叫做“计算机程序设计艺术”(The Art of Computer Programming)。经常会有人问我,为什么起了这么一个标题。甚至还有人不相信我用了这么个标题,在很多引用中,我发现他们错把书名引用为“计算机程序行为”(The Act of Computer Programming,这里,错把art当做act)。

在这次演讲中,我想解释一下为什么我觉得艺术是最合适的词、艺术和科学什么不同、艺术是好是坏以及正视这门学科对我们有什么帮助。

我第一次谈论起这个标题是在1966年。那是在加利福尼亚举办的世界性ACM会议上。那时候我的书还没有出版,我和一个早已了解我的自负朋友一起在酒店吃午饭的时候,他打趣道,“新书打算叫做高德纳导论吗”,我回击道,“恰恰相反,我打算用你的名字。”他叫Art Evans。

这个故事告诉我们,艺术(“art”)一词可以有不同的意义。实际上,最有趣的地方是,几乎所有的意思多多少少都和计算机编程有关。准备演讲的时候,我去图书馆查了一下有多少和用了“艺术”一词的出版物。几天之后得出结论,“艺术”可能是语言中最有意思的一个词了。

旧的艺术

如果追溯到拉丁文中,ars,artis表示技巧,和希腊的τεχνη有差不多的意思——技术和技巧的词根。

现在提起艺术,可能你的第一印象就是美术,例如绘画、雕塑之类的。但在二十世纪之前,艺术的意思和现在大不相同。即使现在,某些方言中还保留这艺术原来的意思,特别是和科学相比较的时候,我想花几分钟介绍一下艺术的经典含义。

中世纪时候,第一所大学是为教授七门学科建立的:语法,辩论,逻辑,算数,几何,音乐和天文,叫做“liberal arts”。注意,这和今天的文科大学有很大不同,七门课中至少有三门是和计算机密切相关的。那个时候,艺术一词指的就是人类设计制造的东西,反抗自然和天性。“liberal”就是自由和解放,和耕种等劳动是对立的。中世纪的时候,艺术本身的意思是逻辑,即三段论的学习。

科学 vs 艺术

很多年来,“科学”一词和“艺术”有着差不多的含义。比如,人们讲七门学科统称作“自由的艺术”,有时候也叫做“自由的科学”。15世纪时Duns Scotus称逻辑是“科学的科学,艺术的艺术。”随着文明和科技的进步,它们才逐渐有了区别,“科学”代表知识,“艺术”代表知识的运用。比如,天文科学研究原理,艺术就是研究如何利用其进行导航。和今天科学与工程的差别差不多。

19世纪有很多有关科学和艺术的讨论,我觉得最好的是John Stuart Mill,他写道:

很多时候,几门不同的科学相互联系,来完成一件事情。人们要结合不同的事物,来做到一件事,这需要懂得不同方面的知识。从某种意义上说,艺术就是组合不同方面的科学,将其付诸实践,而不止于空想。将不同的科学组合在一起,我们才有了探索宇宙真理的可能。艺术将关系偏僻的学科联系在一起,运用到现实生活中,来满足我们的需求。

在我研究艺术的意义时,我发现从艺术到科学的过渡持续了至少两个世纪。比如,1784年的一本矿物学教材的序言中有下面一句话:“在1780年之前,矿物学被认为是艺术,还不算作科学。”

大多数字典中,科学的意思是逻辑、系统地组织一般规律。科学就是可以让我们从更高层次的概念上来思考问题。就像John Ruskin在1853年写的,科学的工作就是将现实的现象进行抽象。

假如这些人能生活在我们这个时代,他们也许会同意以下观点:科学就是我们了解透彻的知识,我们能够把这些只是教授给计算机。如果我们没了解到这个程度,那么就还处在“艺术”的认知阶段。算法或者计算机程序的概念,提供了一种可以测试我们对某一领域了解有多深的方法,从某种意义上说,从艺术到科学的过渡阶段,也就是我们学习如何在这一领域实现自动化的阶段。

人工智能已经取得了重大进步,但是在可预见的将来,计算机能做的事情,和普通人类还有着巨大的鸿沟。人类能够语言,视听甚至编程的奥秘仍未解开,所以某种意义上,我们所做只可称之为“艺术”。

从这个方面说,将计算机编程变成一门科学是可行的,而且从演讲开头的地方我引用的那段评论起,已经过去了十五年,我们走了很长一段路。十五年之前,我们对编程了解的还很少,甚至不知道如何证明一段程序是正确的——直到程序正常运行之前,我们都是在盲目地尝试。只有在近几年我们才明白计算机处理的抽象过程。尽管只有很少的程序能够严谨地被证明正确性,这些理解还是带给了我们很多好处。重点是,我们今天在写程序的时候,我们知道,如果想要证明程序的正确性,是可能的。比起以前写程序,现在要可靠的多。

“自动化编程”是人工智能方面一个很火的分支。其倡导者或许会做这样的演讲:“将编程视作手工艺品(编程是很久之前的历史文物了)”。因为他们的目标是制造可以自动化编程的机器,代码写的比人类好,只要给出特定问题,就可以生成程序。个人来说,我这个目标是不可能的,但并不是说这个课题不重要,因为我们做的每件事都可以提高我们的“艺术技巧”,从这方面说,我们要力争将艺术的方方面面都转为科学:在这个过程中,我们不断推动着艺术的发展。

科学和艺术

从上面我们的讨论来看,计算机程序可以看做是艺术和科学,二者相辅相成。但是显然,很多人不管他们的领域是什么,都会得出这样的结论。我看过一本写于1893年的初级摄影的书,开篇说:“摄影的发展既是一门科学,又是一门艺术。”事实上,当我翻开字典查“艺术”和“科学”的时候,就看见字典的序言上写着,编著字典既是一门科学,又是一门艺术。数据和单词的整理归类是严谨的科学,而斟酌字句和定义则是一门艺术。科学失去了艺术也就失去了作用,艺术没有了科学则缺乏准确性。

准备演讲的时候,我在斯坦福图书馆的目录里面看别人都是怎么在书名里用“艺术”和“科学”的。结果相当有趣。

比如,我找到几本这样的书:《钢琴弹奏的艺术》、《钢琴演奏技巧的科学》、《钢琴练习的科学》,还有一本是《钢琴弹奏艺术:一种科学的方法》。

还有一个比较有才的标题是《数学的高雅艺术》,至少我觉得计算机编程算不上是“高雅艺术”。几年之前,我看过一本叫做《计算的艺术》的书,1879年在旧金山出版,作者是C. Frusher Howard。这本书是将使用的商业计算的,1890年之前,卖出了40万册。序言中作者的理论和我的截然不同,他说:“数字计算的科学并不重要,但是认知的艺术技巧不可或缺。”

还有一些书同时用了科学和艺术两个词,例如Maharishi Mahesh Yogi 的本体科学和生活的艺术。还有一本叫做“科学探索的艺术”,讨论的是科学如何做出重大探索发现的。

从上面可以看出,艺术可以有如此多的含义。但说实话,我在取书名的时候,并没有特意地去考虑这些。有一本很有意思的书,Robert E. Mueller的《艺术的科学》,所表达的意思最接近我今天的主题。他说:“曾经有人认为,搞艺术的丝毫不懂逻辑,而搞科学的在艺术方面就是呆瓜。”他解释了综合艺术和科学所带来的收获。

科学的方法是关乎语言逻辑,系统条理,客观,冷静,理性。而艺术关乎审美,创造,主管,激情,不合逻辑。对我而言,两者在编程方面都有价值。

Emma Lehmer在1956年写道,她觉得编程是“一门令人激动的科学,又是一门迷人的艺术。”H.S.M. Coxeter 在1957年写道,他感觉自己更像一个艺术家而不是科学家。同时,C.P. Snow也在反对两极分化,声称如果我们如果想做出真正的进步,就必须将科学和艺术相结合。

艺术的工作

我听长演讲的时候,一个小时左右注意力就开始不集中了。所以现在大家是不是也有点累了?不过希望接下来大家集中注意力,因为这是我最深入的部分了。

当我谈到计算机程序是一种艺术的时候,我说的是一种艺术形式,一种感官的审美。作为教育工作者和作者,我的工作就是帮助人们学习如何编写优美的程序。鉴于这个原因,最近我得知我的书被康奈尔大学放在美术图书馆的时候格外高兴。(显然,不会有人到这里翻这本书,八成是图书馆管理员因为署名弄错了吧。)

我认为,当我们写程序的时候,就好像在写诗或者谱曲,如Andrei Ershov所说,编程可以给我们理性和感性的双重享受,因为它的目标就是控制复杂的东西,用不同的规则建立庞大的系统。

还有,当我们读别人的程序的时候,就如欣赏艺术品一般来理解它们。我仍然记得1958年在SOAP II上读汇编代码的感觉。可能这听起来有点疯狂,但是我很好奇如此庞大的程序是怎样的。手写漂亮的代码是完全可能的,即使是用汇编语言。这就是我涉足计算机程序的原因。

有些代码很优雅,有些很精妙,有些则闪耀着智慧。我认为,写出宏伟、壮丽、高雅的代码就是一种艺术。

口味和风格

编程的风格在近几年成了热门的话题,推荐读一下Kernighan和Plauger的《编程格调》。需要强调的是,没有什么最好的“风格”,每个人都有自己的喜好,强迫别人适应一种风格是错误的。我们经常听说:“我不懂艺术,但是我知道自己喜欢什么。”重点是,你要喜欢自己所采用的风格,那应该是你表达自己的最好的方式。

Edsger Dijkstra在他的《计算机程序设计艺术导论》的序言中说:

我的目的是让人们认识到编码风格的重要性,但是特定的风格仅仅只能让人意识到风格化的好处。就像教授谱曲的老师,老师不会去教学生如何谱写特定风格的曲子,而是教他们如何挖掘自己的风格,表达自己。

现在,必须来谈谈什么是好的风格,什么是坏的。我们不能用死板的眼光来评判别人的工作,19世纪的哲学家Jeremy Bentham是这样说的:

评判风格和口味就是把自己放在了全人类的领袖的位置上,其实能影响的只有自己的风格而已。没有什么是最好的,除非你的工作是满足雇主的需求;没有什么是最坏的,除非你在故意恶作剧。

当你按照自己的喜好纠正别人的风格的时候,可能从潜意识里干涉了别人的权益。这就是我一般不去反对大多数程序员的原因。重要的是,他们在创造他们认为美的东西。

Bentham提出了一个关于审美的很好的建议——“实用性”。我们有选择风格的自由,但是如果能在符合我们自己的审美的同时,别人用起来又很方便,就更好了。我承认我很享受编程,但是更享受写性能良好的程序。

当然,评价一个程序是不是好的方面也有很多。首先,程序能够正确肯定是好的。其次,如果程序修改起来简单,能够自如应对以后的需求改变就更好了。如果在保证这两点的同时,程序又具备可读性,就完美了。

产品型的程序还有一个重要的地方——与用户的交互性,特别是处理用户输入数据的错误时。组织有意义的错误信息和引导减少错误的设计的确是一门艺术。

另一个重要的方面是程序运行时候的性能和占用的资源。但是现在很多人在谴责关注程序性能,称这得不偿失。现在的计算机进步了,不需要在乎那点性能。而过去的程序员因为过度关注性能, 写的代码极其复杂,导致以后维护和debug的时候非常困难,不足以弥补性能所带来的优点。

真正的原因是,程序员在错误的时间和错误的地方过度关注了性能。过早做优化是罪恶之源。

我们不能反对劳动,提倡懒惰,既不能疏于优化,也不能迷失在斤斤计较的时间和内存中。当我们买一辆车的时候,可能对50块或100块不怎么在乎,但是在商店买东西的时候,对几毛钱都会斤斤计较。我观点是,考虑性能要考虑时机和地点。在我的结构化编程的论文中详细讨论了这个问题。

更少性能,更多快乐

我发现,当我们用有限的工具完成了事情的时候,所获得预约会更多。例如,我曾经写过的一个非常自豪的编译器,仅仅使用了4096个字,每个字16比特。在限制之下做事情会让人有记忆超群的感觉。

同样的道理适用于很多场合。比如,比起加长型林肯,人们更爱他们的大众汽车。当我学习编程的时候,那还是一种消遣,程序是写在打孔纸带的上的,那时候大家在比谁用的纸带更短。现在我们教授编程的时候,如果不让学生在计算机上亲手实验的话,就很难激发他们的学习热情。大规模计算机以及他们的操作系统和编程语言很难从一开始就引起他们对编程的热爱。

如何将这些准则用于提高程序员工作上的预约比较模糊。如果经理突然宣布,新的机器内存只有之前的一半,肯定所有的程序员都会抱怨。任何人,即使是非常热爱编程的人,都不会愿意损失不必要的性能。一个很好的例子是,很多电影制片人在1920年的时候抵制有声电影,因为他们很自豪没有声音也能很好地传达电影的意思。相同的,可能有程序员也抵制性能更好的机器。今天机器性能的进步可能多少毁了一些代码的优雅性,但是却没有人愿意回到默片时代,不是因为懒,而是因为他们知道利用先进的科技,制作多彩的电影是可能的。艺术的形式改变了,但是供艺术家发挥的空间依然很多。

那么他们是如何提高自己的技术的?多年来,最好的制片人往往生活在电影工业不是很发达的国家,在艺术方面有很多限制。近年来,对编程事业推动较大的人都不是有很多机会接触大型计算机的人。这个故事告诉我们,应该在教育中限制资源,当我们认为设限,才会被迫将自己的能力超这个限制进步。我们不能永远生活在奢华的环境中,那会让我们丧失激情。竭尽所有的资源来解决问题会给我们磨练,当面对真正的问题时才能游刃有余。而且在限制下解决问题也会带来更多快乐。

同样都是艺术家,我们没必要因为有趣去做一些事感到有负罪感。我迷上编程就是因为一个解决素数问题的ALGOL程序,而不是产品化的东西。以前我有一个斯坦福的学生,发现了最短的可以打印出程序本身的源代码的FORTRAN程序而激动不已。我并不认为研究这种问题是一种浪费,上面提到的强调“实用性”的Bentham也不反对,他说“相反,这其中的实用性是无可争议的,快乐的源泉不就是最大的实用性吗?”

提供优美的工具

现代艺术还强调的一个方面是创造性。现今大多数艺术家都期望创造出美丽的东西,只有有创新性的想法才有价值。我不是说程序在这方面完全一样,只是这带给了我一方面的灵感。有时候我们会被分配一些很枯燥的工作,甚至几乎是不可能完成的,没有丝毫创造性。这时候有人可能会说:“编程还是美妙的吗?你没有压力,可以随便写优雅的代码,可以这样说。像我一样要处理这些东西,还能说编程是艺术吗?”

的确,不是所有的编程工作都是有趣的。比如家庭主妇,每天要一遍又一遍地打扫相同的地方,这种工作没有创造性。但是即使在这种情况下, 依然可以有乐趣:如果我们有漂亮的同居,那么即使是例行工作,也会有趣的多。想象一下,如果桌子是精心设计过的,非常漂亮,那么每天去擦也不会枯燥。

我想要呼吁所有设计系统和机器给我们用的系统工程师和计算机工程师们,求你们给我们方便的工具,尤其是那些常用的,而不要我们每天跟它们做斗争。请给我们有动力写出好代码的工具,让我们在编程中享受更多快乐。

对我来说,让大学新生接受“编程很有趣”的观点多少有些困难,因为一开始我就要教他们“xxxx任务等于这样这样和这样”,即使批处理语言可以设计的方便易用,而不是像现在这样这么死板。

硬件工程师可以将机器设计地更加易用,例如提供符合数学规律的浮点运算。现在机器上的运算让调试和分析异常困难,但是设计良好的运算可以鼓励数字分析源提供更好的子运算,具备更高的精度。

软件工程师可以做什么呢?一个绝佳的方式是,给系统用户提供可以交互的进程管理程序。系统不应该过度自动化,不能让太多的动作在后台默默进行,应该让程序员可以监视进程的运行。有些任务可以让系统自动完成,有些则应该让程序员手动操作。如何在两者之间取舍?这就是一个优秀的操作系统应该权衡的事情了。

程序度量工具也是一个重要的方面。多年来,程序员对自己程序的性能和开销大多估计有误。那时工具及其有限,也难怪性能总会和预期出入很大。这种工作就像是,新婚夫妇在不知道柴米油盐价格的情况下,做家庭开支预算一样。程序员所有的就是一个优化编译器,而且它的细节也不得而知。幸运的事,我们现在有了系统的监控工具,能实时反映程序指令和开销。这种系统已经取得了巨大的进步,不仅仅因为度量工具的成果,还因为使用起来非常方便。我相信不就的将来,普及只是时间问题。

众所周知,编程语言对风格的影响很多。所以语言设计者也有义务将程序语言超鼓励良好风格的方向发展。现在的语言在程序和数据结构方面的表现都不尽如人意,所以我很期待接下来纪念语言设计的发展。

总结

我们将编程视作艺术,是因为它需要知识的积累,需要技巧和才智,更因为它创造美的东西。将自己当做艺术家的程序员,在工作中能享受到更多的快乐,也会更加出色。我期待能在将来的计算机大会看到人们用这样的标题:艺术的现状。


这是Donald E. Knuth的Turing Award Lecture演讲,原文发表于1974年《ACM通讯》,译者赖信涛。本文禁止转载。