例外處理設計與重構實作班

Teddy Chen
Sept. 14 2013
Copyright@2013 Teddysoft
我是誰
• 2012年7月成立泰迪軟體,從事敏捷開發顧問、教
育訓練、軟體工具導入等服務。
• 2012年6月,出版暢銷書「笑談軟體工程:敏捷方
法的逆襲」。
• 2012年4月起,多次講授Scrum課程,與學員互動氣
氛佳,滿意度高。
• 超...
課程內容
• 例外處理基本觀念
• 例外處理的4+1觀點
• 建立例外處理中心思想—Staged Robustness
Model
• EH Bad Smells and Refactoring's

Copyright@2013 Teddys...
例外處理基本觀念
一個軟體開發專案存在著很多互相競爭
且衝突的非功能需求

robustness

time-to-market, iterative &
incremental design,
(exception handling)
誰贏、誰輸? maint...
Robustness輸了之後會造成系統不穩定

系統不穩定會有什麼問題?

Copyright@2013 Teddysoft
Copyright@2013 Teddysoft
輕則損失時間、金錢與商譽,
重則可能危害生命安全。
SPECIFICATION
Correctness
Robustness
提升軟體可靠度需同時考慮
Correctness與Robustness這兩個因素
• Correctness
– 軟體產品可以執行規格中所規範的工作或行為
– 可透過Contract Specification來達成

• Robustness...
本課程介紹如何透過例外處理
來增加系統的強健度
練習:請分享一個因為例外
處理不良而造成金錢上、時
間上、精神上損失的經驗
例外處理機制—Exception
Handling Mechanism (EHM)
問題: 請說出一個你熟知的程
式語言的例外處理機制
例外處理機制(EHM)是程式語言用來
支援例外處理的方法
•
•
•
•
•
•

Representation
Definition
Signaling
Propagation
Resolution
Continuation

Copyrig...
1. Representation
• 程式語言表達例外的方法
– Symbol
• strings or numbers

– Data object
• Used to hold error and failure information ...
2. Definition
• 程式設計師如何定義一個例外
– Symbols
• new exceptions are defined as strings or
numbers.

– Data objects and full objec...
3. Signaling
• 產生一個例外(的實例),並且將例外傳給
接收者的指令稱之為:
– throwing, signaling, raising, or triggering

• 例外產生方式有兩種:
– Synchronous ex...
4. Propagation
• If an exception is signaled and not coped
with locally, the exception can be propagated
to the caller of ...
5. Resolution
• Exception resolution or handler binding is a process
of finding a suitable handler in the target, which is...
6. Continuation
• An exception continuation or exception
model specifies the execution flow after
an exception handler ret...
容易搞混且重要的觀念:Fault, Error,
Failure, Exception彼此的關係
cause of failure

fault
(1) design
(2) component

a state may lead to
fai...
以下何者是design fault,何者是component
fault?
1.
2.
3.
4.
5.

除以零 (division by zero)
Index Out of Bound
網路斷線
硬碟空間已滿
檔案不存在

