Categories
Uncategorized

Errors, anomalies and custom exception

Programmer for an exception (Exception) word should not unfamiliar, especially now Exception basically standard OOP programming language. To me, the word is both familiar and unfamiliar, familiar because heard many times, it seems there are a lot of use; strange because few really thought about in the end what is abnormal, and how to use exceptions. This article documents some of my views on how to use exceptions, custom exception, not necessarily correct, also requested the exhibitions.
    This article addresses: https: //www.cnblogs.com/xybaby/p/11645885.html

What is unusual

An exception is a means of error handling:

exception handling is an error-handling mechanism

In the above definition is generalized error error, unexpected behavior of any code logic, operating system, computer hardware is error. Java is not the language of confrontation with Exception Error (Java in, Error and Exception there is a difference, in short, Error handling in theory, should not be captured, see Differences between Exception and Error), nor with panic golang error opposites.

In programming languages, for the classification error can be roughly divided into Syntax errors, Semantic errors, Logical errors, if the timing error was discovered from the point of view, can be divided into Compile time errors, Runtime errors.

Actual programming language, and the description on the wiki:

Exception handling is the process of responding to the occurrence, during computation, of exceptions – anomalous or exceptional conditions requiring special processing – often disrupting the normal flow of program execution.

As can be seen, in general, Exception corresponds Runtime error, such as the following code

FileReader f = new FileReader("exception.txt"); //Runtime Error

If the file does not exist, it will throw an exception, but only when the program runs to this line of code when it is to know whether the file exists.

It should be noted, is not the only means an exception error handling, another widely used approach is error code, error code is a more ancient error handling means, the next chapter will be on the error code and exception the pros and cons of introduction.

When using exceptions

The following two examples to illustrate exception when used.

Preliminary abnormal

The first example comes from StackExchange When and how should I use exceptions?.
    Main problems need some pages crawled, as judged http://www.abevigoda.com/ Abe Vigoda (Godfather actor) is still alive. code show as below:

def get_abe_status(url):
    # download the page
    page = download_page(url)

    # get all mentions of Abe Vigoda
    hits = page.find_all_mentions("Abe Vigoda")

    # parse the first hit for his status
    status = parse_abe_status(hits[0])

    # he's either alive or dead
    return status == "alive"

def parse_abe_status(s):
    '''Param s: a string of the form "Abe Vigoda is something" and returns the "something" part'''
    return s[13:]
    

In short, it is to download web content, extract all sentences contain “Abe Vigoda”, the first sentence parsing to determine “Abe Vigoda” if still alive.

The code above may occur several problems:

    download_page failed due to various reasons, the default throws IOError

    Since the url error, or web content modification, hits may be empty

    If hits [0] is no longer “Abe Vigoda is something” format, then the return is neither parse_abe_status Alive, Dead nor, as expected not (code comments)

First, for the first question, download_page may throw IOError, according to the function signature, the caller can be expected to function is the function needs to read the page, then throw IOError is acceptable.

As for the second question – hits may be empty, the title there are two main solutions.

Use error code

Here is the return None

def get_abe_status(url):
    # download the page
    page = download_page(url)

    # get all mentions of Abe Vigoda
    hits = page.find_all_mentions("Abe Vigoda")

    if not hits:
        return None

    # parse the first hit for his status
    status = parse_abe_status(hits[0])

    # he's either alive or dead
    return status == "alive"

Obviously, this is to tell by error code (None) caller error occurred, also mentioned in the previous section are in addition to the error code Exception handling error handling means another widely used.

So what are the advantages and disadvantages does Exception error code comparison?
    First, the advantages:

    Not introduce a new concept, just a normal function call

    Easy to understand, it will not disrupt the current flow of execution

Compared Exception, its drawbacks include:

    The code all the time you need to check the return value, while the caller is easy to miss some of the checks, which may be hidden, delayed more serious problems exposed


    Lack of contextual information error

    Sometimes simply a function does not return a value (such as constructor), this time you have to rely on global error flag (errno)

For example, the Linux environment, linux open returns -1 to indicate an error, but what is the specific reason, you have to go see additional errno

Back to the code above, from the performance function to achieve it, check_abe_is_alive should be more appropriate than get_abe_status, the name is more expressive. For this function the caller, the expected return value should be a bool value, it is difficult to understand why a return None. As a dynamically typed language Python and magnified the problem, the call is likely to return value conditional execution, such as if check_abe_is_alive (url) :, where None has also been used as a False serious logic error.

None returned error code also reflects the shortcomings of: exposure delays, and lost the context of the error occurred. For example, a function should return an Object, returned a result None, then use the return value of a property when only a trace, but use the return value of the place may be related to the return value of the place has been created across ten eighteen thousand years. Did not let the real, original error immediately exposed to when it happened, bug check up is not easy.

