Re: [問題] 程式的例外
這是一個很好的問題
好到我覺得今天早上應該多燒三柱香感謝祖先 [意義不明]
這個問題也有點大,說不定可以寫一本書?
我也不是什麼 master 還是啥鬼的
倉促隨手寫到哪算到哪
只能說希望有拋磚引玉的效果
※ 引述《Shrugg (淚眼問花花不語)》之銘言:
: 想請問一個一直都沒辦法在邏輯上說服自己的觀念性問題
: 參考資料都說,程式的例外是用來擷取runtime時的例外情形,用來攔截例外的發生的.
: 可是要是已經知道會有那些例外可能發生,
: 設計程式時我們不是就會把限制條件給加上去了,
: 根本不用等到例外發生了再來攔截吧?
: Runtime會發生的例外都是設計程式時根本沒想到的,既然沒想到,
: 為什麼會知道要怎麼去預防呢?
: 像旗標的Java2第十四章以一個使用者輸入錯誤當例子,程式例只能輸入數字
: 但當使用者輸入字串時就會是一個例外,所以程式安排這邊設計一個攔截字串例外
: 發生時的處理.
: 但是假設我是這個程式的開發者
: 我要是一開始就知道這個例外的存在,我就會設條件讓使用者不能輸入數字以外的資料了
: 如果我連這個例外都沒有預估到,我又怎麼會知道要去攔截這個例外呢?
: 希望有人知道我在說甚麼
我覺得看待 exception 機制,得兩方面都著眼
一個是炸 exception 的程式,也就是被呼叫、被使喚的 callee
一個是被炸 exception 的程式,也就是呼叫別人的 caller
單純從 callee 的角度來看 exception 機制
很容易就會得到你的結論
甚至會覺得 exception 機制真的自找麻煩
還得生出一堆 exception class(Java 人最愛生物件了 [死])
那麼,先換個位置也換個腦袋
從 caller 的角度來看呢?
我常常會說 caller 其實就是上司
吩咐 callee 屬下去作一件他不想自己作的事情
假設是買便當好了,所以你會設計一個買便當專員
public class 跑腿 {
public static 便當 買便當(需求 request, 預算 money) {
//根據需求跟預算來決定回傳什麼便當
}
}
當午餐時間到了,你可能就這樣作
便當 bandon = 跑腿.買便當(
this.想午餐要吃什麼(new Date()),
this.錢包.全部的錢
);
this.吃(bandon);
如果按照你的說法
> 設計程式時我們不是就會把限制條件給加上去了,
> 根本不用等到例外發生了再來攔截吧?
套用在 caller 上會怎麼樣呢?
//錢包至少要有錢
if (this.錢包.is沒錢()) {
//準備餓肚子
}
//錢包裡頭的錢要大於要買的便當
需求 午餐需求 = this.想午餐要吃什麼(new Date());
if (this.錢包.全部的錢 < 午餐需求.金額 ) {
//準備餓肚子
}
便當 bandon = 跑腿.買便當(
午餐需求,
this.錢包.全部的錢
);
this.吃(bandon);
等等,這不科學阿...
我是主管耶... 我一秒鐘幾十萬上下
我還得自己去確認錢包裡頭的錢、確認錢夠買午餐?
喵的,這不能叫跑腿自己確認就好了嗎?
不然這跑腿也太沒用了吧? 可以 fire 掉換一個強一點的嗎?
我只要告訴他我的需求、給他我的錢包就好
就像一開始的那樣
便當 bandon = 跑腿.買便當(
this.想午餐要吃什麼(new Date()),
this.錢包.全部的錢
);
this.吃(bandon);
最好錢不夠他還會自己先墊錢最好...
(完美跑腿:我會去地下錢莊借錢,掛你的名字 [指])
於是叫 HR 去應徵一個新的跑腿
public class 跑腿v2 {
public static 便當 買便當(需求 request, 預算 money) {
if (money <= 0) {
//沒錢買個屁阿?
}
if (money < request.金額) {
//錢不夠買個屁阿?
}
//根據需求跟預算來決定回傳什麼便當
}
}
結果主管眉頭一皺,發現便當並不單純
因為無論是「沒錢買屁」還是「錢不夠買屁」
(對不起,這個跑腿講話比較粗俗)
都得等跑腿v2 買完回來之後
打開便當發現裡頭只有屁味
才知道還是沒便當可吃
更慘的是,我還得仔細去分辨是哪種味道
才能了解到底是我根本沒給跑腿錢、還是錢給不夠
便當 bandon = 跑腿.買便當(
this.想午餐要吃什麼(new Date()),
this.錢包.全部的錢
);
if (bandon.is沒錢買屁() ) {
//...
} else if (bandon.is錢不夠買屁() ) {
//...
} else {
//終於可以吃便當
this.吃(bandon);
}
這就更奇怪了,誰會期望便當會有屁味?
何止是愚蠢,簡直就是愚蠢!這公平嗎?鄉親們答應嗎?
(謎之聲:先生你又跑錯棚了)
為甚麼跑腿不能在沒辦法正常買到便當的時候
直接告訴我:「我發生意外了... Orz」
這樣如果我沒有收到意外的訊息
那就表示拿到便當的時候我可以放心吸氣、大口咬下
try {
便當 bandon = 跑腿.買便當(
this.想午餐要吃什麼(new Date()),
this.錢包.全部的錢
);
this.吃(bandon);
} catch (Exception e) {
//處理意外
}
所以叫 HR 去找會丟 exception 的跑腿v3
public class 跑腿v3 {
public static 便當 買便當(需求 request, 預算 money)
throws 買便當意外 {
if (money <= 0) {
throw new 沒錢買便當意外();
}
if (money < request.金額) {
//順便告訴我差了多少錢
throw new 前不夠買便當意外( request.金額 - money );
}
//根據需求跟預算來決定回傳什麼便當
}
}
所以我就只要這樣處理就可以了
try {
便當 bandon = 跑腿.買便當(
this.想午餐要吃什麼(new Date()),
this.錢包.全部的錢
);
this.吃(bandon);
} catch (沒錢買便當意外 e1) {
//趕快借錢塞進錢包
} catch (錢不夠買便當意外 e2) {
int 差多少 = e2.get差額();
//差不太多就補足、差太多就需求變更吧 [遠目]
}
hmmm... 等等,雖然現在跑腿v3 只能告訴我這兩個意外
但是我還是可以先把其他想到的意外先設想要怎麼處理
等到 22k 可以請到博士來當完美跑腿的時候
我的買便當應變對策也不用再回頭再修改
現在的跑腿也還是可以繼續撐著用
甚至 HR 還知道要用什麼條件去找完美跑腿,所以
try {
便當 bandon = 跑腿.買便當(
this.想午餐要吃什麼(new Date()),
this.錢包.全部的錢
);
this.吃(bandon);
} catch (沒錢買便當意外 e1) {
//趕快借錢塞進錢包
} catch (錢不夠買便當意外 e2) {
int 差多少 = e2.get差額();
//差不太多就補足、差太多就需求變更吧 [遠目]
} catch (便當賣完意外 e3) {
//需求變更吧... 只是同一家店賣的東西不要再點了
} catch (食材滅絕意外 wtf) {
//趕快呼叫鐵平
}
這樣子舉例下來,有稍微解答了你的疑惑了嗎?
至於其他沒有提到 or 我不會的部份
就有請各方高手開示指正了 Orz
_____________________________________________________________________
突然想到 n 久以前寫的
《[新手止難] 為什麼有些東西要弄得那麼複雜?》
想到這一夜裡頭《四郎探母》那句
「阿... 真老阿......」
原來我依然一事無成
--
錢鍾書: 說出來的話
http://www.psmonkey.org
比不上不說出來的話
Java 版 cookcomic 版
只影射著說不出來的話
and more......
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 1.162.249.163
→
04/16 03:33, , 1F
04/16 03:33, 1F
→
04/16 03:52, , 2F
04/16 03:52, 2F
推
04/16 04:42, , 3F
04/16 04:42, 3F
推
04/16 08:50, , 4F
04/16 08:50, 4F
推
04/16 09:18, , 5F
04/16 09:18, 5F
推
04/16 10:08, , 6F
04/16 10:08, 6F
推
04/16 10:36, , 7F
04/16 10:36, 7F
推
04/16 10:52, , 8F
04/16 10:52, 8F
推
04/16 19:49, , 9F
04/16 19:49, 9F
推
04/16 22:50, , 10F
04/16 22:50, 10F
推
04/19 01:23, , 11F
04/19 01:23, 11F
討論串 (同標題文章)