PTT推薦

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

看板Soft_Job標題[心得]以策略模式重構switch case或if (影片)作者
landlord
(91)
時間推噓18 推:18 噓:0 →:36

最近在客戶那邊一起 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留言評論
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.25.31.202 (臺灣)
PTT 網址

free11213612/13 22:18推91哥

wvwvwvwvwv12/13 23:01實用推Y

Raymond071012/13 23:0691安安

foreverk12/13 23:25推,legacy code看到if又case又if真的吐血

petercoin12/14 09:10shipper輸入的部分還有改善的空間嗎?感覺用字串很容易

petercoin12/14 09:10出包...

alihue12/14 09:16包成 enum 吧,然後在 convert 到 enum 時做 err handlin

alihue12/14 09:16g

kkjkj12/14 11:49樓上,我想問一下當如果enum沒該對應,怎麼處理比較好?

alihue12/14 12:28Throw exception.

superpandal12/14 12:47噗 XDDD

WashFreeID12/14 13:59推~

tbpfs12/14 14:36改用kotlin重構,你會看到新世界

kkjkj12/14 15:17這樣switch的default動作用exception有點不太妥吧?

kkjkj12/14 15:22我會這樣問是我曾經是在對應後,外面增加判斷是否null

kkjkj12/14 15:23想知道有沒有其他方式,處理對應不到的情況

brianhsu12/14 15:36重點應該是對應不到後的行為,如果這本身就是不合法的操

brianhsu12/14 15:36作,你在外面檢查到 null 之後,還是要丟 exception 啊

brianhsu12/14 15:36

alihue12/14 15:38還是看當下商業邏輯,如果走不下去直接丟 ex 外面就不用

alihue12/14 15:38檢查 null 更乾淨

kkjkj12/14 15:39switch的defalut動作是合法的阿<=這邊在於討論改成enum情況

aoma12/14 15:39推~

alihue12/14 15:42你應該不會想要全部用到的地方都檢查 null,把責任丟給

alihue12/14 15:42convertor ,錯就丟 ex,如此一來其他地方直接用 enum 就

alihue12/14 15:42乾淨很多

kkjkj12/14 15:43我知道你的使用情況了,我的情況是要吐不同的ex才多判斷null

alihue12/14 15:45對 還是根據你的情節決定 default 幹什麼事,說不定你們

alihue12/14 15:45有default enum

dog3011112/14 15:54怕null做個空物件

undersky12/14 16:33推~ 影片看不是很明白但git history很清楚

a1283891012/14 22:40推 看history很明確 每個步驟

vi00024612/14 22:44https://dotnetfiddle.net/L2BGVY

vi00024612/14 22:45寫了一個用泛型的範例

landlord12/14 23:45謝謝樓上幾位的鼓勵,我培訓中的練習題都是這樣呈現的

wesley23412/15 08:28吃太飽

csieflyman12/15 10:02enum class Shipper implement Product interface ove

csieflyman12/15 10:02rride caculateFee method.另外 Shipper constuctor

csieflyman12/15 10:02 宣告 shipperName 屬性 強迫每個 enum 一定有 name

csieflyman12/15 10:02 屬性 再把 Cart 的 hashmap 替換成 Shipper.shipping

csieflyman12/15 10:02Fee(input) static method 裡面用 values() 比對 name

csieflyman12/15 10:02 找出對應的 enum 再呼叫 caculateFee 即可

csieflyman12/15 10:09這樣就沒有 if 也沒有 map 也沒有 Cart class

electgpro12/16 14:00你這個應該不能叫做策略模式,因為沒有動態 injection

electgpro12/16 14:01另外我滿好奇你覺得的 code smell 是指什麼

electgpro12/16 14:02在我看來你的 refactor 只有把 if 取代成 map

electgpro12/16 14:03除此以外結構上並沒有什麼太大的差異

landlord12/16 21:11data clump 變成 parameter object: Product

landlord12/16 22:24順帶一提,歡迎大家把自己的想法、重構、設計呈現出來

landlord12/16 22:25soure code 在 github 上,連 branch 都開好了

landlord12/16 22:25歡迎fork回去,自己錄一版重構的影片跟repo放上來討論

landlord12/16 22:26soure -> source

accessdenied12/20 10:50if 的確很難維護啊,光是改成switch 就有部分防呆

accessdenied12/20 10:50效果了。