此系列文章是我閱讀《Refactoring To Patterns》過程中實際演練的筆記。閱讀過程中發現若沒有相當的 Design Patterns、Refactoring 底子,此書真的不易閱讀,必須伴隨實際操作才能更理解每個步驟具體的方式,故在這記錄之餘也跟各位分享。
書中是使用 Java 的程式碼作為範例,而我比較熟稔 C#,所使用的演練環境為:Visual Studio 2017、ReSharper、VsVim。過程中會因應 ReSharper 的功能,所以有些許的調整以便更「優雅」的進行重構。
此篇是關於 7.4 Replace State-Altering Conditionals with State 的具體演練。
此次的 smaple code 是我建立的,若有錯誤還請多包涵,詳細程式碼請見:https://github.com/mystic01/refactoringtopatterns。
以下,請搭配影片閱讀(數字表示影片時間、藍色表示重構技法、紫色表示我的困擾):
- 將兩個條件式給抽出為 method,提高可讀性。Extract Method。0:00
- 將
state
的型態由string
改為PermissionState
。1:18- 一樣使用先用再生的技巧,改掉
string
為PermissionState
,再將其生出。 - 接著逐一改為
new PermissionState("XXX")
,這邊用了一個小技巧。2:10
先把建構子妥妥的生出來,接著逐一半自動的改為new PermissionState("XXX")
。 - 把該改的
string
都半自動的換為PermissionState
。
- 一樣使用先用再生的技巧,改掉
- 將各個
static
的PermissionState
換為對應的 class。4:00
這邊好像沒有什麼特別的技巧,就逐一改改生生...。
- 將各個
static
的PermissionState
搬移(Move To Another Type)到PermissionState
。6:45
- 搬
claimBy()
至所有PermissionState
(含其子 class)。7:36- 因為
claimBy()
這個 method 要保留在SystemPermission
中,所以將其內容抽出為claimBy2()
(避免名稱重複)。 - 將
claimBy2()
搬移(Move Instance Method)至PermissionState
。
※ 7:50 這邊有一個極度困擾我的問題,希望有大師可以為我解惑,感激不盡。
只要使用 Move Instance Method,被抽出去 method 所用到的 field 就會再被 Encapsulate 一次。就像影片中,又產出了一個State1
的 property,但明明就有State
存在。這個問題後面的步驟還會陸續發生,讓我非常困擾,也 Google 不到解法。
※ 8:26 困擾之餘,也借影片分享將兩個 Property 改回同一個的方式。硬是將State1
rename 為State
是行不通的(會發生衝突,導致呼叫端還是會保留在State1
)。我是先把State
改為StateXXXX
(非rename),再把State2
rename 為State
,此時就不會發生衝突,接著刪掉其中一個State
。如果有更好的方式也請告訴我,希望可以忽略衝突強制 rename...。
- 將
claimBy2()
改名回claimBy()
。 - 將 claimBy() 移到(Push Members Down)該放置的子 class(兩個 Requested 相關 class)。Push Members 的動作就帶有複製的意思,超棒的。
- 跳至錯誤處,半自動的在
PermissionState
生出abstract
的claimBy()
。 - 逐一跳至錯誤處,逐一處理 override、implement
claimBy()
,也同時刪除不必要的判斷邏輯。
- 因為
- 仿照上述
claimBy()
的方式依序處理grantBy()
、denideBy()
。10:57
- 整理程式,將各 class 搬移至各檔案,打完收工!!18:40
其他 Refacotirng To Patterns 影片請見:Refactoring To Patterns
不堪入目的練功過程:Refactoring To Patterns (exercise)