我最近在想,如果能回到二十年前,跟那個剛入行、滿腔熱血但天真到不行的自己說幾句話,我會說什麼?
那時候的我,跟現在很多剛踏入這行的新手工程師一樣,覺得寫越多 code、用越新的技術,就代表自己越厲害。半夜還在盯著 production server 的 log,一邊喝著咖啡,一邊覺得自己真是為技術獻身,超帥的。現在回頭看,只覺得...嗯,年輕真好。
這不是你在什麼速成班或技術部落格會看到的文章。那些地方教你的是「怎麼做」,但很少人會告訴你「為什麼」,以及在那些光鮮亮麗的「最佳實踐」背後,藏了多少血淚跟不得不做的權衡。所以,這篇算是我自己的一些...嗯,老實說,就是一些踩坑踩了十幾年後,才慢慢搞懂的事吧。
先說結論:重點不是你會什麼,而是你懂「何時」該用什麼
我自己是覺得,從 Junior 往 Senior 走的路上,最大的差別不是你會的工具變多了,而是你腦袋裡的「判斷力」。你知道什麼時候該用大砲打小鳥(然後被罵浪費資源),什麼時候該用一把瑞士刀解決所有問題(然後祈禱它不要半路壞掉)。這是一種...權衡的藝術,而且沒有標準答案。
規模,才是決定一切的殘酷現實
剛開始寫 code 的時候,真的,我以為每個專案都要能應付百萬人同時上線。為了做一個可能只有我媽跟三個大學同學會用的 App,花了幾個月去搞什麼微服務、K8s...結果專案根本沒上線就死了。超蠢的。
老實說,如果你的服務只有十幾個人在用,一台最陽春的主機配個簡單的 REST API,絕對夠用。真的,不要想太多。太多專案不是死在功能不夠好,是死在為了那根本不存在的「千萬流量」而過度設計,活活把自己搞死。
但有趣的地方來了。當你的服務真的...真的有一天,每日請求衝到一千萬次的時候(相信我,這絕對是個幸福的煩惱),整個世界都不一樣了。你會在凌晨三點被叫起來,因為你那台可憐的小主機終於掛了,然後你才開始Google什麼是「負載平衡」。你會發現「自動擴展 (Autoscaling)」不是一個潮到出水的 buzzword,而是你晚上能不能好好睡覺的關鍵。
重點不是要你一開始就懂所有東西。沒人是神。重點是,你要能意識到「欸,好像不太夠用了」,然後知道該往哪個方向去學習、去升級。這才是成長。
當「一個人」變成「一個團隊」
我還記得我第一份工作,基本上就是個一人開發團隊。超爽的。什麼自動化測試、CI/CD,我都覺得是多餘的。東西壞了?我馬上知道要去哪裡修,因為整坨 code 都是我上禮拜才寫的。
然後我加入了一個十幾個開發者的團隊,每天都有人 push code...然後一切就崩潰了。真的不誇張。我們的 codebase 變成一場恐怖的疊疊樂遊戲,尤其到了禮拜五下午,根本沒人敢點 deploy 按鈕。我們是在好幾次不小心把開發到一半的功能直接推上 production 的慘劇後,才學到「功能旗標 (Feature Flags)」有多重要。
這聽起來很 humbling...呃,就是很讓人洩氣但又很真實的真相是:那些你一個人寫 code 時覺得「超麻煩」、「沒必要」的規範,在團隊裡,全都會變成救命符。
下面這個表,大概可以說明這種心態的轉變。我自己看了都覺得好笑。
| 開發習慣 | 單打獨鬥時的想法 | 進入團隊後的現實 |
|---|---|---|
| 程式碼註解 | 寫啥註解?變數名稱我看得懂就好啦。反正過幾天就忘了,到時候再回來看 code 就好。 | 拜託你寫一下註解好嗎!這段 `doMagic()` 到底是對哪個世界的魔法?你休假了我要怎麼通靈? |
| 測試 | `console.log()` 就是我最好的朋友。手動點一點,看起來沒壞就好。自動測試?浪費時間。 | 沒有自動化測試的 PR 根本不該被 review。你怎麼保證你改的東西沒弄壞其他人的功能?這是信任問題! |
| Git Commit 訊息 | `fix bug`, `update`, `wip`... 夠清楚了吧?不然還能怎樣。 | `feat(auth): add google SSO login` ... 拜託照規範寫。不然出事了誰知道哪個 commit 開始壞掉的? |
| 環境設定 | 「在我電腦上可以跑啊!」這句話理直氣壯。管你去死,反正我這邊是好的。 | 用 Docker 把環境包起來是基本禮貌好嗎?我不想花半天時間處理你電腦可以、我電腦不行的鳥事。 |
當「在我電腦上可以跑」變成一句髒話
這真的不是開玩笑的。「It works on my machine」這句話,大概是軟體工程界的「我發誓我交作業了」—— 可能是真的,但對解決問題一點幫助都沒有。
自己一個人玩的時候,開發環境亂七八糟就算了。但在團隊裡,一個可以重現的、一致的開發環境,不是「有很好」,而是「沒有就不行」。我真的浪費過太多生命在處理那種「只有在某某人的 Mac 上,用 node v14.7.2 才會出現」的鬼問題。現在我會把開發環境的設定,當作一個正式的工程問題來處理,而不是隨便弄弄就好。
技術債:帳單總有一天會寄來
我知道,有時候為了趕死線,你真的得寫一些又快又髒的 code。這很正常,沒什麼好羞恥的。我自己也常幹這種事。
聰明的做法是,你要很誠實地告訴自己(和你的團隊):「我現在在走捷徑」。我會留下很多麵包屑,例如用 `// TODO: 這段是暫時的解法,之後要重構成...` 這樣的註解,或是在 Jira/Trello 上開一張票,標記為「技術債」。
問題是當這些「暫時的解法」變成了「永久的設施」。我看過太多五年前為了解決一個小問題而寫的 quick fix,五年後還在 production 環境的核心部分運作,像個定時炸彈一樣,靠著數位膠帶跟工程師的祈禱在硬撐。
說到技術債,我覺得像 Martin Fowler 這些大神常常把它講得很高深,像是在討論什麼建築學理論。但在台灣的快節奏環境下,老實說,老闆或 PM 哪管你那麼多,他們通常只問「這個功能禮拜五能上線嗎?」。這種文化差異,就讓「償還技術債」這件事變得更困難。你得學會怎麼跟非技術人員解釋,為什麼現在花兩天時間重構,可以省下未來兩個月的維護地獄。
所以,到底什麼才是「軟體工程」?
搞了快二十年,我慢慢覺得,軟體工程的核心其實不是「建造東西」。
它的核心是「在資訊不完整的狀況下,做出好的決定」。
是知道什麼時候「不要」做某個功能,即使做起來會很好玩。是願意刪掉自己寫得很漂亮、但已經沒有用的 code。是在你永遠無法擁有所有你想要的數據時,依然要去平衡各種鳥事、做出取捨。
我見過最厲害的工程師,他們不只是 code 寫得快。他們打造的,是讓其他人也能在上面快速又安全地開發的「系統」和「基礎」。他們創造的地基,是讓整個團隊的生產力都提高,而不只是他們自己。
然後,他們也知道何時該打破自己訂下的規則。上面我講的每一條建議,都有例外。而學會辨識那些例外,大概就是資深和資淺工程師最大的差別。
所以,給所有還在新手村掙扎的你:擁抱混亂吧,從錯誤中學習。你現在崇拜的每一個大神,都曾經跟你一樣,坐在完全相同的位置,可能還犯下跟你一樣、甚至更蠢的錯。
好消息是,隨著你等級提升,你犯的錯會越來越有趣。
輪到你了
看完這些,你覺得自己踩過最大的坑是哪個?或是有沒有什麼課本上學不到、讓你印象深刻的「血淚教訓」是我沒提到的?在下面留言分享一下吧,讓後進們少走點冤枉路。