Throw an exception

class NotFoundError(Exception):
    """Throw this when something can't be found on a page."""

def get_abe_status(url):
    # download the page
    page = download_page(url)

    # get all mentions of Abe Vigoda
    hits = page.find_all_mentions("Abe Vigoda")

    try:
        hits[0]
    except IndexError:
        raise NotFoundError("No mentions found.")

    # parse the first hit for his status
    status = parse_abe_status(hits[0])

    if status not in ['alive', 'dead']:
        raise SomeTypeOfError("Status is an unexpected value.")

    # he's either alive or dead
    return status == "alive"

Note that the above code also contains a solution to the third problem, namely to ensure that status is either alive or dead. But we focus on the handling of hits empty. There are two points worth noting:

    Throw a custom exception NotFoundError, rather than IndexError. This is a wise choice, because the hits is empty is an implementation detail, the caller’s hard to imagine why you want to throw IndexError. About custom exception, there is a special section will be discussed later.

    To determine hits is empty, this is not recommended practice by attempting to capture IndexError, because there obviously can be determined by if not hits hits is empty

About determination (IF) or a try-catch conditions used in Best practices for exceptions is described in

Use exception handling if the event doesn’t occur very often, that is, if the event is truly exceptional and indicates an error (such as an unexpected end-of-file). When you use exception handling, less code is executed in normal conditions.

Check for error conditions in code if the event happens routinely and could be considered part of normal execution. When you check for common error conditions, less code is executed because you avoid exceptions.

Or if a try-catch, in fact, suggests that about the exception itself a controversial point: that is, whether the exception should serve as a means of process control, summed up the wiki speak different languages ​​have different preferences. However, personally I think that if they can use if, do not use try-catch, exception only for use in the real anomalies.

Abnormal Revisited

The second example comes from stackoverflow When to throw an exception, the main problems are the habit is defined for any unexpected circumstances, an exception is thrown, as UserNameNotValidException, PasswordNotCorrectException, but the team is not recommended, and therefore the question about the main post to seek an exception recommended.

I think this is a problem we may encounter, capture and handle exceptions relatively simple, but when we do should throw an exception, the standard exception was thrown custom exception it? Let’s take a look at the answer on StackOverflow

Overwhelmingly answer:

My personal guideline is: an exception is thrown when a fundamental assumption of the current code block is found to be false.
    A master gave the example of a Java code: a judge is not a class List <> subclass, then theoretically should not throw an exception, but returns Bool value. But this function is assumed that the input should be a class, if the input is null, then it is contrary to the hypothesis, we should throw an exception.

Overwhelmingly Answer 2:

Because they’re things that will happen normally. Exceptions are not control flow mechanisms. Users often get passwords wrong, it’s not an exceptional case. Exceptions should be a truly rare thing, UserHasDiedAtKeyboard type situations.
    A direct answer to the main question of the main questions, it should be emphasized that an exception error occurred in rare cases (other than expected) should be used only exception should not be a means of process control

Overwhelmingly Answer 3:

My little guidelines are heavily influenced by the great book “Code complete”:

  • Use exceptions to notify about things that should not be ignored.
  • Don’t use exceptions if the error can be handled locally
  • Make sure the exceptions are at the same level of abstraction as the rest of your routine.
  • Exceptions should be reserved for what’s truly exceptional.
            When A primary reference “Code Complete” that appeared only in the current level of the code can not handle, you can not ignore the error, it should throw an exception. And extremely should be used only true exceptions.

Overwhelmingly Answer 4:

One rule of thumb is to use exceptions in the case of something you could not normally predict. Examples are database connectivity, missing file on disk, etc.
    Exceptions should only due to the unexpected, uncontrollable circumstances, such as data connections, disk file read failed cases

Overwhelmingly answer 5:

Herb Sutter in his book with Andrei Alexandrescu, C++ Coding Standards: throw an exception if, and only if

  • a precondition is not met (which typically makes one of the following impossible) or
  • the alternative would fail to meet a post-condition or
  • the alternative would fail to maintain an invariant.

As can be seen from the above answer, if violated program (routine) of the basic assumptions (assumption, prediction, setup, pre-condition) h or inhibit (post-condition, invariant), and the current level code when he can not properly handle You should throw an exception.

Modern software development models, such as hierarchical, module, component, third party library makes it more places need to use exception, because the caller does not have enough information to determine how to handle exceptions. For example, a network link library, if the destination address is not connected, their coping strategies depending on the user library is retried or change a url. For library functions, an exception is thrown is the best choice.

Custom exception

In the previous section we have seen examples of custom exception (NotFoundError) of.

Programmers should be familiar with standard programming language provides an exception class, when necessary try to choose the most appropriate standard exception classes. If the standard exception class can not express just the right cause of the exception, you should consider custom exception class, especially for the development of an independent, third-party libraries.

