Skip to main content
Engineering LibreTexts

12.15: When Not to Use Exceptions

  • Page ID
    45976
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Just because Pharo has exception handling, you should not conclude that it is always appropriate to use. As stated in the introduction to this chapter, we said that exception handling is for exceptional situations. Therefore, the first rule for using exceptions is not to use them for situations that can reasonably be expected to occur in a normal execution.

    Of course, if you are writing a library, what is normal depends on the context in which your library is used. To make this concrete, let’s look at Dictionary as an example: aDictionary at: aKey will signal an Error if aKey is not present. But, you should not write a handler for this error! If the logic of your application is such that there is some possibility that the key will not be in the dictionary, then you should instead use at: aKey ifAbsent: [remedial action].

    In fact, Dictionary»at: is implemented using Dictionary»at:ifAbsent:. aCollection detect: aPredicateBlock is similar: if there is any possibility that the predicate might not be satisfied, you should use aCollection detect: aPredicateBlock ifNone: [remedial action].

    When you write methods that signal exceptions, consider whether you should also provide an alternative method that takes a remedial block as an additional argument, and evaluates it if the normal action cannot be completed. Although this technique can be used in any programming language that supports closures, because Smalltalk uses closures for all its control structures, it is a particularly natural one to use in Smalltalk.

    Another way of avoiding exception handling is to test the precondition of the exception before sending the message that may signal it. For example, in Code 13.9.1, we sent a message to an object using perform:, and handled the MessageNotUnderstood error that might ensue. A much simpler alternative is to check to see if the message is understood before executing the perform:

    Code \(\PageIndex{1}\) (Pharo): Object»performAll: revisited

    performAll: selectorCollection
        selectorCollection
            do: [:each | (self respondsTo: each)
                ifTrue: [self perform: each]]
    

    The primary objection to Code \(\PageIndex{1}\) is efficiency. The implementation of respondsTo: s has to lookup s in the target’s method dictionary to find out if s will be understood. If the answer is yes, then perform: will look it up again. Moreover, the first lookup is implemented in Smalltalk, not in the virtual machine. If this code is in a performance-critical loop, this might be an issue. However, if the collection of messages comes from a user interaction, the speed of performAll: will not be a problem.


    This page titled 12.15: When Not to Use Exceptions is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.