[心得]以策略模式重构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