最近十分流行「砍掉重練」這個詞,我一開始接觸的時間點,約莫是在十幾年前還在玩MUD(Multi User Dimension)的年代。MUD大致和現在的線上遊戲差不多,只不過它是文字模式的線上角色扮演遊戲,所有的場景呈現、人物動作描述,甚至玩家控制人物行為的方法,都是透過文字傳達。

RPG遊戲,免不了有練功升級的過程,玩家必須進行一些角色能力方向的選擇。在過程中,如果做錯了一些決定,就會導致訓練出來的角色,升到最高等級,能力卻不如預期。所以,很多玩家就會忍痛「砍掉重練」。砍掉重練的想法,基本上是出自對現況的不滿,又想追求完美的想法。程式人也是特愛這想法的族群,尤其是那種上進、對自己有期許的程式人。

想要重練的6大原因
這麼多年的軟體開發生涯,我看過太多砍掉重練的例子,當然包括我自己。為什麼會決定把辛苦寫成的程式全數廢掉,重新再打造一個新的呢?據我的觀察,原因大致有下列數種:(一)撰碼風格不佳;(二)過多重複累贅的程式碼;(三)程式架構疊床架屋;(四)架構設計不夠通用;(五)所運用的技術跟不上潮流;(六)有太多隱藏在深處的臭蟲未爆彈。

覺得程式風格不佳,引發想要砍掉重練的念頭,是初期程式人時常會有的症狀。尤其是那種原先不講究撰碼風格(包括程式編排、命名慣例),突然有一天領會到撰碼風格其實很重要,特別容易在體驗到好的程式風格所帶來的益處時,會想把程式全部砍掉重練。

對於有經驗的程式人,這種症狀是偶發的,通常只有在經歷一段較長的時間後,撰碼風格已經改變,而新式與舊式的風格產生不協調的情況才會發作。自律越嚴的程式人,越是難以忍受風格的不一致,於是便會興起重頭練過的念頭。

而過多重複累贅的程式碼,通常是起因於為了縮短時程,直接將程式碼由系統的某處直接抄寫,或抄寫後再小幅度修改,再放到系統的另一處。談到「物件導向程式設計中常見的錯誤」時,我便有提到這是所謂「相似或重複的程式碼(Duplicated Code)」的問題。

這個問題多半是因為貪圖一時之快,未能保持時時重構(Refactoring)的態度,相似或重複的程式碼,又會在系統中漫延。如果對後果一無所知,倒也不打緊,若是對可能引發的問題十分清楚,發現問題病入膏肓,又不是一時三刻地重構可以解決,就很有可能會想重新來過。

程式架構疊床架屋,是許多系統隨著時間及需求不斷調整,時常會造成的問題。這種情況在所難免,因為對系統需求的預測,本來就很難在初次分析之際,就通盤掌握,在開發過程甚至上線後,許多需求才會一一發掘。

但如果原先架構設計的方向和新需求不符,又沒有在納入新需求時,以漸進的方式調整架構,便很容易造成在不夠穩固的基礎上持續添磚加瓦,最後蓋出一棟危樓。

架構不夠通用,和「程式架構疊床架屋」相關。會查覺架構設計不夠通用,就是因為開發端陸續接收到新的需求,或者變更的請求,卻發現系統現行的設計,不容易滿足。倘若勉強為之,就得繼續蓋上去。為了徹底解決問題,程式人會想把重要的架構元件整個改頭換面,以根絕問題。

至於「所運用的技術跟不上潮流」,更是觸動喜歡吸收科技新知的程式人想要砍掉重練的常見原因。例如,原先使用EJB(Enterprise JavaBean)的技術,但在Hibernate之類的技術出現之後,發現它具有諸般好處,於是既有的系統,頓時處處看起來不順眼。所以,「技術更新狂熱者」時常會為此耗費大量的時間,努力保持所用的技術能夠處於最新的潮流之上。

