57

Possible Duplicate:
design by contract tests by assert or by exception?

Is there a rule of thumb to follow when deciding to use exceptions instead of asserts (or vice versa). Right now I do only throw if it's something I think will happen during runtime on the user side (like a socket or file error). Almost everything else I use asserts.

Also, if I were to throw an assert, what is a nice standard object to throw? If I recall correctly there is std::logic_error, but is that not a good object to throw? What would I throw for a missing file or unexpected input (such as from the command line instead of a frontend app)?

Null
  • 1,950
  • 9
  • 30
  • 33
  • 1
    related: http://stackoverflow.com/q/8087895/855050, http://stackoverflow.com/q/12062365/855050, http://programmers.stackexchange.com/q/133851/34467 – a06e Aug 18 '15 at 14:15

6 Answers6

67

My rule of thumb:

Exceptions are used for run-time error conditions (IO errors, out of memory, can't get a database connection, etc.).

Assertions are used for coding errors (this method doesn't accept nulls, and the developer passed one anyway).

For libraries with public classes, throw exceptions on the public methods (because it makes sense to do so). Assertions are used to catch YOUR mistakes, not theirs.

EDIT: This may not be entirely clear, due to the null value example. My point is that you use assertions (as others have pointed out) for conditions that should NEVER happen, for conditions that should NEVER make it into production code. These conditions absolutely must fail during unit testing or QA testing.

Mike Hofer
  • 16,477
  • 11
  • 74
  • 110
  • 2
    Could you clarify why public library-methods should throw exceptions? I don't see how one could possibly recover from an illegal argument or bad object state. – Maxpm Jan 30 '12 at 13:44
  • 1
    Certainly. If you're writing the public library method, and someone passes YOU the illegal argument, YOU throw. YOU can't recover from that. Presumably, someone is consuming your library. It's their job to correct the defect. You're absolutely correct: You can't recover from it. Make your caller do it. – Mike Hofer Jan 30 '12 at 15:38
  • How is the caller meant to recover? If a developer uses my library incorrectly, it is a coding error and it should be neither recovered from, nor present in production. – Maxpm Jan 30 '12 at 20:10
  • 3
    But that's the point. He recovers by fixing the defect before it ever reaches production. – Mike Hofer Jan 30 '12 at 22:52
  • But that's him manually rectifying his error, not the program working around it by design. Besides, isn't that exactly what assertions are for, anyway? Finding and fixing defects before they ever reach production? – Maxpm Jan 30 '12 at 23:40
  • 14
    The problem is that an assertion is removed from the release version of your compiled assembly. You can't use it if you're compiling a release build. You *must* throw. – Mike Hofer Jan 31 '12 at 15:04
  • "Exceptions are used for run-time error conditions... Assertions are used for coding errors..." Not entirely true. Exceptions can (and possibly should) be used for coding errors as well: cf. std::logic_error and its derived classes. – plexando Feb 17 '20 at 07:46
36

Assert the stuff that you know cannot happen (i.e. if it happens, it's your fault for being incompetent).

Raise exceptional situations which are not treated by the regular control flow of the program.

4

You use exceptions for exceptional situations. For example an out of memory situation or a network failure.

You use assert to ascertain that a cetain precondition is met. For example a pointer is not NULL or an integer is within a certain range.

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
  • 6
    The parallelism of "assert" and "ascertain" does not work. To "assert" is to declare positively, whereas "ascertain" is to learn. Thus, assert presupposes "true", whereas ascertain suggests no particular bias. It's not a terrible mnemonic, but the suggested etymology is flawed. – Argalatyr Jan 03 '09 at 21:21
  • Agree with Argalatyr. To assert is "to insist upon", "to declare boldly" or similar. To ascertain is "To discover with certainty, as through examination or experimentation", for which "discover" is a synonym. – Mike Hofer Jan 03 '09 at 22:10
  • 1
    Also, the "exceptions for exceptional situations" rule could use clarification. Why is a network failure exceptional but not a null pointer? – JW. Jan 03 '09 at 22:11
4

I use asserts for things that should never happen, yet do. The sort of thing that when it happens, the developer needs to revisit incorrect assumptions.

I use exceptions for everything else.

In reusable code, I prefer an exception because it gives the caller a choice of handling or not handling the problem. Just try catching and handling an assert!

Paul Beckingham
  • 14,495
  • 5
  • 33
  • 67
2

Assert is a means to verify that the program is in a possible state. If a function returns -1 when it should only return positive integers, and you have an assert that verifies that, your program should stop because it puts your program in a dangerous state.

Jason Evans
  • 28,906
  • 14
  • 90
  • 154
Loki
  • 29,950
  • 9
  • 48
  • 62
  • 3
    It's very odd that in a Q on exceptions vs. assertions, you never mentioned the former at all. But re what you said about assertions: What is a "possible state"? As assertions only run in debug mode, they should only be used in dev to catch bugs that should never have been written. Once a program is in the wild, it should be free of bugs (hopelessly utopian, I know, but humour me) and can be run in release mode, so assertions will not catch anything. But errors can result from users doing wacky things, including permutations of input we never thought "possible"... hence the need for exceptions – underscore_d Sep 15 '18 at 10:15
1

As a general rule, I throw exceptions from:

  1. public functions of a package to catch programming errors.
  2. internal functions to report system errors or pass-through sub-system errors.

where I use asserts only internally to catch implementation mistakes.

donpark
  • 141
  • 1
  • 5