今年的九月對我來說是一個滿特別的月份,因為加入新的工作環境,我開始接觸一套自己並不熟悉的系統;雖然 C#、ASP.NET、SQL、Web API 這些技術本身並不陌生,但真正需要花時間的,其實不是重新學習這些技術,而是要在有限的時間裡,快速理解一個已經運作中的系統。
回頭看這一個月,做的事情其實滿分散的:分析系統架構與流程、整理文件、研究程式碼效能和雲端成本、進行壓力測試、SQL 移轉 Stored Procedure、補上參數驗證與一致性測試,以及研究 Stored Procedure 的版本控管與 CI/CD;如果單獨看每一件事情,好像彼此之間沒有太大的關係,但把它們串起來之後,這些工作都在做同一件事情:讓自己盡快建立起對這套系統的完整理解,從一個剛加入團隊、還在摸索系統的人,慢慢變成一個可以開始參與改善的人。
剛開始接觸系統時,我花了不少時間去追 API 的執行流程,從 Web API 的入口一路往下看,理解不同 Layer 之間的關係,以及商業邏輯、資料存取和資料庫之間是怎麼串起來的,這個過程也讓我再次感受到,「看懂程式碼」和「理解一個系統」其實是兩件不同的事情;單純知道某個 Method 做什麼,並不代表知道它為什麼會這樣設計,也不代表知道它和其他功能之間有什麼關係,所以這次我比較在意的,不只是把單一功能看懂,而是試著建立整個系統的心智模型:資料從哪裡進來、經過哪些處理、最後流向哪裡,以及不同元件之間是怎麼互相影響的。
在這個過程中,我也開始整理系統架構與流程文件,對我來說文件不只是提供給其他人看的東西,也是一種驗證自己理解是否正確的方法;當我必須把一個複雜的流程整理成可以說明的架構時,往往也會發現自己其實還有一些地方沒有真正理解,也因此這個過程並不是單純把程式碼看過一遍,而是透過整理和描述,把原本零散的資訊慢慢組合成比較完整的系統觀。
從程式碼往外看,開始理解系統的另一面
當對系統有了基本理解之後,我開始關注的不再只是「這段程式碼能不能正常運作」,而是它實際執行時會產生什麼影響,某些程式碼的執行效率會影響 CPU、Memory、Database、I/O 或 Network 的資源使用,而當系統運行在 Cloud 環境時,這些資源消耗最後也可能反映在雲端成本上;這讓我開始用不同的角度看程式碼:如果這段程式碼的執行效率不好,在系統規模變大之後會發生什麼?如果 Request 數量增加,資源消耗會怎麼變化?這些變化最後又會不會轉化成實際的營運成本?
也就是在這個階段,我開始把原本比較單純的「程式碼 → 功能」,慢慢延伸成「程式碼 → 執行效率 → 資源消耗 → 系統運作 → 雲端成本」;這種思考方式和單純看程式碼本身不太一樣,因為開始需要把 Application、Database 和 Infrastructure 放在同一個脈絡裡看。
除了分析程式碼和架構之外,這個月也開始接觸壓力測試,這對我來說也是一個滿有意思的轉變,因為在看程式碼時,我們很容易根據邏輯去推測系統應該會怎麼運作,但真正把系統放到一定的負載下之後,才會知道原本的假設是不是成立;透過壓力測試,我開始關注 Response Time、Throughput、Concurrency、Resource Utilization,以及系統在高負載下的行為:哪些地方會成為 Bottleneck?當同時處理的 Request 增加之後,哪一層會先出現問題?資源使用量和效能之間又是什麼關係?
這也讓我更加確定,寫出一個「可以正常運作」的系統,和真正知道它「在壓力下會怎麼運作」,是兩件不同的事情;前者比較像是確認功能正確,後者則開始涉及系統實際運作時的行為,而這也是我以前比較少從這個角度去思考的事情。
從 SQL Migration 開始,看見更多工程問題
這個月另一個比較有感的工作,是把原本由應用程式組合 SQL Command 的方式,逐步移轉到 Stored Procedure;一開始看起來只是一個 SQL Migration,但實際做下去之後,很快就會牽涉到更多問題:原本的行為能不能完整保留?Parameter 要怎麼處理?缺少 Parameter 時應該怎麼驗證?修改之後又要怎麼確定新舊實作的結果一致?
所以我也開始補上 Parameter Validation 與 Parity Test,透過不同的資料分布與情境去比較原本的 SQL 實作和新的 Stored Procedure 是否維持相同的行為,做到這裡我開始發現一件事情:真正的工程問題,很少會只停留在「把程式改掉」這一層;當 Stored Procedure 被正式納入系統之後,又會自然延伸到另一個問題:這些 Database Object 要怎麼做版本控管?要不要放進 Repository?Production Deployment 要怎麼管理?能不能透過 CI/CD 自動化?
因此,我也開始研究 Stored Procedure 的版本控管,以及 Repository 搭配 CI/CD 管理 Database Changes 的方式,從一開始的 SQL Migration,最後一路延伸到 Testing、Version Control、Deployment 和 CI/CD;這也讓我重新感受到,Software Engineering 很多時候不是把一個問題解掉就結束,而是解完之後,很自然會看到下一層的問題。
如果把這個月做過的事情全部串起來,其實會發現它們之間有一條滿明顯的脈絡;先理解系統架構與流程,再去看程式碼的執行方式;從執行方式延伸到效能,再從效能看到資源消耗與雲端成本;接著透過壓力測試驗證系統在實際負載下的行為;另一方面,從 SQL Migration 開始思考資料存取方式,再往下延伸到測試、版本控管、Deployment 與 CI/CD;這些事情看起來各自獨立,但其實都在幫助我回答同一個問題:這套系統到底是怎麼運作的,以及如果我要修改它,會帶來什麼影響。
從熟悉技術,到開始理解完整系統
也因為這樣,我發現自己開始關心的東西變多了,以前面對一個問題,我可能會先想:「這段程式碼要怎麼改?」現在比較容易先想的是:「為什麼它會變成現在這個樣子?」如果我改了這裡,整個系統會發生什麼事情?這個地方會不會成為效能瓶頸?當負載增加之後,它還能不能維持現在的行為?如果系統規模繼續成長,這樣的實作會不會增加營運成本?
我覺得這些問題的出現,本身就是一種變化,因為我開始在意的已經不只是「把功能完成」,而是這個功能放進整個系統之後會產生什麼影響;以前可能會把 Database、Application、Infrastructure 看成不同的事情,現在則開始把它們串在一起看;以前比較在意功能有沒有完成,現在開始會在意它的 Maintainability、Performance、Resource Consumption,以及在不同負載下的行為。
這個月使用 AI Agent 的方式也開始有一些變化;以前比較容易把 AI 當成寫程式碼的工具,但當面對一個自己不熟悉的系統時,我開始把 Agent 用在系統探索、程式碼分析、執行流程追蹤、Repository 關係整理,以及文件整理上;對我來說,這類工作的價值不一定是直接產生一段可以使用的程式碼,而是幫助我更快建立系統的心智模型。
當然 Agent 提供的分析並不能直接當成答案,還是需要自己回頭確認程式碼、驗證執行流程,以及判斷它的分析是否符合實際系統,但這讓我開始把 Agent 視為一個協助探索系統的工程夥伴,而不只是 Code Generator;尤其是在剛加入一個新團隊、需要快速理解既有系統的情況下,能夠縮短建立心智模型的時間,本身就是很有價值的事情。
如果要說九月最大的收穫,我反而不會說是學會了哪一個新的技術,真正比較明顯的變化,是開始從「熟悉技術的 Developer」,慢慢轉向「需要理解完整系統的 Engineer」。
以前面對一個問題,我可能會先想:「這段程式碼要怎麼改?」現在比較容易先想的是:「為什麼它會變成現在這個樣子?」而當我開始這樣思考之後,很多事情也會自然連在一起:程式碼的設計會影響效能,效能會影響資源消耗,資源消耗可能進一步影響雲端成本;Database 的修改不只是 SQL 本身的問題,也會牽涉到 Testing、Version Control 和 Deployment。
這個轉變其實滿有意思的,因為加入新環境之後,我原本最在意的是「我要花多久才能把這套系統搞懂?」但到了月底,我開始問的問題已經變成「這套系統為什麼這樣設計?哪裡可能是 Bottleneck?如果我改了這裡會影響什麼?它在壓力下會怎麼運作?程式碼的效率又會怎麼影響雲端成本?」我覺得這些問題本身,就是我開始真正融入這個系統的證明。
所以,如果要替九月留下一句話,我可能會說,這並不是一個「學了很多新技術」的月份,而是一個重新建立自己工作方式的月份;從一開始面對陌生系統時,只想趕快知道它怎麼運作,到後來開始想知道它為什麼這樣運作;從理解單一功能,到開始理解架構、流程、效能、資料庫、測試與部署之間的關係。
我想,真正的融入可能也不是在很短的時間內把整套系統全部搞懂,而是從「我不知道這裡怎麼運作」,慢慢走到「我大概知道它為什麼這樣運作,也開始知道哪些地方值得再問一個為什麼」,而九月可能就是這個轉變真正開始的月份。