重写Reddit

2012年注:本文首发于2005年。发布之后,Django上线了一个RemovingTheMagic项目,提出了我的一些质疑(尽管我本人发现它仍然不可用),[web.py](http://webpy.org/)促进了FriendFeed的[tornado.web](http://www.tornadoweb.org/)和Google的[gae.webapp](https://developers.google.com/appengine/docs/python/gettingstarted/usingwebapp)以及其它项目(尽管如此我仍然喜欢web.py),本文引起了Reddit流量的永久井喷,仍然没有真正地停止增长。

reddit.com过去的一周里,我们用Python代替Lisp重写了网站。这周我们做了很多工作(透露:我们使用了我开发的web.py类库)。其他人熟悉Lisp(整个站点用它编写),他们喜欢Python(他们用它重写了整个站点),然而他们决定,在这个项目中喜欢Python多一些。Python版本的网站需要更少的代码,运行更快、代码更容易阅读和维护。

根据在reddit博客上的评论,比Lisp更好的东东的想法,表面上对一些人是不可思议的。Lisp爱好者们很快着手尽量找到变换语言背后的真正原因。

有人认为这里面一定有不同寻常的干预,由于“貌似没有切换到低等语言的其它原因。”又有人觉得其它事情必须在发生着:“这会是……一个谎言?扔掉竞争力?貌似Paul Graham没有在他的文章里暗示这个策略呀……”还有人附和道:“我认为这是恶作剧。”也有人提出,作者只是想更多地“走捷径、hack和伪装手法。”

当然,它们都是极端的情况。其它人猜测一定有来自外部的压力。“我猜,要么是类库,要么是雇佣新员工。”有人总结到:“一些投资商想要任何程序员都能维护的产品。我希望他给你支付了好多钱。”

Lisp新闻组comp.lang.lisp对于这次切换感到失望,他们为了表明自己是多么地正确,最近正计划把reddit写成Lisp的一个竞争者

这些说法当中,稍微中肯的提到Lisp的价值在于能够创建新的语言结构,这对于简单的web应用程序而言,是不必要的,因为结构已经被建好了。不过,这也不是真实的。web.py完全从零起步,用到了各种“新的语言结构”(linguistic constructs)——甚至更好——这些结构具有语法,让它们具有合理的可读性。当然,Python不是Perl 6,因此你不能增加任意语法,不过你经常能够找到把事情搞定的聪明方法。

另一方面,Python有它自己的问题。最大的问题在于它有很多web应用程序框架,但是都不太好。Python爱好者只是注意到了第一句,而明显忽视了第二句,因为当我告诉他们我正在用自己的类库时,通常的反应是“我认为Python不需要另一个web应用程序框架”。是的,Python需要更少的web应用程序框架,但是它也需要不是太糟糕的框架。

貌似最有前途的框架就是Django了,我们最初的确想用它重写reddit。做为有经验的Python程序员,我尽量帮助其他人解脱出来。

从外面看Django貌似优秀:良好外观的网站、极具才能和天赋的开发者,表面过剩的、优秀功能。开发者和社区是非常有帮助的,也对补丁和建议作出响应。所有正确的目标都在他们的哲学文档和FAQ得以支持。然而不幸的是,它们好像完全没有达到自己的期望。

Django声称它是“松耦合”的,却要求你的代码符合Django的风格。Django坚持你的代码执行本身,或是通过命令行工具,或是借助正确的环境变量和Python路径做特定的服务器处理程序调用。当你开始项目时,Django默认为代码生成了嵌套四层的文件夹,而你能够移动一些文件,我在搞清楚移动哪一个以及如何移动上遇到了麻烦。

...

如果它是一种流动,它就是艺术

我现在听到了。“哦,主教Jeebus,不是一个 认为代码是艺术 的程序员。”问题在于,每个属于艺术家的人都喜欢玩一个虚伪的游戏,他们做的任何事情都是艺术,即使把鸡肉绑在他们的内裤上。然而,不在艺术家俱乐部的任何人都不能把他们做的事情称作艺术。他们想随便把一个垃圾堆卖给富得流油的笨蛋,但是如果你试着说,你辛苦写了一年的C++代码是艺术,那么你就错了。对不起,呆子,你脖子上没有纹身,也没有海洛因静脉注射疤痕【注1】,那么你不可能在搞艺术。

对不起,如果艺术家能够把家禽绑在她的内裤上在地板上堆垃圾,或者什么也没做,那么任何人做的任何事情都是艺术,包括我精心编写的C代码,早上我排出的粪便,还有我的水彩画。基本上,如果你想把你做的事情称作艺术,那么它就是艺术。如果有人对你说它不是,那么他们就不是艺术家。证明完毕。继续。

事实上,我想讨论的、关于为什么代码是艺术,不是从外在视角的、需要纹身的种类来评判,而是当你在一件事的时候,这件事对你做了什么。在我开始学习水彩之前,我没有把它看做“什么是艺术”的视角。与深入编程、写作、舞蹈或者演奏音乐的时候,水彩和素描是我曾经体验过的、非常熟悉的感觉。精神高度紧张时,时间停止了,身体内的所有地方和意念完美配合,就好像我自己不存在了。当沉浸其中时,直觉的跳跃、极度兴奋和放松,是程序员、音乐家、艺术家和作家体验到的一切。一种感觉的流动是贯穿他们的共通活动,与很多需要高度专注于大脑活动的一种更改状态的活动类似。

在Gray Marcus的著作《Guitar Zero》里,他讨论了你的大脑如何没有专门的“音乐部分”。研究表明演奏音乐让你的整个大脑使用很多部分去协调,但是每个部分在做着不同的事情,而不是你演奏时的平常功能。在白天的工作时,一部分处理语言,当你演奏音乐时,它会检测音符距离。另一部分的白天工作是追踪运动的物体,当你演奏音乐时,它会处理时间的选择。当你演奏完音乐时,他们回到了白天的工作,你突然就回到了正常状态。

我相信这种同样的现象发生在(但不限于)编程、视觉艺术、音乐、舞蹈和写作上。这些都是活动,它们在人类历史上比较新近,他们不是我们固有的本性,而是需要教育,所有这些好像都需要同样的更改大脑功能。除此之外,这些活动输出的接受者,在听音乐、观看视觉艺术或阅读时,也可能体验着相同的感觉。

这种现象可以解释感觉的流动,它能够解释为什么人们喜爱这些活动。这种流动是一种让部分大脑做一会儿不同工作的、单纯的能力,海马(译者注:大脑中被认为是感情和记忆中心的部分)的一种旅游。还可以解释,它为什么需要训练,为什么让人厌倦,在很多方式上,为什么它难以复原。很多程序员、艺术家和音乐家在经过这种更改大脑功能的一段时间后,会谈论与其他人交流的困难。

还有,人们可能享受到这种感觉,因为它提供了类似的、更改的意识,就像他们从毒品、酒精、沉思、宗教体验中得到的,只是需要很少的努力或意想不到的结果。不必静静地坐数个小时祈祷或沉思,你就能做一些艺术、阅读、写作或编程。在欧洲,有一种传统,艺术被作为一种沉思,礼拜者在他们祈祷时会想象一部分圣经,当艺术家在画画或雕刻的时候,他们被认为在与上帝交流。它可能是流动现象中的、这种传统的起源。它也解释了为什么艺术、音乐和宗教是如此地被交织在一起。

我现在相信,如果某种活动带来了流动的感情,需要一种更改的大脑功能去做,那么这种活动就是一种艺术。与这种活动的输出内容无关,而是这种输出对你的大脑做了什么。编程之所以是艺术,是因为它需要让你的大脑做一些平时不那样做的、却产生了一种沉思的感觉,需要努力却觉得不太费力。

我还有一种模糊的想法,它对于提高艺术教育至关重要。当前的艺术教育是关于艺术家的外在结果。他们可以创作一幅看起来像某种东西的画作吗?他们能够在地板上堆垃圾吗?他们能够演奏出爵士平均水平吗?他们能够分析一种算法吗?然而,如果艺术、音乐和编程教育具有额外更高的、使用那种艺术帮助学生学习这种流动的技能的目标,又该如何呢?如果学生能够做这种小小的、精神上的技巧,那么他们能够在这种活动之外得到更多的享受,而不仅仅是他们创作了什么。它将是通过教授一门实际技能来获得精神健康的一种目标。尽管如此,我写到这里的时候,还是觉得有些疯狂。

现在,我认为,如果你做的事情给了你一种感觉流动,那么它就是艺术。我甚至现在可以说,最好的艺术引起了在其他人的这种流动,如果你曾经见过有人一整天在玩电子游戏或上网,那么你就知道编程在这个部分击败了一切。

...

冰激凌和分布式系统

我们能够处理好冰激凌的总量吗?

在我小时候,我真的喜欢吃冰激凌。它现在还是不错,只是回到那个时候我对它多少有些狂热。我父母知道脂肪和糖的美味混合物最好偶尔食用,因此要小心地限制量。当然,我找到了系统中的方法。首先,我找到妈妈,问问是不是可以吃冰激凌了,她将给出答案。如果她不同意,我再去找爸爸问同样的问题。这个策略增加了获得同意的机会,因为我父母的决定不是一致的。少数情况下,我甚至能吃到妈妈同意的冰激凌,然后找爸爸尝试图吃到第二碗。

这种诡计持续了一段时间后,我父母明白过来了。他们决定有必要给我提供一致的答案,唯一的方式就是在我询问吃冰激凌时,他们每次都要彼此沟通一下。他们的协调方法非常有效。它确保了一致性的答案,只不过让我等待问题答案的时间稍微长了些。

当我父母上班时,这种方法就不管用了。做为一个孩子,我能够找到好借口在任何时候与其中一个家长说话,但是他们的工作会妨碍他们彼此沟通。再一次,我可以把这种情况用在了丰富的、甜甜的、奶油优势上。由于我父母无法交流,我能够强迫得到不一致的决定。我父母让他们做出是否购买冰激凌的一致性决定,却不能彼此沟通,这是他们的失误?

假定网络由至少两个节点组成,这样网络可以被分为两个不相交的、非空集合:{G1,G2}。证实的基本思想就是假定G1和G2之间的所有信息都丢失了。如果G1发生了一个写操作,随后G2发生了一个读操作,那么读操作不能返回之前写操作的结果。

假定我父母没有手表,他们做出的决定只能根据他们收到的信息和内部状态,Glibert和Lynch证实了他们通常不能做出一致性的决定。这是关于写和读的通常结果。他们在某些特定情况下可以做得更好吗?

灵活使用时钟

在时间上,我父母的冰激凌策略是我一周得到一碗。他们每天上班之前商量一下,在我还没有得到每周配额的时候,决定在接下来的八个小时内,只有他们其中一个可以发出冰激凌的决定。如果轮到我妈妈负责,我给爸爸打电话要决定,他就告诉我,他不能给我决定。只要我能够联系到妈妈,我就能得到一致性的答案。如果我不能联系到妈妈,我就运气不佳了。尽管如此,补救措施就是如果妈妈加班,爸爸会注意到超过八个小时了,然后做出决定。

很快,我这个灵巧的小家伙,就意识到爸爸的手表比妈妈的表走得快些。当他到家时,我就去找爸爸要一个香草味儿的。他看看他的手表,发现八个小时过了,就认为妈妈已经失去了做决定的授权。在检查了冰箱里的碗仍然是空着的,以确保妈妈没有在白天决定,那么他就让我吃。我将狼吞虎咽地吃完,然后给我妈妈打电话。她的手表告诉她,还没有过八个小时,她就给我第二碗了。我打败了这个系统!

[客户的租约时间]被限额E因为始终偏移缩短了。至少,租约的正确功能只需要始终有一个已知的、有界限的偏移。

如果我父母读过Gray和Sheraton,他们将知道如何修复他们的租约协议。我妈妈和爸爸将不得不测出两个手表速率之间的偏差,在假定我妈妈不再拥有租约之前,要加上一些时间(E)到我爸爸的时间上。

把结果汇总

由于时尚饮食横扫全国,我父母认为冰激凌没有他们想象的那样糟。做为负责任的父母,他们仍然想追踪我的消费来检查他们的假设。在工作时间,我妈妈和爸爸退回到了做不一致的决定,每个人只是保持了他们自己同意的频率的记录。一旦他们再次回到家里,他们就累加各自数量,以得到精确的总数。

追踪口味有点儿难度。每次我提出一勺子的量,他们都要写下我被许可的口味。偶尔地,我打开冰箱发现那种口味没有了,然后我在打电话请求减少我的总数。由于我是个小孩子,不记事,我记不住妈妈或爸爸是否记录了“同意”,因此我随机给其中一人打电话记录“不同意”。这没有关系,因为他们仍然能够累加各自独立的数量,在一天结束后再汇总出精确的总数。精确的总数,也就是说,直到灾难发生才出现。

我从妈妈那里收到了吃草莓味冰激凌的许可,但是在制冰盒和冰冻果子之间的普通地方没有找到。我就回拨过去报告没找到,但是在我说再见之前电话断了。由于不能联系到妈妈而带来的焦躁,我向爸爸报告了同样的情况。当总数在一天结束被汇总出来时,我父母被负的总数搞晕了。我们发明了“负冰激凌”吗?

不幸的是,我父母没有追踪无冲突复制数据类型的开发。如果他们知道,他们将用