天天看點

軟體開發是一門手藝活

開發軟體并不像是工廠在制造産品。20世紀80年代,大家驚聞日本在建造“軟體工廠”,這些工廠能通過流水線作業批量生産高品質的軟體。而這在當時的技術水準下是天方夜譚,即使是現在的技術也還達不到。把一群程式員塞進工廠中的房間,讓他們站成一排,并不能有效地減少bug數量。

如果寫代碼不同于流水線作業,那它更像什麼呢?有人提出,軟體開發是一門手藝活。當然,這種說法也并不總是成立的,因為不知你怎麼想,反正我覺得那個詢問你該如何索引幫助檔案的Windows對話框,從形狀到樣式,無論從哪個角度看,都和人們常說的“工藝品”差遠了。

寫代碼不是工業生産活動,也不總是一門手藝活(但它可以是),它其實更像是一種設計活動。設計是一個很模糊的概念,其特征在于用較慢的成本增長換取較快的價值增長。《紐約時報雜志》對iPod贊不絕口 ,稱贊蘋果公司是世間少有的知道如何用優秀設計來增加價值的公司。

圖檔由蘋果公司提供,詳情參見:http://www.apple.com/pr/photos/ipod/03ipod.html

但是,關于設計這個話題我已經講了很多,現在想談談軟體開發的工藝品特性,包括它是什麼以及如何辨識。 我想和大家分享一段我正在重寫的代碼,它實作的是CityDesk 3.0的檔案導入功能。(插播一條廣告:CityDesk是我的公司釋出的一款友善易用的内容管理産品。)

功能規格說明非常簡單。使用者通過标準的對話框選擇一個檔案,然後程式把該檔案複制到CityDesk資料庫中。

結果這個例子很好地說明了,有的時候“寫好最終1%的代碼要耗去90%的時間”。程式的第一版設計草案是這樣的:

(1) 打開檔案;

(2) 把全部内容裝進一個龐大的位元組數組;

(3) 把位元組數組儲存為資料表中的一個條目。

這個程式在通常情況下運作得很順暢。對于一般大小的檔案,程式基本上一眨眼的工夫就跑完了。但是它存在幾個小bug,容我一一列舉。

其中一個較大bug出現在壓力測試中,當時我試着把一個120MB的檔案拖入CityDesk。一般情況下,人們不會在網站上放這麼大的檔案。這在實際中幾乎不可能出現,但也不是沒有可能。程式運作了大概一分鐘才結束,其間沒有任何視覺回報,界面呈現假死狀态,點選哪裡都沒有反應。這明顯不夠理想。

從使用者界面設計的角度來考慮,我應該在程式進行耗時操作的時候顯示某種進度條,以及一個取消按鈕。更理想的情況是讓檔案在CityDesk的背景進行複制,不影響使用者進行其他的操作。要實作這一功能,比較容易想到的方案有三種:

(1) 隻開一個線程,每隔一段時間檢查是否有輸入事件;

(2) 再開一個線程,仔細地做好線程同步;

(3) 再開一個程序,不需要很仔細地做好程序同步。

我的經驗是,方法1的效果總是不夠理想。當程式正在進行檔案複制操作時,很難保證其他所有代碼能安全運作。埃裡克•雷蒙德的論述讓我相信,多線程的方案不如多程序的方案 ,而且根據我多年的經驗,多線程程式設計增加了太多額外的複雜度,會引入不少這種方案所獨有的、危險的海森堡bug 。3号方案看起來更好,尤其是考慮到我們使用的資料庫支援多使用者操作,并不介意多程序的并發通路。是以過了這個感恩節假期,我準備用方案3來實作這個功能。

但是退一步想,我們從最初簡單的讀取檔案、儲存到資料庫出發,最終采取了一個複雜得多的方案:開一個子程序,讓它讀取檔案并儲存到資料庫;子程序還要有進度條和取消按鈕; 并且要建立一種機制,讓子程序能在檔案儲存完畢時通知父程序,即時顯示處理完畢的檔案。另外要做的一部分工作是通過指令行把參數傳遞到子程序;還要處理視窗焦點的行為,讓它符合使用者的心理預期;以及特殊情況的處理,比如使用者在程式正在複制檔案的時候關閉電腦。我猜最後要寫的代碼量是原來的10倍,隻是為了優雅地處理大檔案,而這些工作的成果隻有大概1%的使用者能看到。 當然了,還有一種程式員會認為,子程序的方案還不如原來的方案。它被“過度設計”了,增加了太多額外的代碼行,這也導緻程式更有可能出現錯誤。這叫過猶不及。他們會說,這種做法是是典型的Windows思維,Windows在他們眼中并不是一個設計得很高明的作業系統。他們對設計進度條的必要性嗤之以鼻。因為在UNIX下,隻要敲擊Ctrl+Z然後用“ls -l”看看檔案體積有沒有增加就知道程式是否還在運作了!

這個故事告訴我們,修複出現機率為1%的問題,有時候需要花500%的精力。這種情形并不是軟體開發活動所獨有的,我這樣說是因為我管理過一些建築施工工程。上周,我們的建築承包商最終完成了對Fog Creek新辦公樓 的裝修完善工作,包括給正門裝上嶄新的藍色丙烯面闆,并在門的邊緣每隔20厘米包上一條鋁片。仔細看下面這張照片,你會發現每扇門的四周都有鋁條。在兩扇門接觸的部分,兩條鋁片呈豎向對齊排列。在圖上可能看得不明顯,但這兩條鋁片中央的固定螺絲并沒有完全對齊,大約相差2毫米。木工師傅事先做了仔細測算,但是在安裝鋁條的時候,門是放在地上的。等到門挂到軸上才發現,壞了,螺絲很明顯地沒有對齊。

這種情況絕非個例,我們的辦公室裡有很多螺絲不是完全對齊的。問題在于打完孔後再矯正位置的成本是很高的。正确的位置隻偏那麼幾毫米,是以不好重新打孔。如果追求完美的話,隻能換掉整扇門,太不值了。這個例子再一次闡釋了有時候修複出現機率為1%的缺陷需要500%的努力,也同樣揭示了為什麼這個世界上有那麼多工藝品的完美程度停留在99%,而不是100%。(我們的建築師總是喋喋不休,聲稱亞利桑那州的某些豪宅中,每顆螺絲都是完全對齊的。)

大部分人都認為,軟體具有與之類似的特性,讓它帶有工藝品的氣息。當一群真正具有工匠情懷的人們建構一個軟體産品時,他們會想辦法對齊所有的螺絲。也就是說對于一些極其罕見的情況,軟體也能處理得很漂亮。但要做到這一點,開發者勢必将大部分的精力投入到對各種罕見情況的正确處理上,而不是集中精力讓主要的業務邏輯正常運轉。這也就意味着開發者要用500%的精力去處理好出現機率為1%的情況。

要達到一定的工藝水準,需要付出巨額的開發成本。軟體行業裡唯一值得付出巨額的開發成本的情形,是開發面向海量使用者的軟體。很遺憾,譬如保險公司的内部人力資源系統,就永遠不會達到這種完美的工藝水準,因為沒有足夠的使用者數量來攤薄成本。然而對于開發零售軟體的公司,這種不斷追求并完善軟體品質的做法正是使用者想看到的,因為那将會為公司提供長期的競争優勢,是以請廣大使用者耐心期待,我們會慢慢來,因為慢工才能出細活。

軟體開發是一門手藝活

摘自《軟體随想錄 卷1》

繼續閱讀