[心得]以策略模式重構switch case或if (影片)

作者: landlord (91)   2020-12-13 21:27:28
最近在客戶那邊一起 pair 重構 legacy code,
碰到了一大段 if/else statement,用來判斷什麼時候該使用哪一種cache,
並依照不同 cache 的邏輯來決定回傳的內容。
發現還是有蠻多風氣比較封閉的公司對這類型的基本功跟處理不是很熟悉,
可能是對 code smell 不熟,對重構不熟,對 design pattern 不熟,對工具不熟。
因此,我用自己幾年前的一個「計算運費」的範例,設計成這類型程式碼重構的簡介。
這個範例之前是 C#,這次示範我改用 Java,用 IntelliJ 來重構。
有整個重構過程的 IDE 操作影片,也有每一個重構 baby steps 的 commit history。
影片:https://youtu.be/zO-NnNC-xyg
GitHub commit history: https://bit.ly/strategy-91
也可以參考 《Refactoring to Patterns》 的
Replace Conditional Logic with Strategy:
https://www.informit.com/articles/article.aspx?p=1398607&seqNum=2
IntelliJ/Android Studio 在重構上還是地表上最強的兵器啊。
作者: free112136 (Free)   2020-12-13 22:18:00
推91哥
作者: wvwvwvwvwv (殺死丁力這個雜碎a~)   2020-12-13 23:01:00
實用推Y
作者: Raymond0710 (雷門)   2020-12-13 23:06:00
91安安
作者: foreverk (文藝青年)   2020-12-13 23:25:00
推,legacy code看到if又case又if真的吐血
作者: petercoin (彼得幣)   2020-12-14 09:10:00
shipper輸入的部分還有改善的空間嗎?感覺用字串很容易出包...
作者: alihue (wanda wanda)   2020-12-14 09:16:00
包成 enum 吧,然後在 convert 到 enum 時做 err handling
作者: kkjkj (kk)   2020-12-14 11:49:00
樓上,我想問一下當如果enum沒該對應,怎麼處理比較好?
作者: alihue (wanda wanda)   2020-12-14 12:28:00
Throw exception.
作者: superpandal   2020-12-14 12:47:00
噗 XDDD
作者: WashFreeID (免洗)   2020-12-14 13:59:00
推~
作者: tbpfs (http://0rz.tw/Uk989)   2020-12-14 14:36:00
改用kotlin重構,你會看到新世界
作者: kkjkj (kk)   2020-12-14 15:17:00
這樣switch的default動作用exception有點不太妥吧?我會這樣問是我曾經是在對應後,外面增加判斷是否null想知道有沒有其他方式,處理對應不到的情況
作者: brianhsu (墳墓)   2020-12-14 15:36:00
重點應該是對應不到後的行為,如果這本身就是不合法的操作,你在外面檢查到 null 之後,還是要丟 exception 啊。
作者: alihue (wanda wanda)   2020-12-14 15:38:00
還是看當下商業邏輯,如果走不下去直接丟 ex 外面就不用檢查 null 更乾淨
作者: kkjkj (kk)   2020-12-14 15:39:00
switch的defalut動作是合法的阿<=這邊在於討論改成enum情況
作者: aoma   2020-12-14 15:39:00
推~
作者: alihue (wanda wanda)   2020-12-14 15:42:00
你應該不會想要全部用到的地方都檢查 null,把責任丟給convertor ,錯就丟 ex,如此一來其他地方直接用 enum 就乾淨很多
作者: kkjkj (kk)   2020-12-14 15:43:00
我知道你的使用情況了,我的情況是要吐不同的ex才多判斷null
作者: alihue (wanda wanda)   2020-12-14 15:45:00
對 還是根據你的情節決定 default 幹什麼事,說不定你們有default enum
作者: dog30111 (安)   2020-12-14 15:54:00
怕null做個空物件
作者: undersky (undersky)   2020-12-14 16:33:00
推~ 影片看不是很明白但git history很清楚
作者: a12838910 (Ziv.C)   2020-12-14 22:40:00
推 看history很明確 每個步驟
作者: vi000246 (Vi)   2020-12-14 22:44:00
https://dotnetfiddle.net/L2BGVY寫了一個用泛型的範例
作者: landlord (91)   2020-12-14 23:45:00
謝謝樓上幾位的鼓勵,我培訓中的練習題都是這樣呈現的
作者: wesley234 (掃地)   2020-12-15 08:28:00
吃太飽
作者: csieflyman (風之驕子)   2020-12-15 10:02:00
enum class Shipper implement Product interface override caculateFee method.另外 Shipper constuctor宣告 shipperName 屬性 強迫每個 enum 一定有 name屬性 再把 Cart 的 hashmap 替換成 Shipper.shippingFee(input) static method 裡面用 values() 比對 name找出對應的 enum 再呼叫 caculateFee 即可這樣就沒有 if 也沒有 map 也沒有 Cart class
作者: electgpro (Ray(甫))   2020-12-16 14:00:00
你這個應該不能叫做策略模式,因為沒有動態 injection另外我滿好奇你覺得的 code smell 是指什麼在我看來你的 refactor 只有把 if 取代成 map除此以外結構上並沒有什麼太大的差異
作者: landlord (91)   2020-12-16 21:11:00
data clump 變成 parameter object: Product順帶一提,歡迎大家把自己的想法、重構、設計呈現出來soure code 在 github 上,連 branch 都開好了歡迎fork回去,自己錄一版重構的影片跟repo放上來討論soure -> source
作者: accessdenied (存取違規)   2020-12-20 10:50:00
if 的確很難維護啊,光是改成switch 就有部分防呆效果了。

Links booklink

Contact Us: admin [ a t ] ucptt.com