Replace error code with exception (replace the error code with an exception)

Source: Internet
Author: User

Replace error code with exception (replacing the error code with exceptions) http://book.51cto.com 2010-02-03 bear festival translated by People's post and telecommunications press I want to comment (0)
  • Abstract: refactoring: improving the design of existing code clearly reveals the reconstruction process and explains the principles and best practices of refactoring, it also shows when and where to start mining code for improvement. Chapter 2 describes how to simplify function calls. This section describes replace error code with exception (replacing error codes with exceptions)
  • Label: refactoring code function refactoring: improving the design of existing code

 

10.14 replace error code with exception (replace the error code with an exception)

A function returns a specific code to indicate an error.

Switch exception.

 
 
  1. int withdraw(int amount) {  
  2.     if (amount > _balance)  
  3.         return -1;  
  4.     else {  
  5.         _balance -= amount;  
  6.         return 0;  
  7.     }  
  8. }  
  9.    
  10. void withdraw(int amount) throws BalanceException {  
  11.     if (amount > _balance) throw new BalanceException();  
  12.     _balance -= amount;  

Motivation

Like life, computers occasionally make mistakes. Once something goes wrong, you need some countermeasures. In the simplest case, you can stop the program and return an error code. This is like killing myself because I missed a plane (if I did that, even if I were a cat, my nine lives would be lost ). Although my smooth attempt brings a bit of humor, this "software suicide" option is indeed good. If the program crashes at a low cost and the user is tolerant enough, you can safely terminate the program. But if your program is important, you need to handle it in a more serious way.

The problem is: the errors found in the program do not necessarily know how to handle the errors. When a subroutine discovers an error, it needs to let its callers know the error, and the caller may also pass the error along the call chain. Many programs use special outputs to indicate errors. The traditional methods of UNIX and C-based systems are to return values to indicate successful or failed subprograms.

Java has a better way to handle errors: exceptions. This method is better because it clearly separates "Common Programs" from "error handling", which makes the program easier to understand-I hope you are now confident that: the comprehensibility of code should be our goal.

Practice

Decide whether to throw a controlled or unchecked exception.

If the caller has the responsibility to check the necessary status before calling, an uncontrolled exception is thrown.

To throw a controlled exception, you can create a new exception class or use an existing exception class.

Find all callers of the function and adjust them accordingly to make them use exceptions.

If a function throws an uncontrolled exception, adjust the caller so that the caller can perform a proper check before calling the function. Compile and test each modification.

If the function throws a controlled exception, adjust the caller so that the caller can call the function in the try section.

Modify the signature of the function to reflect the new usage.

If a function has many callers, the modification process may be too long. You can divide it into the following steps.

Decide whether to throw a controlled exception or an uncontrolled exception.

Create a new function and use an exception to indicate the error status. Copy the code of the old function to the new function and make appropriate adjustments.

Modify the function ontology of the old function to call the new function.

Compile and test.

Modify the callers of the old function one by one to call the new function. Compile and test each modification.

Remove the old function.

Example

In real life, you can overdraft your account balance, but it is not surprising that you cannot do this in computer textbooks? However, the following example assumes that you cannot do this:

 
 
  1. class Account...  
  2.   int withdraw(int amount) {  
  3.       if (amount > _balance)  
  4.           return -1;  
  5.       else {  
  6.           _balance -= amount;  
  7.           return 0;  
  8.       }  
  9.   }  
  10.  
  11.   private int _balance; 

To make this code run abnormally, I first need to decide whether to use a controlled exception or an uncontrolled exception. The key to decision-making is: whether the caller is responsible for checking the deposit balance before the withdrawal, or whether the withdraw () function should be responsible for checking. If "checking the balance" is the caller's responsibility, "the withdrawal amount is greater than the deposit balance" is a programming error. This is a programming error, so I should use uncontrolled exceptions. On the other hand, if "checking the balance" is the responsibility of the withdraw () function, I must declare in the function interface that it may throw this exception, so the caller is reminded to pay attention to this exception, and take appropriate measures.

Example: uncontrolled exceptions

Consider uncontrolled exceptions first. This indicates that the caller is responsible for the check. First, I need to check the calling code. It should not use the return value of the withdraw () function, because the return value is only used to indicate programmer errors. If I see the following code:

 
 
  1. If (account. Withdraw (amount) =-1)
  2. Handleoverdrawn ();
  3. Else dotheusualthing ();
  4. I should replace it with this Code:
  5. If (! Account. canwithdraw (amount ))
  6. Handleoverdrawn ();
  7. Else {
  8. Account. Withdraw (amount );
  9. Dotheusualthing ();
  10. }

Compile and test each modification.

Now, I need to remove the error code and throw an exception when a program error occurs. This behavior is abnormal and rare, so I should use a guard statement to check this situation:

 
 
  1. Void withdraw (INT amount ){
  2. If (amount> _ balance)
  3. Throw new illegalargumentexception ("amount too large ");
  4. _ Balance-= amount;
  5. }
  6. As this is a programmer's mistake, I should use assertions to point out this point more clearly:
  7. Class account...
  8. Void withdraw (INT amount ){
  9. Assert. istrue ("sufficient funds", amount <= _ balance );
  10. _ Balance-= amount;
  11. }
  12.  
  13. Class assert...
  14. Static void istrue (string comment, Boolean test ){
  15. If (! Test ){
  16. Throw new runtimeexception ("assertion failed:" + comment );
  17. }
  18. }
  19.  
  20. Example: Controlled exception
  21.  
  22. The handling methods of controlled exceptions are slightly different. First, I want to establish (or use) a suitable exception:
  23.  
  24. Class balanceexception extends exception {}
  25.  
  26. Then, adjust the caller as follows:
  27.  
  28. Try {
  29. Account. Withdraw (amount );
  30. Dotheusualthing ();
  31. } Catch (balanceexception e ){
  32. Handleoverdrawn ();
  33. }
  34. Next, I want to modify the withdraw () function to indicate the error status with an exception:
  35.  
  36. Void withdraw (INT amount) throws balanceexception {
  37. If (amount> _ balance) throw new balanceexception ();
  38. _ Balance-= amount;
  39. }

The trouble with this process is that I have to modify all callers and functions called by them at one time, or the compiler reports an error. If there are many callers, this step is too large, with no compilation and testing support.

In this case, I can use a temporary intermediate function. I am still starting from the previous situations:

 
 
  1. If (account. Withdraw (amount) =-1)
  2. Handleoverdrawn ();
  3. Else dotheusualthing ();
  4.  
  5. Class account...
  6. Int withdraw (INT amount ){
  7. If (amount> _ balance)
  8. Return-1;
  9. Else {
  10. _ Balance-= amount;
  11. Return 0;
  12. }
  13. }
  14. First, create a newwithdraw () function to throw an exception:
  15. Void newwithdraw (INT amount) throws balanceexception {
  16. If (amount> _ balance) throw new balanceexception ();
  17. _ Balance-= amount;
  18. }
  19. Then, adjust the existing withdraw () function to call newwithdraw ():
  20.  
  21. Int withdraw (INT amount ){
  22. Try {
  23. Newwithdraw (amount );
  24. Return 0;
  25. } Catch (balanceexception e ){
  26. Return-1;
  27. }
  28. }
  29. Compile and test. Now I can call the old function one by one to call the new function:
  30.  
  31. Try {
  32. Account. newwithdraw (amount );
  33. Dotheusualthing ();
  34. } Catch (balanceexception e ){
  35. Handleoverdrawn ();
  36. }

Because both new and old functions exist, I can compile and test each modification. After all callers are modified, the old function can be removed and rename method (273) is used to modify the new function name so that it is the same as the old function.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.