24
Copy...
為什麼要區分design fault與
component fault?
Exception Handling vs. Fault-Tolerant
Programming
• Exception handling deals with component faults
(anticipated exceptions...
Java例外處理機制
Java Exception Handling: The try
Statement (before JDK 7)

Copyright@2013 Teddysoft

28
Java Exception Handling: The
try_multi_catch in JDK 7

Copyright@2013 Teddysoft

29
Java Exception Handling: The
try_with_resources in JDK 7

Copyright@2013 Teddysoft

30
Java Exception Class Hierarchy
Throwable

Exception

IOException

checked

SQLException

Error

RuntimeException

IndexOut...
Use checked exceptions for
recoverable conditions and
run-time exceptions for
programming errors
使用Checked Exception須遵循Handle-or-Declare Rule

declare

handle
Copyright@2013 Teddysoft
程式如果違反Handle-orDeclare Rule將被Java Compiler
視為語法錯誤
例外處理的4+1觀點
Usage (用途)
Design (設計)
Handling (處理)
Tool-Support (工具支援)
Process (流程)
為什麼例外處理這麼難?
Usage View (例外用途觀點)
Exception, 真的只是用來代表
「例外狀況」嗎?
練習:分組討論要如何處理
EOFException與
InterruptedException?
EOFException範例
public void readDataFromFile(String aFileName){
try (DataInputStream input = new DataInputStream
(new FileI...
InterruptedException範例
public void sleepMillisecond(int ms){
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
//...
Usage View
• Failure
• Notification
– EOFException
– InterruptedException

Copyright@2013 Teddysoft
案情沒有那麼單純,請看另一個
EOFException範例
public void fetchRawBytesAndSetupMessage(DataInputStream aIS)
throws IOException, InvalidPac...
Context 決定 exception的用途
Design View
(例外設計觀點)
Design View
• Declared:
– 例外有宣告在元件的介面規範中
– 又稱為anticipated或expected例外
– 代表component fault

• Undeclared:
– 例外沒有宣告在元件的介面規範中
...
Declared Exception
public void fetchRawBytesAndSetupMessage(DataInputStream aIS)
throws IOException, InvalidPacketExceptio...
Undeclared Exception

(1/2)

public Hamburg createHamburger(String type) {
Hamburg ham = null;

}

switch (type) {
case "p...
Undeclared Exception

(2/2)

public void deposit(int value) {
if (value < 0 ) {
throw new IllegalArgumentException
("存款金額不...
你在做例外處理還是容錯設計?
public void deposit(int value) {
if (value < 0 ) {
throw new IllegalArgumentException
("存款金額不得為負數.");
}
UC
...
你在做例外處理還是容錯設計?

(2/2)

public String execute(String cmd) throws
D

C

D

UC

IOException,

NullPointerException,
IllegalAr...
Design View小結
撇開程式語言是否區分checked與
unchecked例外,唯有將例外宣告在介面
上(或以某種形式存在程式或文件中),
在設計階段程式設計師才有機會知道要
如何來因應可能會遭遇到的異常狀況。

Copyright@...
Handling View
(例外處理觀點)
Handling View
• Recoverability (可恢復性)
– recoverable, unrecoverable(irrecoverable)

• Exception handling constructs in
lang...
Handling View之
Recoverability
Recoverability:爽到你,艱苦到我

Thanks Linda
Copyright@2013 Teddysoft
Recoverability:Callee與Caller都要負責任

Thanks Linda
Copyright@2013 Teddysoft
Recoverability思考練習1
Caller: InterruptedException是一
個可以被修復的例外狀況嗎?

public void sleepMillisecond(int ms){
try {
Callee
Threa...
Recoverability思考練習2
public void readDataFromFile(String aFileName){
try (DataInputStream input = new DataInputStream
(new ...
Recoverability思考練習3
public void fetchRawBytesAndSetupMessage(DataInputStream aIS)
throws IOException, InvalidPacketExcepti...
Handling View之
Exception Handling Constructs
and Utilities
不同的程式語言有不同的例外處理構件
• Java/C#
– try-catch-finally

• C++
– try-catch
– destructor

• Eiffel
– Exception handlers in Eiffel a...
重新思考try-catch-finally的責任與分工
• Try
– Implement requirements (can have alternatives)
– Prepare state recovery (e.g., make a ...
例外處理也是一種程式設計,需要程式
設計能力與軟體元件支援
• 設計技巧
– Memento、Smart pointer、Check point、etc.
– Exception hierarchy
– EH best practices an...
Handling View小結
要判斷一個例外是否為一個可修復的狀
況,是例外處理「設計」的第一個步驟,
但這個判斷依據並不是一件容易的事。

確定了例外的recoverability之後,接著
可利用程式語言構件與軟體元件的協助
來實作例外處...
Tool-Support View
(例外工具支援觀點)
Tool-Support View
• Java語言的tool-support
– 區分Checked與unchecked例外

Copyright@2013 Teddysoft
Java與C#程式比較

Copyright@2013 Teddysoft
Java語言的Tool-Support所造成的後遺症
• Interface evolution problem
• Ignored checked exception

68
Copyright@2013 Teddysoft
Tool-Support View小結
為了提高軟體的強健度,開發人員
需要一個提醒機制,告知那些操作
有可能產生例外,否則開發人員更
容易忽略例外處理,只能等runtime
發生錯誤時再回頭修補。

Copyright@2013 Teddys...
Process View
(開發流程觀點)
Process View
• Waterfall VS. IID (iterative and
incremental development)
• 如何在IID流程中規劃例外處理?
– I will handle this exception...
以Scrum為例
• Story
– Normal scenarios
– Failure scenarios

• 這個sprint先做normal scenarios,下個
sprint再做failure scenarios
敏捷開發讓例外...
「先做normal scenarios,再做failure
scenarios」實務上有何問題?

Copyright@2013 Teddysoft
做normal scenarios的時候遇到例外
怎麼辦?
public void fetchRawBytesAndSetupMessage(DataInputStream aIS)
throws IOException, InvalidPac...
Process View小結
IID或敏捷開發法不會讓例外處理變
得更簡單。若團隊沒有一套例外處
理設計規範,則很有可能反而會降
低系統的強健度。

Copyright@2013 Teddysoft
例外處理的4+1種觀點結論
好難…Orz

例外處理…
建立例外處理中心思想—
Staged Robustness Model
例外處理的目標
例外處理的目標
Robustness Levels (強健度等級)
3

BehaviorRecovery

Service is delivered under the
presence of exceptions

2

State is correct ...
Robustness levels of components
Element

RL G0

RL G1

RL G2

RL G3

name

undefined

error-reporting

state-recovery

beh...
Upgrading and degrading
exception handling goals
restore state, clean up,
and keep programs alive

attempt retries

fail-f...
Applicability for the robustness levels
RL

Applicability

 In the early stage of system development
 Prototyping
G1
 A...
強健度等級小結
Consequences
• Robustness without costly up-front design
• Guiding exception handling implementation

• Independent of lan...
Bad Smells and Refactorings
Refactoring基本觀念
Bad Smells and Refactorings
Refactoring基本觀念
What is Refactoring
• Improving the internal structure of a
software system without altering its
external behavior [fowler...
Refactoring and EH Refactoring
Refactoring
Normal
Behavior

EH Refactoring
Exceptional
Behavior
Behavior

89
Copyright@201...
EH Smells, Refactorings, and RL
EH smell
Return code
Ignored checked
exception
Unprotected main
program
Dummy handler
Nest...
Smell: Return Code
public int withdraw(int amount) {

if (amount > this.balance)
return -1;
else {
this.balance = this.bal...
Refactoring: Replace Error Code with
Exception
public int withdraw(int amount) throws
NotEnoughMoneyException {
if (amount...
Smell: Ignored Checked Exception
public void writeFile(String fileName, String data) {
Writer writer = null;
try {
writer ...
Replace Ignored Checked Exception
with Unchecked Exception
public void writeFile(String fileName, String data) {
Writer wr...
Smell: Unprotected Main Program
static public void main(String[] args) {
MyApp myapp = new MyApp();
myapp.start();
}

95
C...
Avoid Unexpected Termination with
Big Outer Try Block
static public void main(String[] args) {
MyApp myapp = new MyApp();
...
Smell: Dummy Handler
public void m(String aFileName) {
try{
FileInputStream fis = new FileInputStream(new
File(aFileName))...
Replace Dummy Handler with Rethrow
public void m(String aFileName)
{
try{
FileInputStream fis = new
FileInputStream(new
Fi...
Smell: Nested Try Statement
FileInputStream in = null;
try {
in = new FileInputStream(…);
}
finally {
try {
if (in != null...
Replace Nested Try Statement with
Method
FileInputStream in = null;
try {
in = new FileInputStream(…);
}
finally {
try {
i...
Smell: Careless Cleanup
public void cleanup String aFileName) {

try{
FileInputStream fis = new
FileInputStream(new
File(a...
Replace Careless Cleanup with Guaranteed
Cleanup
public void cleanup String aFileName) {

public void cleanup String aFile...
練習:尋找 Smells
練習:EH Refactoring
Advanced Refactoring
Introduce Checkpoint Class
public void foo () throws FailureException {
try {
/* code that may change the state of the obj...
Smell: Spare handler

try { /* primary */ }
catch (SomeException e) {
try {/* alternative */}
catch(AnotherException e) {
...
Introduce Resourceful Try Clause
try { /* primary */ }
catch (SomeException e) {
try {/* alternative */}
catch(AnotherExce...
參考資料

Copyright@2013 Teddysoft
複習
• 例外處理基本觀念
– EHM、fault、error、failure、exception

• 例外處理的4+1觀點
• 建立例外處理中心思想—Staged Robustness
Model
• EH Bad Smells and R...
泰迪軟體敏捷開發訓練藍圖

Copyright@2013 Teddysoft
謝謝,再見 XD
Upcoming SlideShare
Loading in …5
×

201309 130917200320-phpapp01

712 views
639 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
712
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
9
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

201309 130917200320-phpapp01

  1. 1. 例外處理設計與重構實作班 Teddy Chen Sept. 14 2013
  2. 2. Copyright@2013 Teddysoft
  3. 3. 我是誰 • 2012年7月成立泰迪軟體,從事敏捷開發顧問、教 育訓練、軟體工具導入等服務。 • 2012年6月,出版暢銷書「笑談軟體工程:敏捷方 法的逆襲」。 • 2012年4月起,多次講授Scrum課程,與學員互動氣 氛佳,滿意度高。 • 超過17年design pattern實務經驗,曾在pattern領域 最著名的PLoP國際研討會發表論文。 – PLoP 2004:A Pattern Language for Personal Authoring in E-Learning. – Asia PLoP 2011:Emerging Patterns of Continuous Integration for Cross-Platform Software Development. • • • • 2009年取得Certified ScrumMaster。 2008年4月起迄今,5年以上Scrum業界導入經驗。 2008年取得台北科技大學資工博士。 2007年起經營「搞笑談軟工」部落格。 Copyright@2013 Teddysoft
  4. 4. 課程內容 • 例外處理基本觀念 • 例外處理的4+1觀點 • 建立例外處理中心思想—Staged Robustness Model • EH Bad Smells and Refactoring's Copyright@2013 Teddysoft
  5. 5. 例外處理基本觀念
  6. 6. 一個軟體開發專案存在著很多互相競爭 且衝突的非功能需求 robustness time-to-market, iterative & incremental design, (exception handling) 誰贏、誰輸? maintainability, etc. Copyright@2013 Teddysoft
  7. 7. Robustness輸了之後會造成系統不穩定 系統不穩定會有什麼問題? Copyright@2013 Teddysoft
  8. 8. Copyright@2013 Teddysoft
  9. 9. 輕則損失時間、金錢與商譽, 重則可能危害生命安全。
  10. 10. SPECIFICATION Correctness Robustness
  11. 11. 提升軟體可靠度需同時考慮 Correctness與Robustness這兩個因素 • Correctness – 軟體產品可以執行規格中所規範的工作或行為 – 可透過Contract Specification來達成 • Robustness – 軟體系統應付異常狀況的能力 – 可透過Exception Handling來達成 Copyright@2013 Teddysoft
  12. 12. 本課程介紹如何透過例外處理 來增加系統的強健度
  13. 13. 練習:請分享一個因為例外 處理不良而造成金錢上、時 間上、精神上損失的經驗
  14. 14. 例外處理機制—Exception Handling Mechanism (EHM)
  15. 15. 問題: 請說出一個你熟知的程 式語言的例外處理機制
  16. 16. 例外處理機制(EHM)是程式語言用來 支援例外處理的方法 • • • • • • Representation Definition Signaling Propagation Resolution Continuation Copyright@2013 Teddysoft
  17. 17. 1. Representation • 程式語言表達例外的方法 – Symbol • strings or numbers – Data object • Used to hold error and failure information only. • Raised by a language keyword. – Full object • Encapsulate signaling, propagation, and continuation behaviors of exceptions in the class definition. Copyright@2013 Teddysoft
  18. 18. 2. Definition • 程式設計師如何定義一個例外 – Symbols • new exceptions are defined as strings or numbers. – Data objects and full objects • a class is used to define an exception. Copyright@2013 Teddysoft
  19. 19. 3. Signaling • 產生一個例外(的實例),並且將例外傳給 接收者的指令稱之為: – throwing, signaling, raising, or triggering • 例外產生方式有兩種: – Synchronous exception • A direct result of performing the instruction. – Asynchronous exception • Produced by the runtime environment upon encountering an internal error or by stopping or suspending a thread. Copyright@2013 Teddysoft
  20. 20. 4. Propagation • If an exception is signaled and not coped with locally, the exception can be propagated to the caller of the signaling method. • Exception propagation can be explicit or implicit (or automatic). – Explicit: a receiver must explicitly re-throw an unhandled received exception for further propagation – Implicit: an unhandled exception is automatically propagated. Copyright@2013 Teddysoft
  21. 21. 5. Resolution • Exception resolution or handler binding is a process of finding a suitable handler in the target, which is resolved by static scoping at compiler-time, dynamic invocation chain at runtime, or both. • There are two methods to dynamically find a handler: stack unwinding and stack cutting. – Stack unwinding pops the stack frames to search for the matching exception handler – Stack cutting maintains a list of registered exception handlers and looks up the list for a suitable exception handler. Copyright@2013 Teddysoft
  22. 22. 6. Continuation • An exception continuation or exception model specifies the execution flow after an exception handler returns its control. – Termination model – Retry model – Resumption model Copyright@2013 Teddysoft
  23. 23. 容易搞混且重要的觀念:Fault, Error, Failure, Exception彼此的關係 cause of failure fault (1) design (2) component a state may lead to failure error service departs from specification failure represented by exception Copyright@2013 Teddysoft
  24. 24. 以下何者是design fault,何者是component fault? 1. 2. 3. 4. 5. 除以零 (division by zero) Index Out of Bound 網路斷線 硬碟空間已滿 檔案不存在 24 Copyright@2013 Teddysoft
  25. 25. 為什麼要區分design fault與 component fault?
  26. 26. Exception Handling vs. Fault-Tolerant Programming • Exception handling deals with component faults (anticipated exceptions) • Fault-tolerant programming deals with both component and design faults (anticipated and unanticipated exceptions) 範圍不同、成本不同! 26 Copyright@2013 Teddysoft
  27. 27. Java例外處理機制
  28. 28. Java Exception Handling: The try Statement (before JDK 7) Copyright@2013 Teddysoft 28
  29. 29. Java Exception Handling: The try_multi_catch in JDK 7 Copyright@2013 Teddysoft 29
  30. 30. Java Exception Handling: The try_with_resources in JDK 7 Copyright@2013 Teddysoft 30
  31. 31. Java Exception Class Hierarchy Throwable Exception IOException checked SQLException Error RuntimeException IndexOutOfBoundsException unchecked Copyright@2013 Teddysoft NullPointerException 31
  32. 32. Use checked exceptions for recoverable conditions and run-time exceptions for programming errors
  33. 33. 使用Checked Exception須遵循Handle-or-Declare Rule declare handle Copyright@2013 Teddysoft
  34. 34. 程式如果違反Handle-orDeclare Rule將被Java Compiler 視為語法錯誤
  35. 35. 例外處理的4+1觀點 Usage (用途) Design (設計) Handling (處理) Tool-Support (工具支援) Process (流程)
  36. 36. 為什麼例外處理這麼難?
  37. 37. Usage View (例外用途觀點) Exception, 真的只是用來代表 「例外狀況」嗎?
  38. 38. 練習:分組討論要如何處理 EOFException與 InterruptedException?
  39. 39. EOFException範例 public void readDataFromFile(String aFileName){ try (DataInputStream input = new DataInputStream (new FileInputStream(aFileName))) { while (true) { System.out.print(input.readChar()); } } catch (EOFException e) { // How to "handle" this exception? } catch (IOException e) { e.printStackTrace(); } } Copyright@2013 Teddysoft
  40. 40. InterruptedException範例 public void sleepMillisecond(int ms){ try { Thread.sleep(ms); } catch (InterruptedException e) { // How to "handle" this exception? } } Copyright@2013 Teddysoft
  41. 41. Usage View • Failure • Notification – EOFException – InterruptedException Copyright@2013 Teddysoft
  42. 42. 案情沒有那麼單純,請看另一個 EOFException範例 public void fetchRawBytesAndSetupMessage(DataInputStream aIS) throws IOException, InvalidPacketException { int length = aIS.readInt(); setMessageLength(length); byte[] messageBody = new byte[length]; try { aIS.readFully(messageBody); } catch (EOFException e) { throw new InvalidPacketException("Data Underflow"); } setMessage(new String(messageBody)); } Copyright@2013 Teddysoft
  43. 43. Context 決定 exception的用途
  44. 44. Design View (例外設計觀點)
  45. 45. Design View • Declared: – 例外有宣告在元件的介面規範中 – 又稱為anticipated或expected例外 – 代表component fault • Undeclared: – 例外沒有宣告在元件的介面規範中 – 又稱為unanticipated或unexpected例外 – 代表design fault Copyright@2013 Teddysoft
  46. 46. Declared Exception public void fetchRawBytesAndSetupMessage(DataInputStream aIS) throws IOException, InvalidPacketException { int length = aIS.readInt(); setMessageLength(length); byte[] messageBody = new byte[length]; try { aIS.readFully(messageBody); } catch (EOFException e) { throw new InvalidPacketException("Data Underflow"); } setMessage(new String(messageBody)); } Copyright@2013 Teddysoft
  47. 47. Undeclared Exception (1/2) public Hamburg createHamburger(String type) { Hamburg ham = null; } switch (type) { case "pork": ham = new SweetPorkHamburger(); break; case "beef": ham = new SweetBeefHamburger(); break; default: throw new RuntimeException ("Unsupported hamburger type:" + type); } return ham; Copyright@2013 Teddysoft
  48. 48. Undeclared Exception (2/2) public void deposit(int value) { if (value < 0 ) { throw new IllegalArgumentException ("存款金額不得為負數."); } // doing normal deposit logic } Copyright@2013 Teddysoft
  49. 49. 你在做例外處理還是容錯設計? public void deposit(int value) { if (value < 0 ) { throw new IllegalArgumentException ("存款金額不得為負數."); } UC UD // doing normal deposit logic } public void deposit(int value) throws llegalArgumentException { if (value < 0 ) { D throw new IllegalArgumentException ("存款金額不得為負數."); UC } // doing normal deposit logic } Copyright@2013 Teddysoft (1/2)
  50. 50. 你在做例外處理還是容錯設計? (2/2) public String execute(String cmd) throws D C D UC IOException, NullPointerException, IllegalArgumentException; Copyright@2013 Teddysoft
  51. 51. Design View小結 撇開程式語言是否區分checked與 unchecked例外,唯有將例外宣告在介面 上(或以某種形式存在程式或文件中), 在設計階段程式設計師才有機會知道要 如何來因應可能會遭遇到的異常狀況。 Copyright@2013 Teddysoft
  52. 52. Handling View (例外處理觀點)
  53. 53. Handling View • Recoverability (可恢復性) – recoverable, unrecoverable(irrecoverable) • Exception handling constructs in languages and utilities – Roles, responsibilities, and collaborations (e.g., try, catch, finally in Java) Copyright@2013 Teddysoft
  54. 54. Handling View之 Recoverability
  55. 55. Recoverability:爽到你,艱苦到我 Thanks Linda Copyright@2013 Teddysoft
  56. 56. Recoverability:Callee與Caller都要負責任 Thanks Linda Copyright@2013 Teddysoft
  57. 57. Recoverability思考練習1 Caller: InterruptedException是一 個可以被修復的例外狀況嗎? public void sleepMillisecond(int ms){ try { Callee Thread.sleep(ms); } catch (InterruptedException e) { // How to "handle" this exception? } } Copyright@2013 Teddysoft
  58. 58. Recoverability思考練習2 public void readDataFromFile(String aFileName){ try (DataInputStream input = new DataInputStream (new FileInputStream(aFileName))) { while (true) { System.out.print(input.readChar()); } } Callee catch (EOFException e) { // How to "handle" this exception? } catch (IOException e) { Caller: EOFException與 e.printStackTrace(); IOException的recoverability? } } Copyright@2013 Teddysoft
  59. 59. Recoverability思考練習3 public void fetchRawBytesAndSetupMessage(DataInputStream aIS) throws IOException, InvalidPacketException { Callee int length = aIS.readInt(); setMessageLength(length); byte[] messageBody = new byte[length]; try { Caller: EOFException與 aIS.readFully(messageBody); IOException的recoverability? } catch (EOFException e) { throw new InvalidPacketException("Data Underflow"); } setMessage(new String(messageBody)); } Copyright@2013 Teddysoft
  60. 60. Handling View之 Exception Handling Constructs and Utilities
  61. 61. 不同的程式語言有不同的例外處理構件 • Java/C# – try-catch-finally • C++ – try-catch – destructor • Eiffel – Exception handlers in Eiffel are attached at the method level and all exceptions are caught by one handler. 61 Copyright@2013 Teddysoft
  62. 62. 重新思考try-catch-finally的責任與分工 • Try – Implement requirements (can have alternatives) – Prepare state recovery (e.g., make a check point) • Catch – Perform error and fault handling – Report exceptional conditions – Control retry flow • Finally – Release resources – Drop check points if any 62 Copyright@2013 Teddysoft
  63. 63. 例外處理也是一種程式設計,需要程式 設計能力與軟體元件支援 • 設計技巧 – Memento、Smart pointer、Check point、etc. – Exception hierarchy – EH best practices and patterns • 工具 – – – – Logging (e.g., Log4j) Common error formats and dialogs EH smell detection Marker & resolution 63 Copyright@2013 Teddysoft
  64. 64. Handling View小結 要判斷一個例外是否為一個可修復的狀 況,是例外處理「設計」的第一個步驟, 但這個判斷依據並不是一件容易的事。 確定了例外的recoverability之後,接著 可利用程式語言構件與軟體元件的協助 來實作例外處理程式碼。 Copyright@2013 Teddysoft
  65. 65. Tool-Support View (例外工具支援觀點)
  66. 66. Tool-Support View • Java語言的tool-support – 區分Checked與unchecked例外 Copyright@2013 Teddysoft
  67. 67. Java與C#程式比較 Copyright@2013 Teddysoft
  68. 68. Java語言的Tool-Support所造成的後遺症 • Interface evolution problem • Ignored checked exception 68 Copyright@2013 Teddysoft
  69. 69. Tool-Support View小結 為了提高軟體的強健度,開發人員 需要一個提醒機制,告知那些操作 有可能產生例外,否則開發人員更 容易忽略例外處理,只能等runtime 發生錯誤時再回頭修補。 Copyright@2013 Teddysoft
  70. 70. Process View (開發流程觀點)
  71. 71. Process View • Waterfall VS. IID (iterative and incremental development) • 如何在IID流程中規劃例外處理? – I will handle this exception when I have time.  Never happens! Copyright@2013 Teddysoft
  72. 72. 以Scrum為例 • Story – Normal scenarios – Failure scenarios • 這個sprint先做normal scenarios,下個 sprint再做failure scenarios 敏捷開發讓例外處理變得好簡單啊! Copyright@2013 Teddysoft 才怪
  73. 73. 「先做normal scenarios,再做failure scenarios」實務上有何問題? Copyright@2013 Teddysoft
  74. 74. 做normal scenarios的時候遇到例外 怎麼辦? public void fetchRawBytesAndSetupMessage(DataInputStream aIS) throws IOException, InvalidPacketException { int length = aIS.readInt(); setMessageLength(length); byte[] messageBody = new byte[length]; try { aIS.readFully(messageBody); } catch (EOFException e) { throw new InvalidPacketException("Data Underflow"); } setMessage(new String(messageBody)); } Copyright@2013 Teddysoft
  75. 75. Process View小結 IID或敏捷開發法不會讓例外處理變 得更簡單。若團隊沒有一套例外處 理設計規範,則很有可能反而會降 低系統的強健度。 Copyright@2013 Teddysoft
  76. 76. 例外處理的4+1種觀點結論
  77. 77. 好難…Orz 例外處理…
  78. 78. 建立例外處理中心思想— Staged Robustness Model 例外處理的目標
  79. 79. 例外處理的目標
  80. 80. Robustness Levels (強健度等級) 3 BehaviorRecovery Service is delivered under the presence of exceptions 2 State is correct under the presence of exceptions 1 All exceptions are reported StateRecovery ErrorReporting Undefined 0 Robustness unpredictable 80 Copyright@2013 Teddysoft
  81. 81. Robustness levels of components Element RL G0 RL G1 RL G2 RL G3 name undefined error-reporting state-recovery behavior-recovery service failing implicitly or explicitly failing explicitly failing explicitly delivered state unknown or incorrect unknown or incorrect correct correct lifetime terminated or continued terminated continued continued NA (1) propagating all unhandled (1) error exceptions, and recovery (2) catching and and reporting them in (2) cleanup the main program howachieved also known NA as failing-fast Copyright@2013 Teddysoft weakly tolerant and organized panic (1) retry, and/or (2) design diversity, data diversity, and functional diversity strongly tolerant, self-repair, selfhealing, resilience, and retry
  82. 82. Upgrading and degrading exception handling goals restore state, clean up, and keep programs alive attempt retries fail-fast; keep user informed G0 G1 G2 state restoration or cleanup fail G3 all retries fail 82 Copyright@2013 Teddysoft
  83. 83. Applicability for the robustness levels RL Applicability  In the early stage of system development  Prototyping G1  Applying an evolutionary development methodology  Time-to-market  Outsourcing G2  Designing utility components used in different application domains  Behavior-recovery actions should be administered by the user  Developing mission critical systems  Designing components having sufficient application context to G3 recover from behavioral failures, e.g., application controllers  Behavior-recovery actions are inappropriate to be administered by the user 83 Copyright@2013 Teddysoft
  84. 84. 強健度等級小結
  85. 85. Consequences • Robustness without costly up-front design • Guiding exception handling implementation • Independent of languages Copyright@2013 Teddysoft
  86. 86. Bad Smells and Refactorings Refactoring基本觀念 Bad Smells and Refactorings
  87. 87. Refactoring基本觀念
  88. 88. What is Refactoring • Improving the internal structure of a software system without altering its external behavior [fowler] • Steps to perform refactoring: – Identifying code smells – Applying refactorings to remove the smells – Verifying satisfaction Copyright@2013 Teddysoft
  89. 89. Refactoring and EH Refactoring Refactoring Normal Behavior EH Refactoring Exceptional Behavior Behavior 89 Copyright@2013 Teddysoft
  90. 90. EH Smells, Refactorings, and RL EH smell Return code Ignored checked exception Unprotected main program Dummy handler Nested try block Refactoring Replace Error Code with Exception Replace Ignored Checked Exception with Unchecked Exception Avoid Unexpected Termination with Big Outer Try Block Replace Dummy Handler with Rethrow Replace Nested Try Block with Method Replace Careless Cleanup with Guaranteed Careless Cleanup Cleanup Ignored checked exception Introduce Checkpoint Class Dummy handler Spare handler Introduce Resourceful Try Clause Copyright@2013 Teddysoft RL G1 G1 G1 G1 G2 G2 G2 G3 90
  91. 91. Smell: Return Code public int withdraw(int amount) { if (amount > this.balance) return -1; else { this.balance = this.balance – amount; return this.balance; } } 91 Copyright@2013 Teddysoft
  92. 92. Refactoring: Replace Error Code with Exception public int withdraw(int amount) throws NotEnoughMoneyException { if (amount > this.balance) throw new NotEnoughMoneyException (); this.balance = this.balance – amount; } 92 Copyright@2013 Teddysoft
  93. 93. Smell: Ignored Checked Exception public void writeFile(String fileName, String data) { Writer writer = null; try { writer = new FileWriter(fileName); // may throw IOException writer.write(data); // may throw IOException } catch (IOException e) { // ignoring the exception } finally { // code for cleanup } } 93 Copyright@2013 Teddysoft
  94. 94. Replace Ignored Checked Exception with Unchecked Exception public void writeFile(String fileName, String data) { Writer writer = null; try { writer = new FileWriter(fileName); /* may throw an IOException */ writer.write(data); /* may throw an IOException */ } catch (IOException e) { /* ignoring the exception */ } } ↓ public void writeFile(String fileName, String data) { Writer writer = null; try { writer = new FileWriter(fileName); /* may throw an IOException */ writer.write(data); /* may throw an IOException */ } catch (IOException e) { throw new UnhandledException(e, “message”); } } Copyright@2013 Teddysoft 94
  95. 95. Smell: Unprotected Main Program static public void main(String[] args) { MyApp myapp = new MyApp(); myapp.start(); } 95 Copyright@2013 Teddysoft
  96. 96. Avoid Unexpected Termination with Big Outer Try Block static public void main(String[] args) { MyApp myapp = new MyApp(); myapp.start(); } ↓ static public void main(String[] args) { try { MyApp myapp = new MyApp(); myapp.start(); } catch (Throwable e) { /* displaying and/or logging the exception */ } } Copyright@2013 Teddysoft 96
  97. 97. Smell: Dummy Handler public void m(String aFileName) { try{ FileInputStream fis = new FileInputStream(new File(aFileName)); } catch(IOException e){ e.printStackTrace(); } finally{ // cleanup } } 97 Copyright@2013 Teddysoft
  98. 98. Replace Dummy Handler with Rethrow public void m(String aFileName) { try{ FileInputStream fis = new FileInputStream(new File(aFileName)); } catch(IOException e){ e.printStackTrace(); } finally{ // cleanup } } public void m(String aFileName) { try{ FileInputStream fis = new FileInputStream(new File(aFileName)); } catch(IOException e){ throw new UnhandledException (e, “message”); } finally{ // cleanup } } 98 Copyright@2013 Teddysoft
  99. 99. Smell: Nested Try Statement FileInputStream in = null; try { in = new FileInputStream(…); } finally { try { if (in != null) in.close (); } catch (IOException e) { /* log the exception */ } } 99 Copyright@2013 Teddysoft
  100. 100. Replace Nested Try Statement with Method FileInputStream in = null; try { in = new FileInputStream(…); } finally { try { if (in != null) in.close (); } catch (IOException e) { /* log the exception */ } } FileInputStream in = null; try { in = new FileInputStream(…); } finally { closeIO (in); } private void closeIO (Closeable c) { try { if (c != null) c.close (); } catch (IOException e) { /* log the exception */ } } 100 Copyright@2013 Teddysoft
  101. 101. Smell: Careless Cleanup public void cleanup String aFileName) { try{ FileInputStream fis = new FileInputStream(new File(aFileName)); fis.close(); } catch(IOException e){ throw new RuntimeException(e); } } 101 Copyright@2013 Teddysoft
  102. 102. Replace Careless Cleanup with Guaranteed Cleanup public void cleanup String aFileName) { public void cleanup String aFileName) { try{ FileInputStream fis = new FileInputStream(new File(aFileName)); FileInputStream fis = null; try{ fis = new FileInputStream(new File(aFileName)); } catch(IOException e){ throw new RuntimeException(e); } finally { closeIO(fis); } fis.close(); } catch(IOException e){ throw new RuntimeException(e); } } } 102 Copyright@2013 Teddysoft
  103. 103. 練習:尋找 Smells
  104. 104. 練習:EH Refactoring
  105. 105. Advanced Refactoring
  106. 106. Introduce Checkpoint Class public void foo () throws FailureException { try { /* code that may change the state of the object */ } catch (AnException e) { throw new FailureException(e); } finally {/* code for cleanup */} } ↓ public void foo () throws FailureException { Checkpoint cp = new Checkpoint (/* parameters */); try { cp. establish (); /* establish a checkpoint */ /* code that may change the state of the object */ } catch (AnException e) { cp.restore (); /* restore the checkpoint */ throw new FailureException(e); } finally { cp.drop(); } } Copyright@2013 Teddysoft 106
  107. 107. Smell: Spare handler try { /* primary */ } catch (SomeException e) { try {/* alternative */} catch(AnotherException e) { throw new FailureException(e); } } 107 Copyright@2013 Teddysoft
  108. 108. Introduce Resourceful Try Clause try { /* primary */ } catch (SomeException e) { try {/* alternative */} catch(AnotherException e) { throw new FailureException(e); } } ↓ int attempt = 0; int maxAttempt = 2; boolean retry = false; do { try { retry = false; if (attempt == 0) { /* primary */ } else { /* alternative */ } } catch (SomeException e) { attempt++; retry = true; if (attempt > maxAttempt) throw new FailureException (e); } } while (attempt<= maxAttempt && retry) Copyright@2013 Teddysoft 108
  109. 109. 參考資料 Copyright@2013 Teddysoft
  110. 110. 複習 • 例外處理基本觀念 – EHM、fault、error、failure、exception • 例外處理的4+1觀點 • 建立例外處理中心思想—Staged Robustness Model • EH Bad Smells and Refactorings
  111. 111. 泰迪軟體敏捷開發訓練藍圖 Copyright@2013 Teddysoft
  112. 112. 謝謝,再見 XD

×