Next: , Previous: Streams, Up: Tutorial


6.11 Exception handling in Smalltalk

Up to this point of the tutorial, you used the original Smalltalk-80 error signalling mechanism:

        check: num [
            | c |
            c := history
                at: num
                ifAbsent: [ ^self error: 'No such check #' ].
            ^c
        ]

In the above code, if a matching check number is found, the method will answer the object associated to it. If no prefix is found, Smalltalk will unwind the stack and print an error message including the message you gave and stack information.

     CheckingAccount new: 31 "<0x33788>" error: No such check #
     ...blah blah...
     CheckingAccount>>#error:
     [] in Dictionary>>#at:ifAbsent:
     Dictionary(HashedCollection)>>#findIndex:ifAbsent:
     Dictionary>>#at:ifAbsent:
     [] in CheckingAccount>>#check:
     CheckingAccount>>#check:
     UndefinedObject(Object)>>#executeStatements

Above we see the object that received the #error: message, the message text itself, and the frames (innermost-first) running when the error was captured by the system. In addition, the rest of the code in methods like CheckingAccount>>#check: was not executed.

So simple error reporting gives us most of the features we want:

However, there is a more powerful and complex error handling mechanism, that is exception. They are like "exceptions" in other programming languages, but are more powerful and do not always indicate error conditions. Even though we use the term "signal" often with regard to them, do not confuse them with the signals like SIGTERM and SIGINT provided by some operating systems; they are a different concept altogether.

Deciding to use exceptions instead of #error: is a matter of aesthetics, but you can use a simple rule: use exceptions only if you want to provide callers with a way to recover sensibly from certain errors, and then only for signalling those particular errors.

For example, if you are writing a word processor, you might provide the user with a way to make regions of text read-only. Then, if the user tries to edit the text, the objects that model the read-only text can signal a ReadOnlyText or other kind of exception, whereupon the user interface code can stop the exception from unwinding and report the error to the user.

When in doubt about whether exceptions would be useful, err on the side of simplicity; use #error: instead. It is much easier to convert an #error: to an explicit exception than to do the opposite.