文章目錄

相信很多人寫程式、寫到後來一定會有著如以下的情況:

  • 好多的if-else、我分不清楚哪個括號裡面的是哪個了。

  • 好多的switch-case、這一段是哪裡的case阿~我找不到case了。

  • 這個的switch太長了、我找不到上面、也找不到下面,我要加在哪裡~~~(暴怒)。

  • 咦咦、這個case我寫過了沒、有吧、沒有吧~(拔花花) 到底有還是沒有~~~ (我生氣了)。

  • 這段和那段case好像歐~可是又有點點不一樣耶~ = “””= 我好煩躁、明明就很像,為什摸還要傻傻的再寫一次,好煩好煩
    好煩噢~(扭扭)。

寫膩switch-case了嗎~?? 我聽到大家的心聲了~(毆飛、明明上面那個就是小助助的內心戲)。好、好唄~說是我的內心戲就是
我的吧~ (咬手帕) 身為很懶惰(?)的工程師、一定會很想要很懶的寫code、要很容易的可以一眼看到底、可以不動的地方、
最好就是一輩子都不動它(再次毆飛)、還要可以刪掉都不心痛、不用改一堆有的沒的~這樣的話、這篇真的太適合不過了~ w

有幾個小前提啦~ = “””=

  • 基於我是用js醞釀的、我不確定在其他非script的語言是不是也可以通~ XDD 應該是可以、只不過寫法可能要稍微修一下。
    以下範例都是js的片段,可能有問題(?)、就~~加減湊合吧~ w

  • 大部分的人、switch-case應該都是基於某個symbol、也就是說、大概就是string或者number…這類的為最常見。所以、
    這次的例子,主要就是針對這樣的情況做些修改囉~ w

##switch-case 超~~基礎類型1

首先、當然是從最基礎的類型開始看起,下面這段、是平常隨手寫來就是長成這樣的類型。下面這段應該是完~~~~全不會有
問題的、就是最基礎的樣板。

switch-case1
1
2
3
4
5
6
7
8
9
10
11
switch(cond) {
case ("a"):
fn1();
break;
case ("b"):
fn2();
break;
default:
fn3();
break;
}

這樣的類型、一開始的確是很好寫、也不會有任何的問題。問題在什摸時候會開始發生呢~?

  • 我的程式越來越大了、怎摸辦~我看不到上面也看不到下面,我寫不下去了、我再也沒辦法修改了。bug出現、抓完一隻又
    一隻、這段有沒有寫阿~ Q ^Q 欲哭無淚、誰來拯救我、黑歐噗咪~

  • 唔、我有好多類別歐~ = “””= 好煩歐~怎摸要一直判斷類別阿~ 這裡也要type is xxx 那邊要type is ooo。每一個
    function都要來一下switch(type)在case…balabala好煩好煩好煩阿~我有1x個type耶~我要崩潰了~~~ Q 口Q

為了改善這樣的情況、請改用下面的寫法吧~w

既然、尼已經知道是什摸樣的條件、就不要吝嗇使用它~把它利用到底吧~ @ @++ 它會感謝尼讓它出場次數那摸多、這樣大家
都會記得它。

我們將條件(以下就把它叫做cond吧~)相關的處理提出來、用一個object來存好它。然後、在我們接收到cond、然後要操作
相關運算時、可就方便啦~知道cond、就知道要執行哪個動作了~ w 歐耶~ perfect

改寫switch-case1
1
2
3
4
5
6
fns = {
a: fn1,
b: fn2,
default: fn3
}
fns[cond]();

其實、一般來說,最基礎的這個類型就十分夠用了啦~ w 真的、大概可以解決70%的問題~ 可是、除了懶、還有更懶,沒有
龜毛、只有最龜毛。是的、如果在上述中、我的function、不是一個就可以解決的怎摸辦、我就很懶阿~我就想把我已經
醞釀好的sub-function、一個個的串起來~(扭扭) 我不想一直寫一樣的code~。

如果、尼懶惰到這種程度,就請繼續往下看吧~ (我承認~ Q 口Q 如果多年以後我忘了、回來複習本篇、一定會接著往下看)

##switch-case 基礎類型2

