2009年5月29日 星期五

重新建造輪子

程式者的胡言亂語 : 程式者的胡言亂語
重新建造輪子

「重新建造輪子」是軟體開發領域很常被使用到的一個用語,它是許多程式員很常見的一種迷思,有時候,它甚至是可以說是一種心病。我們時常拿建造一個車子的過程來比喻開發軟體的過程。在這個比喻裡,車子是我們最終想要完成的系統本身,而輪子便是建造車子所需的重要零組件。在軟體開發領域裡,建造系統的重要軟體組件,便時常被比喻為輪子。而重新建造輪子,自然意指著重新開發系統所需的軟體組件。

為什麼說,重新建造輪子甚至是許多程式員的心病呢?這是因為許多程式員無法抵擋心中那個呼喚他們、引誘他們重新打造輪子的魔鬼。為什麼要把重新建造輪子這樣子的活動,說的好像是十分邪惡的一件事情一樣?

無庸置疑的,軟體開發的生產力,絕對是現代軟體開發最看重的指標之一,也是許多軟體開發所追求的重要目標。我們在軟體開發上,除了品質的確保之外,加速軟體開發的進程,同樣也是我們所會面臨到的最大挑戰。許多軟體專案的開發延遲,造成產品或服務推出市場的時間失去先機,甚至遲遲無法完成,多半都歸因於開發生產力的不彰。因此,許多開發流程的導入、軟體設計的技巧及方法,都著眼於生產力的提昇。

而輪子的重新建造,意謂著的便是很大的生產力浪費。原本已經存在的軟體組件,在過去肯定花費不少時間於需求的分析、界面的設計、程式的撰寫、以及反覆的測試。而且軟體組件存在的目的,便是要讓多個開發專案所共同運用。這意謂著,每個軟體組件,都經歷了許多專案現實又殘酷的考驗才能夠生存下來。在這些現實又殘酷的考驗中,這些軟體組件等於是經歷了更為廣泛的實戰測試,存在於其中的軟體瑕疵,多半都已獲得修正。我們可以說,既存的軟體組件,多半都有一定可信賴的品質。重新建造輪子,背後代表的意義,往往是得重新再經歷相似的過程、投入資源及時間(通常佔去最多的並不是開發時間,而是最容易被忽略的測試時間),最後得到一個或許可能比較好的組件。但是這又如何呢?或許重新建造的組件的確優於舊有的組件,它可能更有彈性、更通用、適用範圍更廣、能被更多的專案重覆使用、滿足更為多變的需求,但或許在你未來的系統中,這些優點不見得會被完全的利用,兩相權衡下,不見得可以得到好處,但在當下卻是確切的把生產力給浪費掉了。

既然如此,為什麼程式員們總會受到心魔的引誘,一而再、再而三的將寶貴的開發生產力給浪費掉了呢?尤其我要說,愈是優秀、對自我期許高的程式員、愈是受不了這樣子的誘惑,反而愈是平庸的程式員,愈不容易發生重新建造輪子的問題。

這其中的原因究竟為何呢?不妨讓我細細道來。雖然許多人都說程式員這一行是吃青春飯,但我認為程式設計終究是一個大量倚重經驗以及視野的工作,而不像許多人心中所想像的,體力以及對新技術的熟悉佔去極大的比重。我相信許多程式員都會和我有一樣的感受,每經過一段時日,就會覺得自己又「昇級」了,基於這段日子的經驗積累,視野又大有所不同。而這些「昇級」的動力例如像是學習、體會到了某個設計方法論或是架構的好處。當你「昇級」了之後,再回過頭去檢視自己舊時的作品,反而多半都會抱持著負面的觀感。面對過去的自己,時常會有一種「年少無知」、甚至是「年少輕狂」的感覺,真希望「昨日種種譬如昨日死,今日種種譬如今日生」。剛對設計方法或架構有了更深一層感受的你,對比起來,更明白過去所做的設計,究竟存在那些問題以及缺陷,它可能不夠通用、不夠彈性、也難以擴充。倘若你是個自我期許較高的程式員,免不了難以壓抑心中的衝動,這些問題及缺陷,便有如眼中令人難受的沙子,非得立即除之而後快。所以,對於那些既存但卻又看不順眼的輪子們,會興起再次重新打造的念頭,也就不足為奇了。

可是,人總是持續的在成長,你的能力、視野同樣的隨著時間在不斷的進展,或許輪子的確不夠好,但在某個程度上,它總是足堪使用。但如果只是因為你知道有更好的設計方法或架構,就非得要重新再把這些輪子再做過,無疑的只是陷入無止盡的輪子再造地獄之中,也持續的浪費無所謂的生產力在上頭。你或許有所得,但失去的卻更多。

雖然重造輪子,會帶來生產力的浪費,但這也不完全意謂著我們永遠不會重新改寫既有的軟體組件。有些人剛好和喜歡重造輪子的人形成對比,他們總是不喜歡更動舊有的程式碼(通常稱為legacy code),因為他們深怕更動了舊有的程式碼後,引發副作用。當然,他們更不喜歡改寫既有的軟體組件,因為他們相信「做對的事,何必再改變」。何況,重新改寫更是一件浪費生產力的事情。

但是,這種堅持不重新設計所用軟體組件的想法,卻會引發另一個問題,也就是舊有的組件因為設計可能較為不良的關係,先天缺乏通用性的體質就無法因應新的需要,但你又不願意加以重新設計。這使得你得採取繞路的方式,迂迴的達成目的,把額外的地方加諸在其他的組件或甚至是你的應用系統之上,最後就是疊床架屋,持續的在不穩固的基礎上,繼續的加蓋違章建築。而這種情境,在我們日常的開發生活中,其實也是屢見不鮮、時有所聞。

上述的這兩種立場,看起來就像是在天平的兩端、互相衝突,一邊的優點正好是另一的缺點。這或許令人感到困惑,究竟什麼樣的態度才是正確的態度呢?

我常說,軟體設計之道就是取捨之道,也就是說,不論做什麼設計決策,你都會得到某些東西,但也同時會失去某些東西。而這中間的取捨,端視你所位在的情境以及所面對的目標而定。我們形同要找到一個合適的支點去支撐這有著兩個極端的天平,並且使之平衡。太過頻繁的重新建造輪子固然不對,但總不能在輪子的胎紋都磨平了,還勉強裝上車子並且行車上路吧?這中間存在一個適當的平衡點,而好的設計者,便會考量相關的背景因素,決定這平衡點究竟要設定在那一個位置之上。

對應到建造輪子的問題上,決定了一個好的平衡點,你就不會太過頻繁不斷建造輪子,但也不會總是使用同樣的輪子,你會決定適當的更新週期來汰換不合時宜的輪子,同時滿足新的需要。你在生產力和其他像是通用性之類的指標之間取得了一個好的平衡。

怎麼決定支點在何處,是一門藝術,也是判斷設計者功力高下的所在。

沒有留言: