
古希臘神話裡,宙斯決定降下一場大洪水,毀滅青銅時代的人類。
還好普羅米修斯事先知道這件事,趕緊去提醒自己的兒子杜卡利翁,杜卡利翁聽完也沒什麼時間了,他先造好一只大木箱、準備糧食,再和妻子皮拉一起躲進去。
後來洪水真的來了,兩個人就在水上漂啊漂,整整漂了九天九夜,最後才停在帕納塞斯山。
如果杜卡利翁等到水淹進家裡,才打開 YouTube 搜尋「零基礎木箱製作教學」,大概是來不及了 XD,他們能活下來,是因為在洪水來之前,未雨綢繆。
剛出社會的前幾年,意氣風發,看隔壁學長姐改個小東西要兩三天,心裡就在想:
「是不是在偷懶?」
直到後來才發現以前想得實在太簡單,真的寫 code 的時間,也許不到幾個小時,那其他時間到底跑去哪了?
理解時間: 需求說要改這個按鈕的流程,我們總不能就直接改吧?得先搞清楚它按下去會經過哪些 流程、呼叫哪些服務,本來還以為只是前端一個小調整,code 打開後一路往後追,半天、甚至一天就沒了。
等待時間: 好不容易看懂了,寫完 code、本地測完、commit,部署,接著去測試環境手動走一次完整流程,終於覺得沒問題,老大又走過來說:
「出現三個 Bug 了」
好,那就回頭修、重新部署、重新登入、再跑一次,這樣來回兩天,好不容易交出去,幾天後又冒出新的 Bug,「有完沒完啊!」。
理解時間不可能完全消失,畢竟不看懂就亂改,通常只會得到更多工作,不過等待時間不太一樣,它很折磨人,卻也是我們比較有機會改善的地方。
在我們以前,本機開發完後,部署還需要做測試,日常就大概長這樣:
快一點 10 分鐘而已,好像還好對吧?
問題是這個流程不會只做一次,改一次程式跑一次,一個下午跑個幾次,回過神來天都下班了
「看來今天又要加班了...」
因為每次驗證的成本都很貴,我們還會忍不住想:
「反正等等都要重跑,不如多改幾個地方再一起測。」
這下好了,一次變動太大,出現的錯誤好像更多了...
所以我們現在知道除了時間大多都耗在部署跟驗證,先來説説部署,我們會先在自己的本地做編譯,遠端桌面連進伺服器,停掉 IIS 站台,把舊檔先備份起來,再把新版本複製過去。
整套流程最重要的注意事項:
「正式環境的 config 不要蓋掉喔。」
如果站台起不來,可能是路徑不同、漏傳一支 dll,也可能測試環境驗證的是 A,手上準備上線的其實是 B,修完再傳、再啟動、再跟 QA 約時間手測。
複製貼上不是什麼十惡不赦的事情,麻煩的是整套部署方法都放在某個人的腦袋裡,今天要傳哪些檔案?哪一份才是正確版本?出事要換回哪一個壓縮檔?通常只有坐在遠端桌面前、手心正在冒汗的那個人知道,重點是團隊成員稍有不謹慎,把 config 或某些資源覆蓋掉,又剛好沒有備份,那通常就很難搞了...
之前遇過很刺激的事情,某個客戶急著要我們 hotfix,但同一套系統還有其他客戶在用,直接更新正式版本,等於叫其他客戶一起上車,所以我們之前通常遇到這樣的情境下都有同的理念:
「這個客戶今天一定要修好,但其他客戶先不要動喔。」
當時的辦法,是在 IIS 另外開一個站台,放上修正後的版本,再給客戶一組臨時網址,原本正式站台先不動,其他客戶至少不會馬上受到影響。
當下看起來解掉了,但我們如果有多個站台一旦同時活著,新的問題就來了:哪個版本要繼續維護?設定有沒有一致?hotfix 之後怎麼合併回去?什麼時候要合併?臨時站台又要哪一天關?誰要記得這些事情?
如果流程團隊不知道,只靠某個人記著,那事情就大條了,更別提有些 hotfix 是把計算邏輯給換掉,但是資料庫還是同一個的。
現在回頭看,其實我們當時已經有「不要讓所有客戶一次承擔風險」的直覺,只是手上沒有成熟的方法,只能每次都靠人臨場反應。
部署完其實只是上半場,更麻煩的是驗證,改完一段 code,我們沒有別的辦法能快速的知道它到底對不對,只能在本地開瀏覽器、登入、一路點到那一頁,按下剛改完的按鈕,再開 F12 看有沒有噴錯,最後翻進 DB 確認資料有沒有寫對,偏偏系統效能又差,光等畫面跑完就要好幾分鐘,一個下午就這樣來回幾次。
更別說環境問題了:
「我本地明明就過了啊?」
本地用的是自己隨手準備的一小筆資料,測試環境卻是另一份長得完全不一樣的舊資料,於是本地沒問題、測試環境問題一堆,光是要湊出一組能重現問題的資料,就又得花掉很多時間。
而漏測一條路徑,通常不會當場就發現問題,而是等上線幾天後,客戶打電話進來才知道。
現在回頭看,我們當時不是不認真驗證,反而每個人都測得滿頭大汗,只是驗證全靠人工回饋跟臨場記憶,測過的東西留不下來,下次一改動,整組又得重新再驗證一次。
並不是說端到端測試不用做,還是得要做的,但是我們當然希望最好的情況是盡量不要做這麼多次,最好能在更前面的階段就提供「快速回饋」機制了,很幸運的,在前八天我們就學到了其中幾個。
我們有聽過「自動化」嗎?當然有,書上寫過、講師講過、Conf 上也看人家秀過,但我們自己根本沒試過啊!
DevOps 的理念跟相關工具,又不是最近才突然從地上長出來的,可是聽過跟真的把它們接進每天工作的流程,就完全是兩回事。
為什麼沒有做?我們要指責工程師很簡單,但現實是在會議上很難展示這些需要時間發酵的東西,花時間補測試或流程,我們不能指望老闆會給我們這些時間,系統每天都在跑,誰先動誰就得先扛那個風險。
做了不一定有人看到,做壞了倒是全公司都知道。
⋯⋯還有一個最常見的:

