工匠技艺

作者:周思博(Joel Spolsky)
译:Paul May 梅普华
Monday, December 01, 2003 属于Joel on Software, http://www.joelonsoftware.com

软体制作并不是种生产程序。在1980年代每个人都在心惊胆跳,害怕日本软体公司建立「软体工厂」,然后用生产线大量制造出高品质的程式。这在当时行不通,现在也一样行不通。把一大群程式师塞进一个房间再排得整整齐齐的,并没有真正的降低臭虫的数目。

如果写程式并不是生产线式的制造行为,那究竟是什么呢?有些人曾经提议称之为_工匠技艺(craftsmanship)_ 。这也并不算对,因为我不在乎你说什么,Windows里询问要如何索引说明档的对话盒绝对称不上是「工匠技艺」,连一点边都沾不上。

ipod.jpg iPod

写程式并不是_量产_ 也不全是工匠技艺(虽然可以是),它是种_设计_ 。设计是那种价值比成本增加得快的朦胧区域。纽约时报杂志已经大肆吹捧过iPod,还说苹果是少数知道如何利用良好设计提升价值的公司。不过设计我也谈[够](/wiki/The_Joel_on_Software_Translation_Project:%E4%BD%BF%E7%94%A8%E4%BB%8B%E9%9D%A2%E8%A8%AD%E8%A8%88 %E6%89%8B%E5%86%8A%E7%AC%AC%E4%B8%80%E7%AB%A0 “The Joel on Software Translation Project:使用介面设计手册第一章”)了,现在想来谈谈工匠技艺,谈谈什么是工匠技艺以及要如何辨别。

我想想来谈谈我为CityDesk 3.0重写的一段程式:档案汇入程式。(广告:CityDesk是本公司出品的很容易用的内容管理产品。)

它的规格似乎和任何一段程式码一样简单。使用者用标准对话盒选择一个档案,然后程式将该档案复制到CityDesk的资料库中。

结果却变成「最后1%程式用掉90%时间」的最佳范例。最早一版的程式结构大概是这样子的:

1. 开档案
2. 把内容全部读进来,放在一个大位元组阵列里
3. 把位元组阵列放在一个记录中

效果不错。大小合理的档案几乎是一瞬间就做好了。它有几个小问题,我们一个一个来看。

当我把一个120MB的档案丢进CityDesk时跑出第一个问题。通常人们不太会在网站上放个120 MB的档案。事实上应该是少之又少才对。不过虽然少但还是有可能。程式可以用,不过等了一分钟而且画面上完全没有反应 - 程式就这样定住不动,看起来好像完全当掉了。这显然并不太理想。

由使用介面的观点来看,我真正要的是在长时间处理时出现一个进度棒之类的东西再加上一个取消钮。理想的状况下,你可以在CityDesk里继续其他操作,档案复制的作业会在背景执行。这有三种显而易见的方法可以达成:

1. 只用一个执行绪,由该执行绪经常轮询输入事件
2. 启用第二个执行绪,然后小心的进行同步
3. 启用第二个行程,然后不必那么小心的进行同步

我的经验是第一种作法行不通。要确定应用程式里所有程式码都能在复制档案时安全的执行,实在是太困难了。另外Eric S. Raymond也让我相信,以解决方案来说执行绪通常不如单独的行程好:事实上多年的经验显示,多执行绪程式设计产生了很多额外的复杂性,而且会引入全新种类的危险海森堡虫(heisenbugs)。第三项似乎是个好答案,尤其当我们下层用的是多使用者的资料库,不用怕很多行程同时使用。所以我打算等感恩节休假结束就用第三种作法。

不过整体想想看就会发现,我们已经由读档写作资料库变成复杂许多的东西:启动一个子行程,让_它_ 读档写入资料库,这个子行程还要有一个进度棒和取消钮,最后还要某种机制让子行程通知母行程,档案已经处理完可以显示..其他的工作还包括将命令列参数传给子行程,确定视窗焦点的行为正确,还要能处理使用者在复制档案时关机的状况。我猜等把这些都做好,大概要十倍的程式才能优雅地处理大档案,而这可能只是使用者所看到的程式的百分之一。

当然会有某类型的程式师出来争论,说我用子行程的新架构比原本的差。这种作法「过度膨胀」(由于那些额外增加的程式码)。另外潜在的问题也比较多(一样由于是多加的程式码)。这个作法做太过头了。这某种程度也表示Windows的确是个烂作业系统。他们会说这和进度棒有什么关系?他们会嘲笑着说:只要按Ctrl+Z再重复打"ls -l"看看档案大小有没有增加就好啦!

newDoor.jpg

这个故事的教训是修正一个1%的问题可能会用掉500%的工夫。这种状况并不只软体业会发生。敢这样讲是因为我现在就在管理这些建筑工程。上星期我们的包商终于完成Fog Creek新办公室的最后修饰工程。内容包括在前门安装闪亮的蓝色压克力,旁边围着铝框,铝框上每[20公分](http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe =UTF-8&safe=off&q=20+centimeters+in+inches&btnG=Google+Search)就镶有一颗螺丝。如果你仔细看照片,会发现每片门都会被铝框整个包住,当门关起来时,两片直框会并排在一起。虽然图上看不出来,不过中间铝条上的螺丝 几乎 但没有_确实_ 对齐。差了大概有2公厘。负责这件事的木匠很小心的测量,不过装铝框时门是放在地上,并不是等好门装好再当场装的。所以等到要把门装上去时,才发现螺丝并没有对齐。

这或许并不罕见;;我们办公室里很多门的螺丝都没有对的很好。问题是当洞钻好之后,要重新修正的代价贵得离谱。由于正确的螺丝位置离原来的洞只有几公厘,所以不能直接在门上再钻一个,可能得把整个门换掉才能解决。这实在是很不值得。这正是另一个修正1%的问题会用掉500%工夫的例子,而且这也解释了为何这世上很多人造物都是99%好而非100%完美。(不过建筑师倒是不断吹嘘,说某些亚历桑那州的高贵金屋里每根螺丝都排得很整齐。)

这点出了软体的一项特性,一项大部份人都视为_工匠技艺_ 的特性。当软体是由真正的工匠制作时,所有螺丝都会对得整整齐齐..当你做些很罕见的事时,应用程式会表现得很聪明。作者会投入更多的工夫去正确处理特的状况,而不光是让主要的程式会动。即使要额外再花500%的力气去处理1%的状况也在所不惜。

工匠技艺当然是非常昂贵的。唯一负担得起的方法就是针对大量的客户开发软体。很抱歉,不过保险公司开发的内部人事管理程式绝对不可能达到这种工艺的境界,因为就是 没有足够的使用者 来分散额外的成本。不过就套装软体公司而言,这种工艺境界可以让使用者高兴并提供长期的竞争优势,所以我愿意花时间并正确地执行。请容忍我吧。

这些网页的内容为表达个人意见。
All contents Copyright © 1999-2006 by Joel Spolsky. All Rights Reserved.