Skip to main content
removed excess "s"
Source Link
Jonathan Eunice
  • 9.8k
  • 1
  • 33
  • 42

Yes, throwing exceptions is a good idea. Throw them early, throw them often, throw them eagerly.

I know there's an "exceptions vs. assertions" debate, with some kinds of exceptional behavior (specifically, the ones thought to reflect programming errors) handled by assertions that can be "compiled out" for runtime rather than debugging/testing builds. But the amount of performance consumed in a few extra correctness checks is minimal on modern hardware, and any extra cost is far outweighed by the value of having correct, uncorrupted results. I've never actually met an application codebase for which I'd want (most) checks removed at runtime.

I'm tempted to say I wouldn't want a lot of extra checking and conditionals within the tight loops of numerically intensive code...but that's actually where a lot of numerical errors are generated, and if uncaught there, will propagate outward to effect all results. So even there, checks are worth doing. In fact, some of the best, most efficient numerical algorithms are based on error evaluation.

One final placesplace to be very conscious of extra code is very latency-sensitive code, where extra conditionals can cause pipeline stalls. So, in the middle of operating system, DBMS, and other middleware kernels, and low-level communication/protocol handling. But again, those are some of the places errors are most likely to be observed, and their (security, correctness, and data integrity) effects to be most damaging.

One improvement I have found is to not throw only base-level exceptions. IllegalArgumentException is good, but it can come from essentially anywhere. It doesn't take much in most languages to add custom exceptions. For your person-handling module, say:

public class PersonArgumentException extends IllegalArgumentException {
    public MyException(String message) {
        super(message);
    }
}

