Powerful Exceptions: an Overview

Damien Cassou, St├ęphane Ducasse and Luc Fabresse http://stephane.ducasse.free.fr

Exceptions

What You Will Learn

API Overview

  [ doSomething ] on: ExceptionClass do: [ :ex | something ]
anException signal

Convenient messages:

Catching Example

  [ do something ] on: ExceptionClass do: [ :ex | something ]

Example:

  | x y |
  x := 7.
  y := 0.
  [ x / y ] 
      on: ZeroDivide
      do: [ :exception | Transcript show: exception description; cr.
           0 ]
   > 0

Signaling an Exception

To raise an exception:

  (AuthorNameRequest new initialAnswer: 'Stef') signal
  (Warning new messageText: 'Pay attention') signal

Signaling an Exception

Usually classes propose a shortcut

  OutOfMemory signal.
  Warning signal: 'description of the exception'

Testing That an Exception Occurs

SUnit offers should:raise: and shouldnt:raise: to check occurrence of exceptions.

testNameOfMonth

  self assert: (Date nameOfMonth: 1) equals: #January.	

  self 
    shouldnt: [ Date nameOfMonth: 2 ] 
    raise: SubscriptOutOfBounds.
  self 
    should: [ Date nameOfMonth: 13 ] 
    raise: SubscriptOutOfBounds.

Kinds of Exceptions

Exceptions are Real Objects

When you send an unknown message Point new strangeAndBizarre

ProtoObject >> doesNotUnderstand: aMessage

  ^ MessageNotUnderstood new 
       message: aMessage;
       receiver: self;
       signal

Deprecation

To support API migration, Pharo uses deprecation When the deprecation setting is on, a warning is raised when a deprecated method is executed

MenuItem >> title: aString
  "Add a title line at the top of this menu."
  self deprecated: 'Use method addTitle: instead' on: '29 september' in: #Pharo40. 
  self addTitle: aString

Deprecation Implementation Use

Create an instance of Deprecation and signal it

deprecated: anExplanationString on: date in: version
  "Warn that the sending method has been deprecated"
  (Deprecation
      method: thisContext sender method
      explanation: anExplanationString
      on: date
      in: version) signal

Exception Sets

  [ do some work ]
      on: ZeroDivide, Warning
      do: [ :ex | what you want ]

Or

  | exceptionSets |
  exceptionSets := ExceptionSet with: ZeroDivide with: Warning.
  [do some work]
      on: exceptionSets
      do: [ :ex | what you want ]

A Nice Helper: ensure:

spyOn: aBlock
  "Profile system activity during execution of aBlock."
  self startProfiling.
  aBlock ensure: [ self stopProfiling ]

Another nice Helper ifCurtailed:

wait
  "Schedule this Delay, then wait on its semaphore. The current process will be suspended for the amount of time specified when this Delay was created."

  self schedule.
  [ delaySemaphore wait ] ifCurtailed: [ self unschedule ]

Exception Lookup

Handling Exception

Just for your information ;)

Within an handler [ aaa ] on: anExceptionClass do: [ anHandler ], we can:

Returning From an Exception

[ Notification signal. 'Value from protected block' ]
  on: Notification
  do: [ :ex |ex return: 'Value from handler' ]
  
  >  'Value from handler'

We return a different string on normal or notification

Resuming from Resumable Exception

Warning, Notification and subclasses are resumable

[ Notification signal. 'Value from protected block' ]
		on: Notification
		do: [ :ex | ex resume: 'Value from handler' ]

> 'Value from protected Block'.

What You Should Know

Raising

anException signal

Installing:

[ doSomething ] on: ExceptionClass do: [ :ex | something ]

/