最後一個原因,是系統有太多隱藏在深處的臭蟲未爆彈。若是系統在正式產品化或上線之後,仍然在不確定的情況下,時有惱人的臭蟲發生。因為系統規模頗為龐大,要從中挖掘臭蟲,實在難上加難。想要程式人明知這個問題卻不期待重寫,真的不容易。

砍掉重練未必是正確的心態
從開發生產力的角度來看,「砍掉重練」是不正確的態度。既有的程式碼有時看來是負擔,但其實這些程式碼都是花費程式人的心力撰寫、測試人員測試、再修正錯誤而得的。

重寫等於程式碼的投資幾乎都付諸流水,這不僅意謂著程式得全新重寫,而且還得重新測試與修正。事實上,重寫未必在過程中保證能降低太多錯誤發生的機會。

事實上,發生臭蟲的比例應該還是差不多。而舊有程式碼存在的最大價值,便是在於這些程式碼是經過某種程度的測試,具備相當的品質。測試及修正程式碼的成本,時常是撰寫程式碼的數倍,而放棄相對穩定的舊程式碼,所付出的代價可說是相當沉重。

為了求好心切,一點也不划算
其他如「撰碼風格不佳」及「過多重複累贅的程式碼」而想砍掉重練的理由,都是利用重構技巧可以解決的問題。基本上,對舊有程式碼的健康觀念,應該是漸進且持續地導正。

企圖全面翻新,不代表現存的問題一定可以解決。全面翻新最常發生的事,是舊問題仍然上演。何況,每個人的功力總是隨著時間精進,越是處於進步狀態的程式人,每隔一段時間,就會對過去的所撰寫的程式碼不滿意,這卻無疑是優秀程式人的一大心魔。

優秀的程式人,會盡力想維持作品的完美性,但為了形式的完美,卻又以生產力為代價,從工程的角度來看,實在一點也不划算。可用的程式碼,比漂亮的程式碼來得實際、可靠多了。

為了求新求變,好處常常微乎其微
此外,像架構設計不夠通用這樣的問題,倘若真的是架構不夠通用,那麼就很有可能靠重構也無法解決。因為倘若在系統發展到某個階段後,才發現需要更通用的架構,單是從架構上著手重構,要修正的幅度可能很大,不見得可行。

這時候,砍掉重練似乎成了比較合理的選項。但是,很多時候,需要「更通用的架構」的需求,並沒有被確切地檢驗。可能只是「過度工程化(Over-Engineering)」的心理做祟。某些時候,還沒有面臨到的確需要更通用的架構,就提前動手重新打造,反而不理想。

至於「技術更新狂熱者」喜歡運用新技術,更是浪費生產力的想法。一來,新技術未必成熟,運用時所遭遇的問題,也許因為你是全世界第一個碰到的,沒有人能夠幫忙,耗去的時間恐怕更多。

二來,新技術不代表是符合需求的技術,任何一種技術只要能符合需求,就是可以用的技術。新的技術一定已瞄準它想要解決的問題,但是舊的技術大多數時候同樣能夠滿足現有的需求。純粹基於升級或嚐鮮的想法而砍掉重練,是對生產力的一大傷害,最後獲得的好處又常常微乎其微。

權衡成本,評估重練的價值
最後,如果系統中有太多隱藏的臭蟲,又缺乏耐心或時間一一找出來,衡量得失厲害,還是需要在適當的時間點(例如產品的大改版或重大的里程碑),重新開發重要的元件。

砍掉重練並非完全不行,只是因為它會犧牲生產力,所以只有在犧牲的生產力和時間評估起來划算時,才值得這麼做。否則,利用重構技巧導正系統,會是比較合理的態度。

作者簡介:
王建興
清華大學資訊工程系的博士研究生,研究興趣包括電腦網路、點對點網路、分散式網路管理、以及行動式代理人,專長則是Internet應用系統的開發。曾參與過的開發專案性質十分廣泛而且不同,從ERP、PC Game到P2P網路電話都在他的涉獵範圍之內。

熱門新聞

Advertisement