Re: [問題] 程式的例外

看板java作者 (痞子軍團團長)時間12年前 (2013/04/16 01:15), 編輯推噓9(902)
留言11則, 10人參與, 最新討論串3/12 (看更多)
這是一個很好的問題 好到我覺得今天早上應該多燒三柱香感謝祖先 [意義不明] 這個問題也有點大,說不定可以寫一本書? 我也不是什麼 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
你回這篇回的好嗨XD
04/16 03:33, 1F

04/16 03:52, , 2F
還有不用偵測回傳值就能處理 & 會直接離開try等好處
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
excellent!!
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
文章代碼(AID): #1HR3Mlki (java)
討論串 (同標題文章)
文章代碼(AID): #1HR3Mlki (java)