Consciously specify, and conscientiously apply, what so many projects
leave to adhoc (mis)judgment: Develop a practical, consistent, and
rational error handling policy early in design, and then stick to it.
Ensure that it includes:
Identification: What conditions are errors.
Severity: How important or urgent each error is.
Detection: Which code is responsible for detecting the error.
Propagation: What mechanisms are used to report and propagate
error notifications in each module.
Handling: What code is responsible for doing something about the
error.
Reporting: How the error will be logged or users notified
For different runtime errors, you can take different actions. And It’s depends
on you context of application.
error is just warning, log or show it to user, then continue;
error can be resolved inside a function, the whole appliation can
be continue after you reslove or retry, such as input error.
error is serious, application can’t continue, stop (call exit). please
debug me (call abort)
set global error code or return error code or throw exception. then
caller decide what to do (return a error code or use exception)
Pay attention, exception and return a error code has the same philosophy.
let caller decide what to do next.
Exception handling is highly dependent on your application context.
So it should be designed into a program rather than just added
on.
Confusing logical error with runtime error. For logical error, you need torewrite code to fix it. For runtime error, you need to throw it andcatch it to responds. logical error should use assert or unit tesst to find
the as early as possible. For example, in f(Foo* p), p is nullptr. There are
two possibilities:
they are passing nullptr because they got bad data from an
external user (for example, the user forgot to fill in a field and
database connection fail) you should throw an exception since it
is a runtime situation (i.e., something you can’t detect by acareful code-review; it is not a bug).
they just plain made a mistake in their own code. you should
definitely fix the bug in the caller’s code. but you must not merely
change the code within f(Foo* p); you must, must, MUST fix the
code in the caller(s) of f(Foo* p).
In previous example, You can use assert first, after youcode-review, found that It’s not bug, but cause by an exception,such as net disconnect. so you can change assert to throw. THATIS A GOOD STRATEGY!
Use all throw and catch to replace return-code. For a simple function, just
return one error code and user will not forget to test return code. this time,
return-code method maybe is better.
For object constructor, always use exception and try block.
When to use assert ?
your problem comes from your own bad code, it’s better to use
ASSERTs. Including you coding error or addition overflow.
bugs in your program are not something the user can handle, User
can do nothing when he face "age should be not negative" unless
age is inputted by himself(at this time, you should use return error
code)
you have to stop your application. If you write negative age back
to database, It may cause futuristic error for other user later, and
It’s very difficult to trace back.
When to throw a exception( or return error code)?
As a general rule of thumb, throw an exception when your program
can identify an external problem that prevents execution.
identify problems that program cannot handle and tell them about
the user, because user can handle them.
For example, no memory space, no file exit, no net connection ,
no object construct and get invalid data from sever etc.
When to use try... catch block?
Catch an exception where you can do something useful with
it.
You can actually handle the exception. your catch clause
deals with the error and continues execution without throwing
any additional exceptions. My caller never knows that the
exception occurred.
So I can have a catch clause that does blah blah blah, after
which I will rethrow the exception. In this case, consider
changing the try block into an object whose destructor does
blah blah blah. For instance, if you have a try block whose
catch clause closes a file then rethrows the exception, consider
replacing the whole thing with a File object whose destructor
closes the file. This is commonly called RAII
Show some message or log exception, or give user a list options
to select. then rethrow.
For an atomic operation, there is only one try block. That is to say,
inside one function, just include one try block
Exception in C++ is a tool; use it properly and it will help you; but don’t
blame the tool if you use it improperly. "Wrong exception-handling
mindsets" in c++ FAQ website section 17 is good topic. You need to read it
again if you have time.