Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encapsulation and Exceptions

I'm designing my own OO language and was happily going along until I hit exceptions. It seems to me that exceptions break encapsulation.

For example, if class A has an object of class B, B has C, and C has X, which throws an exception to A, the code in A must not only know about X but also B and C to handle it correctly. You can tell this because if you replace C with D, A exception's handler will have to change to extract the relevant information from the call stack.

The only way I can think of around this problem is to have exceptions as part of the class' API so that they propagate back up the calling stack one caller at a time. And they should re-interrupt the exception in their own terms.

Here's an example. Trend is a class for analyzing statistical trends and it has a method, slope, for calculating the slope of a line from two points.

method slope
    given
        Point 1st
        Point 2nd
    returns
        Number m
    except
        when infinite slope

    m gets
        ( 2nd's y - 1st's y ) / ( 2nd's x - 1st's x )
    except
        when any divide by zero
            declare infinite slope
        when overflow of ( 2nd's y - 1st's y )
            declare infinite slope
        when overflow of ( 2nd's x - 1st's x )
            instead do m gets 0
        when overflow of ( 2nd's y - 1st's y ) / ( 2nd's x - 1st's x )
            declare infinite slope
        when any underflow
            instead use 0

end of method slope

Is there a better way to do this?

like image 348
shawnhcorey Avatar asked Jan 20 '26 22:01

shawnhcorey


1 Answers

Real-world exceptions fall into one of three rough categories:

  • System exceptions are thrown when fatal errors in the underlying runtime occur, things like out of memory, stack overflow, or perhaps security violations. These generally shouldn't be caught, and in many cases can't be caught. They basically use the exception system in order to take down the system (relatively) gracefully and report the final stack trace to the developer.

  • Programmatic exceptions are thrown when the code is doing something incorrect. Things like invalid arguments, calling methods on null pointers, out of bounds errors. These shouldn't be caught: instead the code that causes them to be thrown should be fixed. They use the exception system to avoid having a more or less redundant assert system that does most of the same things.

  • Runtime exceptions are thrown when something bad happens that cannot be programmatically prevented. They are thrown when an unexpected circumstance has occurred, but its rare enough that you don't want to clutter up the main API with error codes, etc. These are things like file IO errors, network problems, parse errors, etc. These exceptions will usually be specific to the API that's throwing them. These are the only kind of exceptions that should be typically caught.

If you agree with the above breakdown, then encapsulation only effects the third category. For the other two, the exception isn't caught in code, so it doesn't matter. For the third kind of exception, yes, I think you generally should catch the exception and translate it to different exception that's appropriate the layer that's rethrowing it. This is why most exception systems in other languages support something like "InnerException" where you can attach the previous lower-level exception that led to the current one.

like image 67
munificent Avatar answered Jan 23 '26 12:01

munificent



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!