For example, if the add method of a UserClass is successful, the user object instance is returned. If the instance fails, False is returned. You can use the getError method to obtain the string of the cause of failure ........ speaking of this, I seem to understand that the add method should always return user objects; otherwise, an exception is thrown? But in this case, there is no difference in their code volume. The problem is that even if no exception is caught at the call of the add method, the exception can be further thrown up until it is processed or the process crashes? But in the end, this and the program, such as the add method of a User Class, return the User object instance in case of success, if a failure occurs, False is returned. You can use the getError method to obtain the cause of failure string ........
Speaking of this, I seem to understand that the add method should always return user objects; otherwise, an exception is thrown?
But in this case, there is no difference in their code volume. The problem is that even if no exception is caught at the call of the add method, the exception can be further thrown up until it is processed or the process crashes? But in the end, what is the difference between this and the natural collapse of the program?
---- The above is self-speaking. The following is a problem ----
What is the difference between throwing an exception and returning false? Reply content: first, this is a good question. A deep understanding of the differences between the two is one of the signs of breaking through a moderate programmer.
Clarify the misunderstanding first, that is, the exception is very slow. Exception implementation requires saving the necessary information about the exception throws to the exception capture points, which is the main basis for people to criticize the exception performance. But this is wrong. First, manual acquisition based on the returned error style is equivalent to the exception implementation performance. In most cases, it is inferior to the built-in language exception performance. This gap is particularly evident for operating systems that support native exceptions, such as Windows. Second, for non-stack-based calling implementation, the performance of exceptions and returned errors is slightly different, but the style is different.
Back to the problem, what is the essential difference between exceptions and returned errors? A: exceptions are strongly typed and the type-SAFE branch processing technology, while errors returned are weakened and insecure versions.
First, let's look at the features that returned the error. In general, special return values are required to identify errors, meaning that specific meanings must be reloaded. Assume that an operation returns an int value because it cannot return a negative number (for example, an absolute value). We can use-1 as an operation failure (for example, a function library call loading error). -1 does not have a special meaning in the int type. However, semantics is enforced here, which is weak. There is no way to ensure correctness through the type system check.
One enhancement method is to return two values at the same time. Some languages have built-in support. If there is no built-in support, you can simulate it by defining a structure containing the correct return type and Error Type, respectively. The advantage is that the channel for transmitting information is separated.
Whether an error is returned, the caller must explicitly check the error value. When an error occurs, the current operation must be terminated. When an error is returned, a new error type must be defined. This results in an operation that cannot be simply combined. For example, when Module B calls module A, an error defined by Module B is returned. When Module C calls module A, an error defined by C is returned, these two types of errors are often incompatible. A large amount of code must be added to the Code combination, which leads to code expansion and is very error-prone. For systems with clear interface definitions, a set of common error codes are generally defined to simplify their complexity. The OS kernel is an example. It provides an error code table that adapts to all OS calls. However, many internal error codes are used, and internal error codes are often mapped to external error codes in interfaces.
Exception is a secure branch processing technology. Because it is closely related to error handling, it is easy to regard exceptions as error handling, and even the name "exception" carries a thick meaning of errors. However, this is a misunderstanding. The theoretical basis of exceptions is that in some branch processing, a branch is not frequently compared with other branches. It is equivalent to handling common and extremely rare cases (think about it, there are often the same number of normal and error handling codes, but in most cases there are actually more of the latter ), it is better to simply handle normal situations and classify uncommon situations into one unified process. In this way, we can only focus on the normal situation when writing code. When an error occurs, a special process will help the programmer directly return to the location where the error handling is defined.
This is a little too simplified. Generally, you cannot jump back directly. Because there may be inconsistent values between the exception throw point and the exception handling point, waiting for resources to be released. Therefore, in general, special procedures need to trace the call stack to ensure that the execution is transactional. However, this special process is not enough. You must have the appropriate supporting code. This leads to additional complexity. The RAII concept introduced by C ++ is a pioneering concept, but it still fails to completely eliminate the work of programmers.
Because an exception is a specific type, the signature of a function is not only a list of input parameters, but also a list of output parameters that may throw an exception. The exception hierarchies defined by each module are different, which makes it difficult to combine them. However, it is different from the combination of returned error values. The former causes a compilation type error, while the latter causes a runtime error. Generally, the earlier the error is exposed, the better. We prefer the former.
Ideally, a system with a complete exception structure won't have any running errors (probably so, not expanded ). However, due to the above-mentioned reasons, the Code is also complex and redundant and difficult to maintain in the case of existing exception support.
The above are the basic differences between exceptions and errors.
Part 2 Notice: Is there an elegant solution to the above problem?
My point is: yes. However, because the existing capabilities do not need to be clarified directly without any reference, I will leave it for careful consideration and give it in the case of changing to non-mobile phone input. Please look forward to it. These are error handling policies. The OO language tends to be abnormal. Compared with determining the possible error status of a function, the complete exception object in the "throw" State is considered a better encapsulation; in your case, false is the simplest case. In this case, exceptions may not be advantageous. It is generally considered that using exceptions can simplify complicated error handling code, as long as the program does not need to terminate the execution, try catch is more readable than if else Code (the error handling policy is obvious and the status can be richer, although this is not absolute ).
result = func();if (result === ERR_NO_1) { ... } else if (result === ERR_NO_2) { } else { ...}
In a simple example, if you want to parse the json request response package, only the code that returns false may be
if(jsonObj.has("xxx")){ if(jsonObj.has("xxxxx")) { //......... return true; }}return false;
I wrote some, but I think there is nothing to say. A lot of questions can be found. In many cases, there is no superior or inferior, but only a unified style. For example, C ++ and other languages that support exception are completely exception free in many code libraries, and exception handling is implemented in the form of class C.
There are two types of exceptions. One is "I know that errors may occur in this place, the caller must be aware of the risks of errors", and the other is "this is an error, there is no room to save the crash 』. In Java, these two types of exceptions are the differences between checked exception and unchecked exception.
Exceptions are not limited to error handling. They are often used to process normal scenario and edge case separately. For example, read a file and count the number of times each word appears in the file. The Python syntax is used here:
word_count = dict()for word in words: try: word_count[word] += 1 except KeyError: word_count[word] = 1
If an exception is thrown, no bool is returned.
If it is designed to return a bool or pointer function, no exception is required.
That is to say, exceptions and returned values will never exist at the same time (of course, this is my personal understanding ).
(In my opinion, if the add function in your question may fail, do not throw an exception. If it should not fail under normal circumstances, you can throw an exception. However, you do not need to add try in every place of the add function. Whether your program logic can be restored or not .. (you can also write an auxiliary function to call try add internally .. use this helper function elsewhere :) to continue running. Otherwise, add a try at the program entry and exit)
It seems that you have not answered all of your questions. I will discuss them on the computer tomorrow. It is convenient to return Either or Maybe. If the number of error messages such as Either is rich enough, there is no need to handle exceptions. For WINDOWS implementation, there is a branch statement, one is SEH or global callback, the latter can prevent unexpected program crashes! First, exceptions are foreseeable, so they are predictable. Second, exceptions do not care about the conditions that occur, but how they are handled. Third, exceptions are defined errors, which are easier to locate. Fourth, exceptions can be passed.
The result of execution failure is to exit directly .... Assume that you need to handle an exception (or execution error) as follows:
-- An error message is displayed on the user interface.
However, this exception is thrown by underlying APIs, such as database calls, and the client does not have the permission to directly call this API.
At this time, you can choose:
- Throw an exception.
- Define the error code and return the code layer by layer.
You choose 2,
- It is found that an input parameter called err is added to each function. This parameter is useless because it will be returned to the previous layer without processing and goes directly to the UI.
- There is no problem with this, but one day you are told that a certain underlying change causes this API to throw a new error, the boss asks you to deal with such errors at a layer in the call stack. Therefore, you have added a judgment on the exception type.
- Later, another new module needs to reuse the exception information you wrote in the module you last processed. In order not to use the c & p code, You encapsulate the exception information into an Error class, each subclass inherited from Error stores its own exception information.
- You are satisfied with your own wheel and use it in the module currently maintained-your code looks like this:
def f(err, **kwargs): result = None if(err.code == 1): handle_this_err(err) elif(err.code == 2): return (err, result) else: result = handle_data(**kwargs) return (None, result)
Cross-function error code. Force error check. The happen path is simplified. Finally, you have to write exceptional security code.