想像一下,你奉命要為某個祖傳系統(Legacy System)增加功能匯入新單位資料,追到資料庫卻見到以下畫面。憤怒指數從 1 到 10,你給幾分?

追進程式,你發現每個函數內容幾乎一模一樣,只差在 WHERE OrgId = 'nnnn' 中的單位代碼,憤怒指數又會到幾分?

thumbnail

年輕的我,會判定此舉是對神聖開發工作的褻瀆,天地難容,雖遠必誅!

如今在這個領域打滾多年滾到頭髮都白了,學會用不同角度看待這個結果,則有不一樣的想法。依每個人的背景歷練,甚至人生不同階段反應都不同。

以我自己為例,在職涯的各階段看到上面的程式碼,反應都不同。

哇,好整齊好壯觀

我非本科系出身,學生時代沒受過正統軟體開發訓練,踏入職場開始靠 Coding 吃飯純屬因緣巧合,當年沒學長帶沒前輩教直上一夫當關模式,接專案全憑之前 Coding For Fun 經驗自由發揮,以能動會跑可結案收尾款為目標,胡搞瞎搞竟也做完好幾個案子。(參考:黑歷史 - 我的 SQL Injection 首部曲)

那時從不覺得 Copy & Paste 有什麼不對,看到成排的 Function 可能只會讚嘆好整齊好壯觀,沒特別感覺。

花惹發! 誰寫的?給我出來

再寫了幾年程式,逐漸能體會程式架構不好技術債台築的痛苦,心態漸漸轉變。知道要看書找資料,積極學習系統設計技巧,一心嚮往美妙的系統架構。吃過複製貼上的苦頭,便熱衷於歸納共用邏輯、寫元件、寫模組、寫框架,全力減少重複性工作,追求只改一處一勞永逸的境界。這個時期的我進入「憤青」階段,看到重複程式碼就歸藍波火義憤填膺,尤其文章開頭那種複製碼大軍,絕對怒火中燒,花惹發不絕,甚至會馬上動手修改、重寫(那時還不知這有個專有名詞叫「重構」(Refactoring))。這時的我,看到別人的系統用過時沒效率的方法運行會心生鄙夷,心想你們真沒魄力,怎麼不乾脆砍掉重練一次把事情做好?改革創新帶來很多成就感,一方面源自初生之犢不畏虎,沒想太多把系統弄壞的風險,總想像自己像超級英雄,正將世界推回正軌。

話說:但如果工作換得夠勤,我相信真有人寫了多年程式沒體驗過 Copy & Paste 遺毒,每次程式寫完(甚至還沒寫完)便拍拍屁股換工作換專案,爛攤子都是別人收,至今仍以為「一時 Copy 一時爽,一直 Copy 一直爽」。

哦,是程式債

又過了十幾年,見過聽過經歷過更多職場故事,對於「做事 vs 做人」、「技術 vs 政治」有深一層體會,學會用另一個角度看世界,看事情也多了寬容。所謂世故圓滑,多少也夾雜鄉愿。聽過可歌可泣的悲壯故事,內心開始接受「If it works, dont' touch it」這種迂腐卻能永安保康的思維;看多壯烈成仁的改革者,知道系統架構決策除了技術角度,也常需考量政治、人性才會成功,徒有滿腔熱血,有時會淪為被五馬分屍的商鞅。

現在的我,追求精巧簡約設計的心沒變,但不再追求一次到位,會衡量時勢利弊風險,抱持「推進一點也算得分」的心態,想著有朝目標前進一點,總好過停滯不前,對人類加減有貢獻。而看見糟糕的程式或奇怪的設計,第一反應不再是批評,而是試著想像作者的時空背景,可能的決策理由,設法為其辯護:

  • 有人曾提議要改,但因修改者人微言輕,學長、主管不允許,還嗆他沒聽過「If it works, don't touch it」?
  • 用複製貼上大法,修改只要需求單位驗收;若重構改寫會異動到全系統,需發動大規模複測,主管會支持嗎?

依據所處的職位高度,讓重構成行的難度可能是史萊姆,也可能是大魔王。如果你的職位夠高或公司夠小,有權決定投入工時多寡,也有本事請相關單位配合測試驗收以完成某個"使用者無感但開發者會鬆一口氣"的系統調整,若這樣還不重構,天地不容;如果你是報到未滿一年的菜鳥,兩個抉擇在眼前:一個是一小時無風險解決小問題,但再累積一點技術債;一個則是要說服長官,通知二十個相關單位重新測試,扛下修一個小問題搞壞十個系統的風險。你是否有雖千萬人吾往矣的勇氣?現在想想,只有當年憤青時期的我有勇氣說,Yes,I DO。

改,真的需要勇氣,來面對壓力質疑

在使用者及決策者的眼中,「穩定、堪用但難維護」永遠好過「好維護但有故障風險」(反正又不是他維護),解決技術債的受益者是開發人員,要獲得認可常需要天時地利人和。

