擁有 17 年資歷的解決方案架構師。從 2026 年 3 月到 2026 年 7 月,我是某海灣國家國家港口社群系統身份識別與單一登入層的唯一實作開發者——該平台是其港口與物流產業的前端入口。目前已上線生產環境。

我想精確說明「唯一」的定義,因為這很重要:其他人員確實曾提交過兩個儲存庫——包括 CI、自動化測試、少數修正,以及下游整合工作。我撰寫了約 80% 的後端提交與 70% 的前端提交。沒有人在核心系統上進行過實作功能開發。這是真實的說法。

直接來自 git log --numstat 的量:

  • 602 次提交,約 184,000 行變更,橫跨 1,423 個檔案
  • 後端:383 個 Java 檔案 / 約 21k 行程式碼,19 個控制器,83 個 REST 端點
  • 前端:152 個 TS/HTML 檔案 / 約 15.3k 行程式碼,62 個 Angular 元件
  • 6 個外部整合,每個都有真實與模擬配接器
  • 4 個環境,2 次獨立滲透測試已修復

我在 4 月給領導的書面估計(當時尚未有任何爭議):若無 AI 工具,需 3–4 名工程師花 3 個月完成。

架構

六角形架構(連接埠與配接器)+ CQRS。domain 套件具有零 Spring 或 JPA 匯入——可透過 grep 搜尋,結果為空。這是檢驗六角形架構究竟是設計決策還是流行語的實際測試,而大多數聲稱採用六角形架構的程式碼庫都無法通過此檢查。

domain/         純領域層 — 模型、值物件、事件、連接埠。不含框架匯入。
application/    使用案例 — 命令(寫入)與查詢(讀取)、DTO、組裝器。
dataprovider/   配接器 — JPA 實體、Spring Data 儲存庫、SOAP 用戶端。
web/            入站配接器 — 控制器、DTO、映射器、JWT 過濾器、SAML 處理器。

進入全螢幕模式 離開全螢幕模式

每個功能都是一對配對的 XxxCommand/XxxCommandImpl(交易性寫入)與 XxxQuery/XxxQueryImpl(唯讀)。每個外部相依性都透過連接埠隱藏,並由 Spring profile 選擇真實或模擬配接器——這意味著 QA 與 UAT 可執行完整的端到端流程,而無需依賴政府系統處於上線狀態。他們經常處於離線狀態。

有一個值得借鏡的 JPA 細節:@Version 樂觀鎖定搭配先查詢再更新的儲存模式,特別是為了避免 Spring Data 的「null 版本表示新實體」行為導致重複鍵錯誤。這很容易出錯,偵錯也很痛苦。

使用者生命週期是一個真正的狀態機(PENDING_VERIFICATION → ACTIVE → LOCKED/INACTIVE),使用狀態模式,因此無效的轉換會在領域層失敗,而不是由 UI 中分散的 if 陳述式來防護。

值得閱讀的四個問題

1. Java 的 X.509 剖析器拒絕政府憑證

AVA not a sequence — 一種格式錯誤但在現實世界中相當常見的編碼,JDK 的嚴格剖析器會直接拒絕。我改用 BouncyCastle 的 X.509 工廠撰寫手動中繼資料剖析器。

後來部會在生產環境輪替其簽署憑證,系統隨之停機。因此我將憑證改為可熱重載,並在失敗時刷新。二十天後再次輪替——這次系統自行修復,而未通知任何人。

2. 間歇性 500 錯誤,所有人都歸咎於網路

測試人員在印度,伺服器在阿曼,因此「是延遲問題」是大家的第一反應。

我改為檢查。設定的逾時時間為 60 秒。印度至阿曼的實際往返延遲為 100–250 毫秒——大約短 240 倍。即使嚴重降速也無法產生 60 秒的延遲。而且 500 或 503 是由伺服器產生,是在已經接受連線之後,因此絕對不是網路路徑問題。

政府 API 本身就不穩定。這個結論支持採用重試與退避機制,而不是花數週時間追蹤一個虛幻的網路問題。

在同一個整合中埋藏著:他們的生產 API 會傳回 "WORKING" 表示有效工作許可,而不是 "Active"。一個字串不符就悄無聲息地阻擋了每一位真實使用者的註冊。

3. 三個可能在付款過程中競速的時鐘

10 分鐘的發票到期時間、約 2 分鐘的前端輪詢視窗,以及 60 秒的後端調解作業。緩慢的 3-D Secure 確認可能會超過前端的耐心即使付款成功

修正方式是兩個後端排程器作為安全網,獨立於瀏覽器是否仍開啟,以及兩條獨立的最終化路徑——銀行的伺服器對伺服器回呼(具權威性,即使使用者關閉分頁也能運作)與 SPA 的輪詢(備援)——兩者都透過單一冪等性防護機制匯集,因此無論哪條路徑獲勝,下游同步只會觸發一次。

相關且更愚蠢的問題:瀏覽器直接 GET 銀行的付款端點會悄無聲息地捨棄 POST 主體。修正方式是後端渲染的自動提交表單,讓瀏覽器永遠不會 GET 該端點。

4. Chrome 阻擋 XHR 的 TLS 重新協商,但不阻擋導覽

每個 API 呼叫都以 net::ERR_FAILED 失敗,而 SAML 重新導向卻能完美運作。

這種不對稱正是造成高成本的原因——一個驗證重新導向成功但後續每個 API 呼叫都失敗的系統,看起來就像是後端驗證錯誤。這其實是基礎架構設定問題。

沒有人警告你的重做

兩個儲存庫總共經歷 16 次還原與重建循環。兩個最值得一提的例子:

  • 下游權杖交換交握在一個下午歷經四種不同的協定——兩步驟、service-JWT bearer、app_secret bearer、無驗證標頭——接著在接下來的幾天又還原兩次,最後才確定為單一步驟交換。
  • 業務線正規化規則:一天內透過四個 PR 建立四種策略,全部在同一天還原,因為對方確認其 API 想要的值必須與儲存的完全相同,之後從 main 完全移除,兩週後又以第三種方式重建。

這些都不是 AI 或我的錯。這是當你與需求尚未穩定的團隊整合時會發生的事。

Claude 實際有幫助的地方與沒幫助的地方

它撰寫了大部分程式碼。不僅是骨架——配接器配對、數十個功能的 CQRS 命令與查詢實作、JPA 映射慣例、Angular 元件,以及整合用戶端的大部分內容。這種壓縮正是單人能涵蓋 3–4 人工作範圍的全部原因。

它沒有發現上述四個問題。每一個問題都始於知道該懷疑什麼。憑證失敗以一般 SAML 錯誤呈現。500 錯誤被在場的所有人自信地誤診。時鐘競速從未在測試中出現。TLS 錯誤呈現為驗證問題。

你無法透過提示來修復你尚未正確識別的問題——你描述的是你已經解讀過的症狀,而解讀才是工作。

還有一個沒有人提到的版本:我在五個月內多次達到模型使用上限。速率限制是真正的排程限制,而不是註腳。

我會做不同的地方

測試覆蓋率約為後端的 23% 指令覆蓋率。這很低,我不會粉飾。有了第二位工程師,我會更早投資自動化覆蓋率,並讓有人在實作前審查下游整合協定,而不是透過四輪實時重做才發現不符之處。

樂意深入探討任何部分。