[心得]以策略模式重構switch case或if (影片)
最近在客戶那邊一起 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 在重構上還是地表上最強的兵器啊。
--
推91哥
實用推Y
91安安
推,legacy code看到if又case又if真的吐血
shipper輸入的部分還有改善的空間嗎?感覺用字串很容易
出包...
包成 enum 吧,然後在 convert 到 enum 時做 err handlin
g
樓上,我想問一下當如果enum沒該對應,怎麼處理比較好?
Throw exception.
噗 XDDD
推~
改用kotlin重構,你會看到新世界
這樣switch的default動作用exception有點不太妥吧?
我會這樣問是我曾經是在對應後,外面增加判斷是否null
想知道有沒有其他方式,處理對應不到的情況
重點應該是對應不到後的行為,如果這本身就是不合法的操
作,你在外面檢查到 null 之後,還是要丟 exception 啊
。
還是看當下商業邏輯,如果走不下去直接丟 ex 外面就不用
檢查 null 更乾淨
switch的defalut動作是合法的阿<=這邊在於討論改成enum情況
推~
你應該不會想要全部用到的地方都檢查 null,把責任丟給
convertor ,錯就丟 ex,如此一來其他地方直接用 enum 就
乾淨很多
我知道你的使用情況了,我的情況是要吐不同的ex才多判斷null
對 還是根據你的情節決定 default 幹什麼事,說不定你們
有default enum
怕null做個空物件
推~ 影片看不是很明白但git history很清楚
推 看history很明確 每個步驟
寫了一個用泛型的範例
謝謝樓上幾位的鼓勵,我培訓中的練習題都是這樣呈現的
吃太飽
enum class Shipper implement Product interface ove
rride caculateFee method.另外 Shipper constuctor
宣告 shipperName 屬性 強迫每個 enum 一定有 name
屬性 再把 Cart 的 hashmap 替換成 Shipper.shipping
Fee(input) static method 裡面用 values() 比對 name
找出對應的 enum 再呼叫 caculateFee 即可
這樣就沒有 if 也沒有 map 也沒有 Cart class
你這個應該不能叫做策略模式,因為沒有動態 injection
另外我滿好奇你覺得的 code smell 是指什麼
在我看來你的 refactor 只有把 if 取代成 map
除此以外結構上並沒有什麼太大的差異
data clump 變成 parameter object: Product
順帶一提,歡迎大家把自己的想法、重構、設計呈現出來
soure code 在 github 上,連 branch 都開好了
歡迎fork回去,自己錄一版重構的影片跟repo放上來討論
soure -> source
if 的確很難維護啊,光是改成switch 就有部分防呆
效果了。
1
原原 PO 用 interface 的好處是,shipper 有新的行為時。 可以很簡單的在 interface 加新的 function。 同時可以檢查有 implement Shipper 的 class 要加入新的 function。 感覺上,彈性更好。 缺點嘛... 如果 shipper 很多時每個都要再補 function 是比較累一點。12
終於有空來加入討論啦~ 這邊有 markdown 好讀版: 這邊我也來提一下我的看法。為了閱讀方便我把一些 code snippet 複製在這邊: ```java= public double shippingFee(String shipper, double length, double width, double3
因為有朋友想要 Python 的版本, 簡單的 legacy code 也可以讓他們玩玩 team build 練練手, 所以我就順手整理了 Python 的版本了。 - GitHub Repo & commit history: - 用 PyCharm 重構的影片,YouTube:3
上回用 Java + IntelliJ 來重構一堆 if/else 的計算運費範例, 這次改用 C# + Rider 來重構一樣的例子,方便習慣 C# 的朋友參考與練習, 不過這次刻意改用 Func<T> 來當作 strategy 的實作內容, 以 function 來取代,省去 class + interface 的部份。 兩種作法適用場景不同,東西夠小夠單純,想要少一點 class/interface 等 elements,6
恕刪 策略模式不就是一個戰鬥機器人 防禦模式就護甲值+20 攻擊模式就攻擊力+50 閃避率-10% 回復模式就自動補血+5hp
35
[討論] 重構跟kpi的考量假設以下情境 有個功能A、B都會用到相同邏輯,且有兩份重覆的code (沒有unit test保護,而且年久失修 要加入unit test會需要更多時程) 現在要加入C,也會用到相同邏輯 身為合格的工程師 應該會把ABC重覆的部份提取出來26
[請益] 這種情況要怎麼重構我現在遇到一個情況 同時跟其他人開發很相似的功能 舉例來說 我跟B同時開發兩個電商網站 一個叫博客來,一個叫蝦皮好了 B已經建好博客來商品列表頁面 我也要建立蝦皮的商品列表 想把B建的博客來頁面拿來用24
重構的幾個迷思覺得最近很多文章都有些不求甚解的問題,來寫點論述。 1. 重構不是什麼了不起的事情 2. 變更程式碼,重寫舊的程式碼成自己爽的樣子,不一定是重構。 3. 重構是一種相對安全的工具型開發方法論, 但仍然有不少風險跟誘惑。17
Re: [討論] 重構之前要寫測試 不然不要重構這就是TAD, 一般做法是假設以前人做的是對的 拿以前的output當測資 避免以後的output跟預期結果不同 技術面的錯誤→沒有防呆/沒有釋放資源/overflow/沒有check 這應該不在討論範圍內, 也有客觀標準 行為與邏輯的部分才是有爭議的, 要嘛根本沒規格只有口傳16
Re: [請益] 這種情況要怎麼重構1. 你不應該去動別人開發中的 code, 除非 pair 或你是有被授權的人. 2. 你可以使用他的 code , 建 common, 但你不應該改回他的部分(理由1). 3. 假設改完會有衝突, 那表示你做的不是重構. 4. 如果完成再重構會花更多時間, 那表示你做的不是重構. 5. 你要用他的 code , 跟你要整理重構, 是兩回事.15
Re: [請益] 這種情況要怎麼重構我這篇寫的跟原原PO的狀況無關 ※ 引述《tbpfs ( )》之銘言: : 其實我真的不懂為什麼要急著重構 : 有好處嗎? : 一般而言,重構都是發生在農閒的時候2
Re: [請益] 這種情況要怎麼重構如果專案有deadline的壓力建議是先各自發展以不相互影響為前提,最後再用剩餘時間開 一個分支做重構。其實這就是在規劃專案時沒有一個主要主導的設計人,沒有定義從系統 到功能的分工,導致代碼重工,而且缺乏溝通。 真的建議未來有機會在主導你還是要自己學會定義好工作,先學習不寫code就可以訂出功 能以及架構。我自己工作後常常遇到工程師很喜歡自幹,還沒開始就急著寫code,而不是2
Re: [討論] 重構之前要寫測試 不然不要重構人生在世,吃飯跟拉屎都是要做的,應該沒有人會說, 要先吃飯不然別拉屎,還是先拉屎不然別吃飯。 改扣就是改扣,框個名字自稱叫重構, 是不是不知道,但即使是重構,本質還是改扣。 測試是為了改扣順利,不寫測試還是可以改扣。1
Re: [討論] 怎樣算是一個合格的junior cpp programme錢很多,人難找。 : 2.維護legacy code 錢不錯到很多,公司賺錢有一些是爽缺。 : 1.的話重點是一堆效能增進的技巧 : 像是如何提高cache hit rate 或是multi threading的技術