← 開發日常

Rename 也會造成 Issue

今天稍微紀錄一下自己重構Side Project踩坑的過程,因為重構導致application系統狀態不正確而一直噴error。

出問題的commit

這一段重構主要是把KiPlayerMap重新命名成PlayerMap

Article image

這是一段單純的重構,也是透過Rider的重構工具幫忙Rename的,但是還是造成了問題,為什麼呢?

發生原因

這個被Rename的field是放在GameBoard物件中,而GameBoard本身的所有field都是用來儲存一盤五子棋局的狀態,例如:Player A拿黑棋、棋盤上現在有哪些棋子...等等。

Article image

當玩家做了一些走了一步棋,application就會改變GameBoard的狀態並把它存回Redis中。儲存的過程中,application會用BinaryFormatter把GameBoard轉成byte array並使用StackExchangeRedis寫回Redis中。相反的,拿出來的過程也是把byte array讀回application中並轉回GameBoard。

Article image

然而問題就發生在byte array與GameBoard的轉換過程中,因為Rename,導致原本已經存在Redis中的資料無法正常被讀回。被Rename那個field無法正常被讀回並變成null,程式繼續執行下去就會發生問題。

Article image

壞的設計

這個問題發生主要是因為把資料原封不動的存起來,不止變數的值,甚至是類別的名稱和變數的名稱,這就導致application與redis直接耦合。像是Rename或者move field等重構手法就無法使用在這些DTO中。

還有其他相似的問題,例如:把Enumeration直接用string的形式存在db,而不是用int,這也會造成Rename Enumeration上的不方便。

我們應該要把狀態的值存在db或redis,但是不應該把application的變數名稱也存在db中,因為這會造成application與db直接耦合。當需求發生變化時,要不是造成產品問題,就是改動很耗費時間。

如何改進設計

以上面的例子來說,應該要把GameBoard把轉成Json並儲存,這種做法能解開application的變數名稱與db的欄位名稱的耦合。雖然還是有一些缺點,但比起application與db的相依來說,以這一些代價換來application的彈性,算是很划算的。

Article image

小結

最近在重構自己的Side Project專案時,意外遇到了這個bug,也讓自己對設計有重新思考的機會。在實作需求時,很多時候都是這樣寫也可以,那樣寫也可以,不管是哪一種寫法都有他的優缺點,如果能在這些時候多想一些作法,多比較一下優缺點,就能讓我們的代碼更乾淨,也更少bug。