久違更新一下工作的日記,說是日記但實際上是把這整週工作上遇到的一些議題做個整理,之後固定做個當週的復盤,紀錄每週的成長,而這週其實相較前兩週沒那麼有強度,但還是可從當中衍生出幾個我想紀錄下來的觀念和學習,分別是:
「單一職責原則」這個詞應該可以說是軟體工程師的聖經之一,大家都知道它很重要,但不一定每個人都有確實實踐,也不一定每個情境下都必須實踐,還是需要根據需求去做一些彈性調整。
而我這週遇到的問題是,忘記密碼的 API 重置成功後會自動登入,但如果遇到有開啟 Captcha 功能的網站,會因為登入時需要輸入驗證碼而報錯,所以必須優化成「重置後兩分鐘內可以跳過 Captcha 驗證」。
這個需求牽涉到三個模塊:
我一開始的作法是:
但這邊遇到的問題是,A 跟 B 兩個系統主要的職責是執行驗證的邏輯,判斷要不要執行則是 Gateway 這邊決定的,Gateway 擁有控制權,如果是到子系統才判斷登入要不要避開驗證,相當於把控制權從 Gateway 這邊交出去,這樣職責就錯亂了,所以應該是:
如此一來控制登入流程的這個職責就完全是 Gateway 這邊攬下了。所以在遇到多個微服務之間的改動時,要先去思考哪個微服務做哪些事、他們各自的職責為何?才不會後續不好維護或後面的人不好接手,工作起來的順暢度也會提升。
跟上面同一張 Ticket 的問題,在登入流程中 Gateway 去 Call A 系統取得重置密碼紀錄時,假設 Redis 的節點故障,可能會拋出 Exception。
原本做法是讓它直接往上傳給用戶,因為我想說就算這邊不拋,到時自動登入也會拋出驗證碼錯誤的例外,那為何不先拋?
但我得到主管的說法是,拋出驗證碼錯誤比拋出系統錯誤的用戶體驗好一點,雖然我是不知道到底是怎麼個好法,但確實我只用工程的角度去思考合理的做法,而不是從用戶的角度去思考,這個觀點滿有趣的,下次要更多設想到 UX 的層面來做設計。
這也算是我在上面那張 Captcha 的單衍生出的問題,就是我在一個 Class 裡面定義了一個常數,而這個常數實際上會不會佔用到 JVM 的空間,而它又會被存放在 JVM 的哪個位置,什麼時候才會被拿出來使用?
這個 DEFAULT_VAL 的常數變數會在 JVM 運行時存放在本地內存裡,Metaspace 的 Runtime Constant Pool。
Metaspace 是在 JVM 裡用來存放 Class 相關資訊的空間區域,JVM 在執行中如遇到類加載的情況時,會把 Class 相關的 Metadata,如 Class 內的靜態變數、常數、方法等資訊存入 Metaspace。在 Java 8 以前這個區域被稱為永久代 (PermGen),Java 8 以後被替換成 Metaspace,也從 JVM 堆內存移到本地內存。
JVM 在執行過程中遇到需要使用某個類時,會進行以下步驟:
Metaspace 的特點是,它使用的是本地內存(Native Memory),而非 Java 堆內存
默認情況下,它可以動態擴展(直到系統內存上限)可以通過 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 參數限制其大小,不受 Java 垃圾回收器直接管理,但類卸載時會釋放對應空間
引用 DEFAULT_VAL 這個變數的字串值 "0",會存放在 JVM Heap Memory 裡的 String Constant Pool。JVM 裡的 Heap Memory 就是用來存放所有對象實例的空間區域,包括引用類型變數的實例、字串變數引用的值等等。