依我多年的體悟,系統運作得愈久,就愈沒人敢改。跑了 N 年的 Copy & Paste,之後擴充多半會依循既有模式繼續 Copy & Paste,直到某次契機,系統要改版、翻新重測,或是有個藝高人膽大的勇者又得到長官支持,才有機會重構成功。

所以,看到壯觀的複製碼大軍,真要怪罪,最不能原諒的是 Copy 成第二份第三份的人,他擁有最好的機會用最小成本撥亂反正,站在走向光明或是向下沈淪的叉路口,卻做了錯誤選擇;第二號戰犯則是寫第一份的人,沒多預留未來擴充的可能,讓可變因子參數化。但這部分要看情況,或許那個當下無法想像應該是常數的值居然會改,硬拉成變數反而是 Over Design,應變進化原本就是重構才要做的事,說起來 Copy 第二第三份的人責無旁貸。

回到最早的問題,看到複製程式碼大軍,你的反應是什麼?


Comments

# by Phoenix

我覺得第一份的人是無罪的,用最小的成本完成需求應該是對的, 第三份的絕對是戰犯XD

# by Whisley

也不至於啦,實做第三份的人通常會只會收到:「新單位去加一下,嗄?加個單位要兩天? 之前只要半小時,你會不會寫扣啊?」

# by Toolman

我覺得技術債真的就是債,就像公司想營運可能要借錢周轉,想搶市占就不得不做出能動就好的程式 可是當技術債埋到一個極限後,系統就會變得改不動,業務邏輯不能擴充 一擴充就邏輯不一致,發生營運問題,最後新功能停用,程式退版 然後退版還可能因為兼容沒做好,再發生營運問題 技術債的本質,我覺得就是向未來借些什麼,有借有還再借不難 但若都不還,最後就是只能全部砍掉重來,全部清算 那到時就要看公司還有沒有底氣能夠繼續借技術債 或者有夠多的時間重新打造系統了 😂(一整個惡性循環阿 其實看到公司的程式有複製程式碼大軍、技術債 如果系統還可以繼續沿用好幾年,那大概就是沒事 但如果商業環境變化,導致需要大改動,又不能打掉重來 那可能還是換公司快逃比較好 XD 太老舊的邏輯沒人說得清,要重做連商業邏輯都不好釐清 要沿用改造,牽一髮動全身,一整個 deadlock 阿

# by Huang

賺時間薪水的PG,程式碼花時間重構,薪水反而還會變高。這樣技術債還算是債嗎?bug同理,點bug成金啊~哈哈~

# by Huang

重構不為什麼,只為職業道德

# by cash

我想到這本書 Working Effectively with Legacy Code

# by ByTim

剛進公司那一年,我就是這樣Copy &調整。 現在五年了,只要看到就會把它合併起來,PK要是自動編號就麻煩點。

# by 樂透無名

真是 一把辛酸淚 心有77菸 (合十)

# by acess

當下的人、事、物、時空環境、目標條件(或壓力)都有可能造成這樣的現象, 個人也當過憤青,但經歷過一些案子之後,就比較能放下或寬容, 有看過COPY & PAST寫死的寫法、也有看過很酷炫、炫耀般但後面接手的人不好維護的寫法, 能遇到的好的架構、好的寫作習慣,是可遇不可求。 所以,就放下吧,說不定在當時候的高壓狀態下,也不見得會做得更好。

# by wellxion

我個人經驗是大家都有可能挖洞給自己或別人跳就是, 在時間壓力和需求規模的多方權衡考量下難免會這樣做, 雖然更多時候可能是沒注意到或不在意, 像上述例子那樣乾淨明瞭還真的是難得一見。 XDD 不過只是COPY & PASTE的確滿惱人的, 尤其後面的人不會去注意就只改了一部份位置, 然後等你接手在確認時就會覺得各種疑惑, 是為了部分情境特例還是單純修正問題沒同步到。

# by Tank

案子剛展開通常規模很小 大概也不會花很多錢請PG 搞不好第二人薪水只有25K 那用COPY PASTE也是剛好 能動就該偷笑了 說到程式債 PCHOME介面多年沒有動過 該不會......

# by Austin

我這裡有一個非常糟糕的重構案例,公司有一祖傳API交給了一批新人來重構,當然新人們看到了雜亂無章,單method就有上千行的程式,肯定是先嗤之以鼻,批評的體無完膚,所以一行程式碼都沒看,直接從了解需求開始打掉重練,搞了個把月總算完成了,結果整套API的介面全改了,完全不向下相容,導致使用的人也必須全部跟著修改,先不說產生的bug有多少,光執行效率就比原本的慢了數十倍,前人碰過的坑一個都沒少踩,所以開發完成了數個月沒一個單位敢替換° 因此我認為祖傳代碼別看他其貌不揚,能支撐這麼久的時間,肯定有他過人之處,重構前要保持敬畏的心,仔仔細細把代碼都看清除,完全了解了他的架構及邏輯才能開始修改它

Post a comment