Then when someone sees a PersonArgumentException, it's clear where it's coming from. There's a balancing act about how many custom exceptions you want to add, because you don't want to multiply entities unnecessarily (Occam's Razor). Often just a few custom exceptions are enough to signal "this module isn't getting the right data!" or "this module can't do what it's supposed to do!" in a way that is specific and tailored, but not so over-precise that you have to re-implement the entire exception hierarchy. I often come to that small set of custom exceptions by starting with stock exceptions, then scanning the code and realizing that "these N places are raising stock exceptions, but they boil down to the higher-level idea that they're not getting the data they need; let's replace those stock exceptions with a higher-level exception that more clearly communicates what's really going on."

Yes, throwing exceptions is a good idea. Throw them early, throw them often, throw them eagerly.

I know there's an "exceptions vs. assertions" debate, with some kinds of exceptional behavior (specifically, the ones thought to reflect programming errors) handled by assertions that can be "compiled out" for runtime rather than debugging/testing builds. But the amount of performance consumed in a few extra correctness checks is minimal on modern hardware, and any extra cost is far outweighed by the value of having correct, uncorrupted results. I've never actually met an application codebase for which I'd want (most) checks removed at runtime.

I'm tempted to say I wouldn't want a lot of extra checking and conditionals within the tight loops of numerically intensive code...but that's actually where a lot of numerical errors are generated, and if uncaught there, will propagate outward to effect all results. So even there, checks are worth doing. In fact, some of the best, most efficient numerical algorithms are based on error evaluation.

One final places to be very conscious of extra code is very latency-sensitive code, where extra conditionals can cause pipeline stalls. So, in the middle of operating system, DBMS, and other middleware kernels, and low-level communication/protocol handling. But again, those are some of the places errors are most likely to be observed, and their (security, correctness, and data integrity) effects to be most damaging.

One improvement I have found is to not throw only base-level exceptions. IllegalArgumentException is good, but it can come from essentially anywhere. It doesn't take much in most languages to add custom exceptions. For your person-handling module, say:

public class PersonArgumentException extends IllegalArgumentException {
    public MyException(String message) {
        super(message);
    }
}

Then when someone sees a PersonArgumentException, it's clear where it's coming from. There's a balancing act about how many custom exceptions you want to add, because you don't want to multiply entities unnecessarily (Occam's Razor). Often just a few custom exceptions are enough to signal "this module isn't getting the right data!" or "this module can't do what it's supposed to do!" in a way that is specific and tailored, but not so over-precise that you have to re-implement the entire exception hierarchy. I often come to that small set of custom exceptions by starting with stock exceptions, then scanning the code and realizing that "these N places are raising stock exceptions, but they boil down to the higher-level idea that they're not getting the data they need; let's replace those stock exceptions with a higher-level exception that more clearly communicates what's really going on."

Yes, throwing exceptions is a good idea. Throw them early, throw them often, throw them eagerly.

I know there's an "exceptions vs. assertions" debate, with some kinds of exceptional behavior (specifically, the ones thought to reflect programming errors) handled by assertions that can be "compiled out" for runtime rather than debugging/testing builds. But the amount of performance consumed in a few extra correctness checks is minimal on modern hardware, and any extra cost is far outweighed by the value of having correct, uncorrupted results. I've never actually met an application codebase for which I'd want (most) checks removed at runtime.

I'm tempted to say I wouldn't want a lot of extra checking and conditionals within the tight loops of numerically intensive code...but that's actually where a lot of numerical errors are generated, and if uncaught there, will propagate outward to effect all results. So even there, checks are worth doing. In fact, some of the best, most efficient numerical algorithms are based on error evaluation.

One final place to be very conscious of extra code is very latency-sensitive code, where extra conditionals can cause pipeline stalls. So, in the middle of operating system, DBMS, and other middleware kernels, and low-level communication/protocol handling. But again, those are some of the places errors are most likely to be observed, and their (security, correctness, and data integrity) effects to be most damaging.

One improvement I have found is to not throw only base-level exceptions. IllegalArgumentException is good, but it can come from essentially anywhere. It doesn't take much in most languages to add custom exceptions. For your person-handling module, say:

public class PersonArgumentException extends IllegalArgumentException {
    public MyException(String message) {
        super(message);
    }
}

Then when someone sees a PersonArgumentException, it's clear where it's coming from. There's a balancing act about how many custom exceptions you want to add, because you don't want to multiply entities unnecessarily (Occam's Razor). Often just a few custom exceptions are enough to signal "this module isn't getting the right data!" or "this module can't do what it's supposed to do!" in a way that is specific and tailored, but not so over-precise that you have to re-implement the entire exception hierarchy. I often come to that small set of custom exceptions by starting with stock exceptions, then scanning the code and realizing that "these N places are raising stock exceptions, but they boil down to the higher-level idea that they're not getting the data they need; let's replace those stock exceptions with a higher-level exception that more clearly communicates what's really going on."

Source Link
Jonathan Eunice
  • 9.8k
  • 1
  • 33
  • 42

Yes, throwing exceptions is a good idea. Throw them early, throw them often, throw them eagerly.

I know there's an "exceptions vs. assertions" debate, with some kinds of exceptional behavior (specifically, the ones thought to reflect programming errors) handled by assertions that can be "compiled out" for runtime rather than debugging/testing builds. But the amount of performance consumed in a few extra correctness checks is minimal on modern hardware, and any extra cost is far outweighed by the value of having correct, uncorrupted results. I've never actually met an application codebase for which I'd want (most) checks removed at runtime.

I'm tempted to say I wouldn't want a lot of extra checking and conditionals within the tight loops of numerically intensive code...but that's actually where a lot of numerical errors are generated, and if uncaught there, will propagate outward to effect all results. So even there, checks are worth doing. In fact, some of the best, most efficient numerical algorithms are based on error evaluation.

One final places to be very conscious of extra code is very latency-sensitive code, where extra conditionals can cause pipeline stalls. So, in the middle of operating system, DBMS, and other middleware kernels, and low-level communication/protocol handling. But again, those are some of the places errors are most likely to be observed, and their (security, correctness, and data integrity) effects to be most damaging.

One improvement I have found is to not throw only base-level exceptions. IllegalArgumentException is good, but it can come from essentially anywhere. It doesn't take much in most languages to add custom exceptions. For your person-handling module, say:

public class PersonArgumentException extends IllegalArgumentException {
    public MyException(String message) {
        super(message);
    }
}

Then when someone sees a PersonArgumentException, it's clear where it's coming from. There's a balancing act about how many custom exceptions you want to add, because you don't want to multiply entities unnecessarily (Occam's Razor). Often just a few custom exceptions are enough to signal "this module isn't getting the right data!" or "this module can't do what it's supposed to do!" in a way that is specific and tailored, but not so over-precise that you have to re-implement the entire exception hierarchy. I often come to that small set of custom exceptions by starting with stock exceptions, then scanning the code and realizing that "these N places are raising stock exceptions, but they boil down to the higher-level idea that they're not getting the data they need; let's replace those stock exceptions with a higher-level exception that more clearly communicates what's really going on."