圖片擷取自網路
反正報錯了會有一堆人通知我,頂多被罵,畢竟不犯錯也不會加薪...當整個環境是這樣,好像也沒那麼讓人意外了。
說到這裡,請允許我 show off,雖然這些東西都在我的一意孤行下導入公司,但我實在不想把它講成什麼英雄故事,因為那會完全誤導人,因為我的動機就完全是:
「我好痛苦啊!!!」
以前沒人導入,不是因為同事笨,每天光把需求做完就很累了,痛苦救了也就麻木了,麻木久了甚至就覺得這就是工作本來的樣子,在這種氣氛下先動手的人,扛的不只是技術風險,甚至可能招謾罵:
「你為什麼要沒事找事?」
至於我,除了對於軟工的熱忱之外,運氣也很重要,今天如果換做是一個更緊繃的團隊、一個完全不給空間的主管,甚至是會搞小動作的,都自身難保了,哪敢推什麼?
所以這件事真的跟聰不聰明沒什麼關係,比較是風氣、時機和難處剛好湊在一起,不過這並不能成為阻礙我們精進學習的理由。
環境確實會限制我們,但它不會替我們規劃整段職涯,機會是留給準備好的人。
講到這類話題,就很容易被同事白眼:
「你很閒是不是?我加班加的要死,你還有那麼多時間搞這些?」
是否超有既視感的?但先等等,容我娓娓道來。
我們當然不能期望公司會覺得可以有更好的流程從中受益,就應該提供合理的學習、重構和改善流程的時間,所以我們必須要有一個觀念:
「品質通常會是從自己最基本應該要付起的責任」
差別在於報酬歸誰,今晚花一小時,弄懂怎麼替一段 Legacy Code 補上測試,這個能力不會只留在公司,它會跟著我們走,下一個需求用得到,換一個專案用得到,哪天離開這間公司,它還是用得到。
而且這筆投資的回報,常常會直接回饋到工作上,以前改一個地方要手動點二十分鐘確認,某個晚上我們花一點時間把那段邏輯拉進測試,之後每次改動就可以秒確認,以前每次上線前都提心吊膽的,那是不是我們每天下班後花個幾個小時把 DevOps 給學的更充實,做這些都還不是讓我們白天上班不會這麼不開心嗎?那我們上班開心了,下班不就有更多時間再學更多東西,上班就能再更開心?老闆看你那麼有效率,又替公司導入這麼多好東西,還不幫你加薪?
當然,軟工這條路是條不歸路,真的累到不行的晚上,最划算的選擇往往就是先去睡,重點從來不是今晚拚了多少,而是這樣的節奏,能不能讓我們幾個月、幾年後還走得下去。
Max Verstappen 曾連續四年拿下 F1 世界冠軍,但車手再厲害,也沒辦法只靠技術把車輛競爭力的差距全部打破。
所以,不是我們笨,是我們還沒有工具。
寫程式也是一樣,我們在前八天所學到的,看完不會立刻變成肌肉記憶,還是得平常做練習,做好準備時,等需求和 Bug 哪天進來時,我們可能就會在哪一天靈光一閃就突然拿出來用。
有些東西,我們確實可以先放進木箱裡,像是讀過的書、練過的每個 Kata、知道可以這樣用但是實務上還沒有用到的技術等,等哪天我們遇到真的很難處理,完全沒有頭緒,學長姐都已經離職的時候,我們會慶幸有這些物資在木箱當中。
如果前面九天學的是「不要讓事情更糟」,那接下來就一起看看「可不可以讓事情變的更好」。
明天我們繼續看:在 Legacy Code 中,TDD 的變奏。
Continuous Integration,Martin Fowler
Deployment Pipeline,Martin Fowler