Custom exception has the following advantages:

    Class name implies error, readable, which is the standard libraries, third party libraries, there are many reasons for the exception class

    Facilitate business logic to handle certain exceptions capture

  • Easy to add additional information

    For example, the FileNotFoundException provides the FileName property.

defined exception classes in Why user are preferred / important in java? also has a similar description

To add more specific Exception types so you don’t need to rely on parsing the exception message which could change over time.
You can handle different Exceptions differently with different catch blocks.

In general, you should create specific exception classes corresponding frame, inside the framework of all the exception classes should inherit from this class, such as pymongo

class PyMongoError(Exception):
    """Base class for all PyMongo exceptions."""


class ProtocolError(PyMongoError):
    """Raised for failures related to the wire protocol."""


class ConnectionFailure(PyMongoError):
    """Raised when a connection to the database cannot be made or is lost."""

Abnormal recommendations

After know when to use exceptions, then discusses how to use good exception.

Practice recommendations mentioned below, seeks nothing to do with language, content reference 9 Best Practices to Handle Exceptions in Java, Best practices for exceptions

Exception should include two stages, both stages are worthy of our attention:

    Exception initialization: throw an exception object by raise (throw), the object contains the error occurred context

    Exception handling, through a try – catch (expect) to handle the exception, it will usually be handled logic regardless of whether an exception occurred will be executed by finally (ensure), in order to achieve security anomalies, such as the release of resources.

try-catch-finally
    try-catch-finally block is like a transaction, regardless of whether there is an exception occurs, finally statements in the program to maintain a sustainable, predictable state resources such as the above-mentioned release. However, in order to prevent the call finally forget, in general programming language will provide a more friendly mechanism to achieve this objective. For example, in C ++ RAII, python’s with statement, Java’s try-with-resource

If you can, try to avoid using exceptions
    I mentioned earlier, exception should be used in a real exceptions, and exception processes will also have to jump. So, if you can, you should try to avoid using exceptions. “ Specail case Pattern“` is such a design pattern, that is configured to create a class or an object, used to handle special cases, avoids exception or check the return value, particularly suitable to avoid return null.

Custom exception, should have a concise document
    As alluded to above, for third-party libraries, it is best to have a base class for exceptions in the library that matches the intent, then write the document.

exception raise
    For throws an exception, you need to write documents, make it clear in what circumstances what kind of exception will be thrown; but also to choose just the right kind of abnormality in the exception class system, Prefer Specific Exceptions.

clean code vs exception
    User “clean code” recommended third-party libraries for third-party libraries that may be thrown encapsulation: first, because of these abnormal processing means generally the same; the second is to allow business logic to decouple third-party libraries.

In fact, wrapping third-party APIs is a best practice. When you wrap a third-party API, you minimize your dependencies upon it

exception handling
    When catching exceptions, from the most specific exception class to start capturing, and finally the broadest exception classes, such as the python Exception.

In catch blocks, always order exceptions from the most derived to the least derived

Programmers should be taken seriously abnormal, seen many such python code in the project:

try:
    # sth 
except Exception:
    pass

The first problem is the direct capture the broadest class Exception; secondly did not do anything abnormal, deceiving, of course, in practice it may be a print who do not care about the log.

If we call an interface, this interface might throw an exception, you should go to try to deal with the current exception of existing knowledge, if it can not handle the current level, then there should also be some kind of mechanism to inform on one call By. checked exception is certainly safer than function documentation, appropriate method, but many programming languages ​​are not checked exception mechanism, but also “clean code” is not recommended to use checked exception, because it violates the open close principle, but did not offer better approach.

Wrap the Exception Without Consuming It
    Sometimes throws an exception might be more expressive than the standard self-defined exceptions, such as reading the configuration file when ConfigError (can not find config file) is more appropriate than IoError, another example in the previous example NotFoundError

However, it is important to retain the original trace stack, rather than a stack re-raise. For example, the following Java code:

public void wrapException(String input) throws MyBusinessException {
    try {
        // do something may raise NumberFormatException
    } catch (NumberFormatException e) {
        throw new MyBusinessException("A message that describes the error.", e);
    }
}

It is written below python2

def bar():
    try:
        foo()
    except ZeroDivisionError as e:
        # we wrap it to our self-defined exception
        import sys
        raise MyCustomException, MyCustomException(e), sys.exc_info()[2]

references

  • clean code
  • Differences between Exception and Error
  • Programming Error and exception handling
  • 9 Best Practices to Handle Exceptions in Java
  • Best practices for exceptions
  • When to throw an exception?
  • linux open
  • When and how should I use exceptions?
  • Why user defined exception classes are preferred/important in java?
  • Properly reraise exception in Python (2 and 3)

Leave a Reply