Table of contents:
1 Protect the program from corruption of illegally entered data
2 Assertion
3 Error handling techniques
4 Abnormal
5 Isolate the program to contain the damage caused by the error
6 Code to assist debugging
7 Determine how much defensive code to keep in the product code
8 Take a Defensive Stance on Defensive Programming

content:

Defensive programming is a useful adjunct to software quality techniques. The main idea of defensive programming is that subroutines should not be corrupted by incoming bad data, even those generated by other subroutines. More generally, the core idea is to admit that programs are buggy and need to be fixed, and that smart programmers should program accordingly.

1 Protect the program from corruption of illegally entered data

  • Garbage in, garbage out. This sentence refers to the principle of "no return or exchange" in the field of software development, allowing users to worry about their own affairs.
  • By today's standards, "garbage in, garbage out" has become the hallmark of poor programs that lack security.
  • "Garbage in, garbage out" is not enough for software that is already a product.
  • Good programs don't generate garbage no matter what comes in.
  • It's "garbage in, nothing out"
  • Or "Incoming garbage, going out is an error message"
  • Even "don't allow garbage to come in"
  • Three situations for dealing with garbage:

    • Check the value of all externally sourced data
    • Check the values of all input parameters of the subroutine
    • To decide how to handle erroneous input data, refer to Section 3: Error Handling Techniques

2 Assertion

  • Assertion refers to code used during development to allow a program to perform self-checking at runtime.
  • When the assertion is true, it means that the program is running normally.
  • An assertion that is false means that it has found an unexpected bug in the code.
  • Assertions are especially useful for large, complex programs or programs with extremely high reliability requirements.
  • By using assertions, programmers can more quickly troubleshoot mismatched interface assumptions and errors that have been introduced into the program by code changes or other reasons.
  • An assertion usually takes two parameters: a boolean expression describing what happens when the hypothesis is true, and a message to display when the assertion is false.
  • Assertions are mainly used in the development and maintenance phases.
  • Often, assertions are compiled into object code only during development, but not when production code is generated.
  • During the development phase, assertions can help identify conflicting assumptions, unexpected situations, and erroneous data passed to subroutines.
  • When generating production code, the assertion may not be compiled into the target code, so as not to reduce the performance of the system.
  • Use error-handling code to handle error conditions that are expected to occur, and assertions to handle conditions that should never happen.
  • Avoid putting code that needs to be executed in assertions.
  • Annotate and validate preconditions and postconditions with assertions
  • Preconditions and postconditions are part of a programming and development methodology called "design by contract".
  • A precondition is a property that the calling code of the subroutine or class is guaranteed to be true before calling the subroutine or instantiating the object. Preconditions are obligations that caller code owes to the code it calls.
  • Postconditions are properties of a subroutine or class that are guaranteed to be true after execution ends. A postcondition is the responsibility of a subroutine or class to the caller's code.
  • Assertions are useful tools for specifying preconditions and postconditions. Annotations can also be used to specify preconditions and postconditions, but assertions dynamically determine whether preconditions and postconditions are true.
  • For highly robust code, assertions should be used before error handling.

3 Error handling techniques

Available error handling techniques include:

  • return neutral
  • switch to the next correct data
  • returns the same data as before
  • Replace with the closest legal value
  • log warning messages to log file
  • return an error code
  • call an error-handling subroutine or object
  • Display an error message when an error occurs
  • Handle errors locally in the most appropriate way
  • turn off an app

Correctness and robustness:

  • Correctness means never returning inaccurate results, even if not returning results is better than returning inaccurate results.
  • Robustness means constantly trying to take certain measures to ensure that the software can continue to operate, even if it sometimes produces some inaccurate results.
  • Software where human safety is at stake tends to favor correctness over robustness.
  • Consumer applications tend to focus more on robustness than correctness.

4 Abnormal

  • Notify other parts of the program with an exception that a non-ignorable error occurred.
  • Exceptions are thrown only in the case of true exceptions.
  • Exceptions cannot be used to shirk responsibility.
  • Avoid throwing exceptions in constructors and destructors unless you catch them in the same place.
  • Throw exceptions at the appropriate level of abstraction.
  • Include in the exception message all the information that caused the exception to occur.
  • Avoid empty catch statements.
  • Learn about exceptions that may be thrown by the library you are using.
  • Consider creating a centralized exception reporting mechanism.
  • Standardize the use of exceptions in your project.
  • Consider unusual alternatives.

5 Isolate the program to contain the damage caused by the error

  • The use of a spacer provides a clear distinction between assertions and error handling.
  • Programs outside the fence should use error handling techniques, where any assumptions made about the data are unsafe.
  • The assertion technique should be used in the program inside the fence, because the incoming data should have been cleaned up when passing through the fence.

6 Code to assist debugging

  • The sooner code that aids debugging is introduced, the more helpful it can be.
  • Exceptions should be handled in such a way that it manifests itself during development, and it recovers itself when production code runs. This approach is called "offensive programming". The method of offensive programming is as follows:
  • Make sure the assert statement causes the program to terminate. Don't make programmers into the bad habit of hitting enter to skip a known problem as soon as it hits it. Let the problem cause as much trouble as possible so it can be fixed.
  • Completely fills all allocated memory, which allows you to detect memory allocation errors.
  • Completely populates any files or streams that have been assigned to, allowing you to troubleshoot file format errors.
  • Make sure that the default or else branch of each case statement can generate serious errors (such as causing the program to terminate), or at least that these errors will not go unnoticed.
  • Fill an object with garbage data before deleting it.
  • Have the program email you its error log file so you can see what other errors have occurred in the released software—if that applies to the software you're developing.
  • It is planned to remove the debug-aided code, the available methods are as follows:
  • Extend the use of version control tools and make tools like ant and make
  • Use the built-in preprocessor
  • Write your own preprocessor
  • Use debug stubs

7 Determine how much defensive code to keep in the product code

  • Keep code that checks for important errors
  • Get rid of code that checks for subtle errors
  • Remove the code that can cause the program to hard crash
  • Keep code that can crash your program gracefully
  • Log error messages for your technical support staff
  • Confirm that the error messages left in the code are friendly

8 Take a Defensive Stance on Defensive Programming

  • Excessive defensive programming can also cause problems.
  • If you check data passed in from parameters in every conceivable way and in every conceivable way, your program will become bloated and slow.
  • To make matters worse, the extra code introduced by defensive programming increases the complexity of the software.
  • The code introduced by defensive programming is not without its flaws, and like any other code, you can easily find bugs in the code added by defensive programming—especially if you write it casually.
  • So, think about where you need to defend, and then adjust your priorities for defensive programming accordingly.

王顶
1.2k 声望107 粉丝

学无止境


引用和评论

0 条评论