作者landlord (91)
看板Soft_Job
標題[心得]以策略模式重構switch case或if (影片)
時間Sun Dec 13 21:27:28 2020
最近在客戶那邊一起 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 在重構上還是地表上最強的兵器啊。
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.25.31.202 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/Soft_Job/M.1607866053.A.4BB.html
1F:推 free112136: 推91哥 12/13 22:18
2F:推 wvwvwvwvwv: 實用推Y 12/13 23:01
3F:推 Raymond0710: 91安安 12/13 23:06
4F:推 foreverk: 推,legacy code看到if又case又if真的吐血 12/13 23:25
5F:→ petercoin: shipper輸入的部分還有改善的空間嗎?感覺用字串很容易 12/14 09:10
6F:→ petercoin: 出包... 12/14 09:10
7F:推 alihue: 包成 enum 吧,然後在 convert 到 enum 時做 err handlin 12/14 09:16
8F:→ alihue: g 12/14 09:16
9F:推 kkjkj: 樓上,我想問一下當如果enum沒該對應,怎麼處理比較好? 12/14 11:49
10F:→ alihue: Throw exception. 12/14 12:28
11F:→ superpandal: 噗 XDDD 12/14 12:47
12F:推 WashFreeID: 推~ 12/14 13:59
13F:推 tbpfs: 改用kotlin重構,你會看到新世界 12/14 14:36
14F:→ kkjkj: 這樣switch的default動作用exception有點不太妥吧? 12/14 15:17
15F:→ kkjkj: 我會這樣問是我曾經是在對應後,外面增加判斷是否null 12/14 15:22
16F:→ kkjkj: 想知道有沒有其他方式,處理對應不到的情況 12/14 15:23
17F:推 brianhsu: 重點應該是對應不到後的行為,如果這本身就是不合法的操 12/14 15:36
18F:→ brianhsu: 作,你在外面檢查到 null 之後,還是要丟 exception 啊 12/14 15:36
19F:→ brianhsu: 。 12/14 15:36
20F:推 alihue: 還是看當下商業邏輯,如果走不下去直接丟 ex 外面就不用 12/14 15:38
21F:→ alihue: 檢查 null 更乾淨 12/14 15:38
22F:→ kkjkj: switch的defalut動作是合法的阿<=這邊在於討論改成enum情況 12/14 15:39
23F:推 aoma: 推~ 12/14 15:39
24F:→ alihue: 你應該不會想要全部用到的地方都檢查 null,把責任丟給 12/14 15:42
25F:→ alihue: convertor ,錯就丟 ex,如此一來其他地方直接用 enum 就 12/14 15:42
26F:→ alihue: 乾淨很多 12/14 15:42
27F:→ kkjkj: 我知道你的使用情況了,我的情況是要吐不同的ex才多判斷null 12/14 15:43
28F:→ alihue: 對 還是根據你的情節決定 default 幹什麼事,說不定你們 12/14 15:45
29F:→ alihue: 有default enum 12/14 15:45
30F:推 dog30111: 怕null做個空物件 12/14 15:54
31F:推 undersky: 推~ 影片看不是很明白但git history很清楚 12/14 16:33
32F:推 a12838910: 推 看history很明確 每個步驟 12/14 22:40
34F:→ vi000246: 寫了一個用泛型的範例 12/14 22:45
35F:→ landlord: 謝謝樓上幾位的鼓勵,我培訓中的練習題都是這樣呈現的 12/14 23:45
36F:→ wesley234: 吃太飽 12/15 08:28
37F:推 csieflyman: enum class Shipper implement Product interface ove 12/15 10:02
38F:→ csieflyman: rride caculateFee method.另外 Shipper constuctor 12/15 10:02
39F:→ csieflyman: 宣告 shipperName 屬性 強迫每個 enum 一定有 name 12/15 10:02
40F:→ csieflyman: 屬性 再把 Cart 的 hashmap 替換成 Shipper.shipping 12/15 10:02
41F:→ csieflyman: Fee(input) static method 裡面用 values() 比對 name 12/15 10:02
42F:→ csieflyman: 找出對應的 enum 再呼叫 caculateFee 即可 12/15 10:02
43F:推 csieflyman: 這樣就沒有 if 也沒有 map 也沒有 Cart class 12/15 10:09
44F:→ electgpro: 你這個應該不能叫做策略模式,因為沒有動態 injection 12/16 14:00
45F:→ electgpro: 另外我滿好奇你覺得的 code smell 是指什麼 12/16 14:01
46F:→ electgpro: 在我看來你的 refactor 只有把 if 取代成 map 12/16 14:02
47F:→ electgpro: 除此以外結構上並沒有什麼太大的差異 12/16 14:03
48F:→ landlord: data clump 變成 parameter object: Product 12/16 21:11
49F:→ landlord: 順帶一提,歡迎大家把自己的想法、重構、設計呈現出來 12/16 22:24
50F:→ landlord: soure code 在 github 上,連 branch 都開好了 12/16 22:25
51F:→ landlord: 歡迎fork回去,自己錄一版重構的影片跟repo放上來討論 12/16 22:25
52F:→ landlord: soure -> source 12/16 22:26
53F:推 accessdenied: if 的確很難維護啊,光是改成switch 就有部分防呆 12/20 10:50
54F:→ accessdenied: 效果了。 12/20 10:50