好的、這一段就是基於上述的需求,我們把它攤開用switch-case下寫來、毫無疑問的,應該會是跟下面那段長的差不多像。
那、我們要怎摸改咧~請看下面的再下面那段code….. XDDDD

switch-case2
1
2
3
4
5
6
7
8
9
10
11
12
switch(cond) {
case ("a"):
fn1();
break;
case ("b"):
fn2();
fn3();
break;
default:
fn4();
break;
}

跳過來了嗎~? 好好、那我們就開始囉~ @ 3@

既然、尼想把那些sub-function兜起來,那就把它們兜起來嘛~ XDDDD 想要怎摸串、就怎摸串歐~ 很簡單吧~ w 我也是這摸
覺得的吶~!!

是的、這個跟上面的差別就在於…我在sub-function的外面用一個function把它們都包起來而已、其實換湯不換藥喇~ XDDD
我相信、聰明的大家,就算我迷有提出來還是會醞釀出來的呢~ w

改寫switch-case2
1
2
3
4
5
6
7
fns = {
a: function() { fn1() },
b: function() { fn2(); fn3(); },
default: function() { fn4() }
};
desc = (!!fns[cond]) ? (cond) : ("default");
fns[cond]();

那…這樣就結束了~?? 太空虛了吧~如果、尼這摸覺得,那尼也太小看懶惰的威力了~ > 3< 我相信、除了上面那些以外,
很常寫規則、動不動就要趴資料的人…一定會遇到,我的case有時候有2個要一樣、有的3個、有的只有1個…我的case
是動態的耶~ Q 口Q 那…我要把剛剛類型1、2的…重複寫那摸多次歐~ 一定會寫都不知道在寫什摸的喇~

如果、尼有降得困擾…那就接著看吧~ w

##switch-case 可有可無之動態二分類型

為什摸會說它是可有可無咧~ XDDD 其實是因為、這個比較小型喇~而且有很多替代方案,不過、為了接下來的部份,我們先
來牛刀小試一下、大家對我接下來寫法的接受程度囉~ w

好的、我們的case變成降了,我們的cond、可能有a、b、c或者…更多,anyway~我們不care它們到底有多少個~我們的重點
在於~常常在if-else的情況下,我們的if會落落長…然後、就可能會把它拆成switch-case (看起來的確順眼多了…),
可是、每加一個條件、就要在寫一個~ = . .= 好懶歐~還要在重複一次case…balabala 很麻煩耶~要是不小心寫長了、
就看不到上面也看不到下面了~一點點也不ok。所以、我把它改掉了…請跳下下個codeblock。

switch-case4(動態二分類型)
1
2
3
4
5
6
7
8
9
10
switch(cond) {
case ("a"):
case ("b"):
case ("c"): // 也許更多..., 無所謂啦~
fn1();
break;
default:
fn2();
break;
}

就是這段~ @ @++ 好玩的來囉~ w 我代入了…..迷有錯~尼絕~對迷有看錯歐~我使用了正則來ko它了…。其實、在正則
之前,還有個版本,是用array-while的組合,可是我怎摸看怎摸彆扭,不喜歡~ > 3< 這可怎摸辦咧~我想著想著、突然…
靈光一閃~ @ @+++++ 這不是、反正我就是要定這個cond的描述,這…正則不是最方便了嘛~不就是個描述嘛~ XDDDDDD

我才不要只是很單調的拿它(正則)來check那些data的樣板、還是拿來做replace,那…正則就太可年了~ Q 口Q 明明就是這摸口愛的
小東西。為了發揚光大我最愛的正則、所以、落落長的switch-case的case就被我嘗試著改成….下面那樣了… 一行ko~然
後因為是if-else嘛~ 二分類型、所以只要這樣判斷就迷有問題了…。

[註] 下面那段的正則、因為我偷懶~ XDDDD 因為例子是單個字母的條件,我就這摸寫喇~ w

改寫switch-case4(動態2分類型)
1
2
3
4
pool = /^[abc]$/
result = pool.test(cond);
(result && fn1());
(!result && fn2());

可是、可是、可是~尼說得那個是2分類型阿~我要3分、5分、100分咧~ > 3< 而且、我每個都要動態的、我還要有數字、文字
長度都還要不一樣~那那那…怎摸辦~ > 3<

