作者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/cn.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