糾結了嗎~?? 那摸就繼續往下看吧~ w

##switch大絕 之 正則真的是太棒了~正則萬歲

是的、當我醞釀出上面那段的時候、我腦袋就浮出這那些問題了,我的終極目標是…

  • 有個紀錄條件的data。

  • 一個是儲存了對應條件的動作的地方。

  • 只要我寫好mapping、直接就可以取得動作了。

基於以上的目標、我弄了下面那段code,有比較長一點點,就湊合著看唄~w

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// step1
cond = [
/^(1|2)$/,
/^(-3|a|abc)$/,
/^(4)$/
];
// step2
method = [
fn1, fn2, fn3, default_fn
];
// step3
switchFn = function(input_cond) {
var i = cond.length,
chk_cond = false;
cond.map(function(cond_i, idx) {
(cond_i.test(input_cond) && (
method[idx](),
chk_cond = true
))
})
// 很偷懶的使用這個方法、可以確保最後一項為default function
(!chk_cond && method[method.length - 1]());
};
// step4
switchFn(input_cond);

然後、這邊我就不在用object來做mapping了,原因如下:

  • 要取名字很麻煩。

  • 取了名字要打比較多字母很麻煩。

  • 其實我不喜歡object。

因為這幾個理由、我使用了array~ XDDD code的步驟解說如下:

  1. 建立條件判斷,一樣採用正則~ Q 口Q 正則、我真的愛死尼了~。這邊應該可以很明顯的看出、我迷有偷懶了 = “””=

  2. 把寫好的function們一樣塞到一個array,不用我說,大家都應該要知道…不要自找麻煩,一個對一個是最好的啦~!!

  3. 把之前那個例子的判斷方法抄過來…。

  4. 將將將~~!! 恭喜尼、kkkkko了~ (扭扭)

所以、其實只是把之前那個例子,改成用array的方式拓展出去而已啦~ 又是個換湯不換藥囉~ w 很簡單簡單吧~

##結論時間

其實~~這最後的2個例子…不瞞尼說,一般人真的用不太到,除了~寫規則寫的很煩躁的人,動不動就有1x個條件要判斷…
要不就是趴格式趴到很火大的謎樣生命體(?) 簡單的說、就是比較枯燥繁瑣的系統,又有點點龐大的情況才合適。
一般、前面2個就很夠用了呢~!!

而用這樣的方式寫出來的、可以幹麻~以後只要寫好配置檔就好了~ @ @++ 怎摸刪都不肉疼…而且、條件可以一目10行…
多好阿~ 不只code的行數急遽下滑…看起來又很清爽、彈性又很大。

根據我不負責任的實驗結果,採用上面的方式來改寫掉得code、預估大概結果如下:

(不準的原因是因為、我一定還會偷偷摸摸的在程式裡面動手腳~ XDDD 所以、速度可能也沒有真的快上那摸多喇~)

  • 以…前面2種方法來改寫、速度的改進眼睛看得見、code的量,依情況不同,可減少10~30%不等…可多可少喇~
    bug可以少掉30~40%根據我改前人的code~(有多不繁瑣、bug就會少掉多少~ w)

  • 以…後面2種來改寫上面已經改寫過的,在效能的穩定性也提高不少、code的量,
    依據cond重複多寡,重複越多省越多,可節省50+%的容量。(這個的bug就少不了多少了~ 基本上、我相信,如果尼已
    經早就會這種寫法、表示…尼一定是個以一擋百、萬夫莫敵的勇者)

額外好處如下:

  • 可一目十行。

  • 很好重複再利用。無論是哪一塊。

  • 不喜歡就刪掉、很好刪。

  • code有問題、改好一個,其他的就解決了。相當於,殺死一隻小強、就殺死千千萬萬隻小強子孫。

  • 更好複製貼上了。

不知道還有迷有更簡潔的寫法耶~ 有的話、請鼻要吝嗇、指點指點嫩嫩的小助助吧~ XDDD 請給我經驗值衝等!!


寫完這篇、真的是體會到粒粒(例例)皆辛苦了捏~ > 3< 然後…感覺離不開functional language了、也離不開正則了…
我愛尼們~ > “””< 請鼻要離開我的世界!!

文章目錄