软件构造随笔7

复习中

1、this和super一样,都是对象内部的引用变量,只能出现在对象内部;

2、this指向当前对象自己,super指向当前对象的父类型特征,故this的东西比super多,也就是super是this的一部分;

3、this()和super()都只能出现在构造方法的第一行,故this()和super()方法不能共存,当一个类的构造方法第一行中没有this(),也没有super(),系统默认有super()方法;

4、this()是构造方法中调用本类其他的构造方法,super()是当前对象构造方法中去调用自己父类的构造方法。

(10) Analyzing Stack Trace Elements
12 Construction for Robustness and Correctness
Stack trace (or call stack trace)
12 Construction for Robustness and Correctness
Method Call Stack
§ A typical application involves
many levels of method calls,
which is managed by a socalled method call stack.
§ A stack is a last-in-first-out
queue.
§ What’s the result?
– Enter main()
– Enter methodA()
– Enter methodB()
– Enter methodC()
– Exit methodC()
– Exit methodB()
– Exit methodA()
– Exit main()
public class MethodCallStackDemo {
public static void main(String[] args) {
System.out.println(“Enter main()”);
methodA();
System.out.println(“Exit main()”);
}
public static void methodA() {
System.out.println(“Enter methodA()”);
methodB();
System.out.println(“Exit methodA()”);
}
public static void methodB() {
System.out.println(“Enter methodB()”);
methodC();
System.out.println(“Exit methodB()”);
}
public static void methodC() {
System.out.println(“Enter methodC()”);
System.out.println(“Exit methodC()”);
} }
12 Construction for Robustness and Correctness
Call Stack Trace
§ Suppose methodC() carries out a “divide-by-0” operation, which
triggers an ArithmeticException. § The exception message clearly shows the method call stack
trace with the relevant statement line numbers:
Enter main()
Enter methodA()
Enter methodB()
Enter methodC()
Exception in thread “main” java.lang.ArithmeticException: / by zero
at MethodCallStackDemo.methodC(MethodCallStackDemo.java:22)
at MethodCallStackDemo.methodB(MethodCallStackDemo.java:16)
at MethodCallStackDemo.methodA(MethodCallStackDemo.java:10)
at MethodCallStackDemo.main(MethodCallStackDemo.java:4)
12 Construction for Robustness and Correctness
Exception & Call Stack
§ Suppose that methodD() encounters an abnormal condition and
throws a XxxException to the JVM.
§ The JVM searches backward through the call stack for a matching
exception handler.
§ It finds methodA() having
a XxxException handler
and passes the exception
object to the handler.
– Notice that methodC() and
methodB() are required to
declare “throws
XxxException” in their
method signatures in order
to compile the program.
12 Construction for Robustness and Correctness
Analyzing Stack Trace Elements
§ A stack trace is a listing of all pending method calls at a particular
point in the execution of a program.
§ You have almost certainly seen stack trace listings—they are
displayed whenever a Java program terminates with an uncaught
exception.
§ You can access the text description of a stack trace by calling the
printStackTrace method of the Throwable class.
Throwable t = new Throwable();
StringWriter out = new StringWriter();
t.printStackTrace(new PrintWriter(out));
String description = out.toString();
12 Construction for Robustness and Correctness
Analyzing Stack Trace Elements
§ A more flexible approach is the getStackTrace method that yields
an array of StackTraceElement objects, which you can analyze in
your program.
Throwable t = new Throwable();
StackTraceElement[] frames = t.getStackTrace();
for (StackTraceElement frame : frames)
analyze frame
§ The StackTraceElement class has methods to obtain the file name
and line number, as well as the class and method name, of the
executing line of code.
§ The toString method yields a formatted string containing all of
this information.
Software Construction
5 Assertions
12 Construction for Robustness and Correctness
First Defense: Make Bugs Impossible
§ The best defense against bugs is to make them impossible by
design. 最好的防御就是不要引入bug J – Static checking: eliminates many bugs by catching them at compile time.
– Dynamic checking: Java makes array overflow bugs impossible by
catching them dynamically. If you try to use an index outside the bounds
of an array or a List, then Java automatically produces an error. —
unchecked exception / runtime error
– Immutability: An immutable type is a type whose values can never
change once they have been created.
– Immutable values: by final, which can be assigned once but never
reassigned.
– Immutable references: by final, which makes the reference
unreassignable, but the object that the reference points to may be mutable
or immutable.
12 Construction for Robustness and Correctness
Second Defense: Localize Bugs
§ If we can’t prevent bugs, we can try to localize them to a small part
of the program, so that we don’t have to look too hard to find the
cause of a bug. 如果无法避免,尝试着将bug限制在最小的范围内 – When localized to a single method or small module, bugs may be found
simply by studying the program text. 限定在一个方法内部,不扩散
– Fail fast: the earlier a problem is observed (the closer to its cause), the
easier it is to fix. 尽快失败,就容易发现、越早修复 Pre-condition
如果违反,该方法
可以做任何事
Since the bad call indicates a bug in the caller,
however, the most useful behavior would
point out the bug as early as possible. 应该尽
可能早的指出client的bug
12 Construction for Robustness and Correctness
Second Defense: Localize Bugs
§ Assertions 断言: When the precondition is not satisfied, this code
terminates the program by throwing an AssertionError exception.
The effects of the caller’s bug are prevented from propagating. Fail
fast,避免扩散
§ Checking preconditions is an example of defensive programming
检查前置条件是防御式编程的一种典型形式 – Real programs are rarely bug-free.
– Defensive programming offers a way to mitigate the effects of bugs even if
you don’t know where they are.
Software Construction
(1) What and Why Assertions?
12 Construction for Robustness and Correctness
What is assertion?
§ An assertion is code that’s used during development that allows a
program to check itself as it runs, i.e., to test your assumptions about
your program logic (such as pre-conditions, post-conditions, and
invariants). 断言:在开发阶段的代码中嵌入,检验某些“假设”是否
成立。若成立,表明程序运行正常,否则表明存在错误。
– When an assertion is true, that means everything is operating as expected.
– When it’s false, that means it has detected an unexpected error in the code.
§ An example
public class AssertionTest {
public static void main(String[] args) {
int number = -5; // assumed number is not negative
// This assert also serve as documentation
assert (number >= 0) : "number is negative: " + number;
// do something
System.out.println("The number is " + number);
} }
12 Construction for Robustness and Correctness
What is assertion?
§ Each assertion contains a boolean expression that you believe will
be true when the program executes.
– If it is not true, the JVM will throw an AssertionError.
– This error signals you that you have an invalid assumption that needs to
be fixed. 出现AssertionError,意味着内部某些假设被违反了 – The assertion confirms your assumptions about the behavior of your
program, increasing your confidence that the program is free of errors. 增 强程序员对代码质量的信心:对代码所做的假设都保持正确
§ Assertion is much better than using if-else statements, as it
serves as proper documentation on your assumptions, and it does
not carry performance liability in the production environment.
断言即是对代码中程序员所做假设的文档化,也不会影响运行时性能
(在实际使用时,assertion都会被disabled)
12 Construction for Robustness and Correctness
What is assertion?
§ An assertion usually takes two arguments
– A boolean expression that describes the assumption supposed to be true
– A message to display if it isn’t.
§ The Java language has a keyword assert with two forms:
– assert condition;
– assert condition : message;
– Both statements evaluate the condition and throw an AssertionError if
the boolean expression evaluates to false.
– In the second statement, the expression is passed to the constructor of the
AssertionError object and turned into a message string. The description
is printed in an error message when the assertion fails, so it can be used to
provide additional details to the programmer about the cause of the
failure.
所构造的message在发生错误时显示给用户,便于快速发现错误所在
12 Construction for Robustness and Correctness
Assertion in Java
§ To assert that x is non-negative, you can simply use the statement
assert x >= 0;
§ Or pass the actual value of x into the AssertionError object, so that
it gets displayed later:
assert x >= 0 : “x is ” + x;
§ If x == -1, then this assertion fails with the error message
x is -1 § This information is often enough to get started in finding the bug.
12 Construction for Robustness and Correctness
Assertion Example
public class AssertionSwitchTest {
public static void main(String[] args) {
// assumed either ‘+’, ‘-’, ‘', ‘/’ only
char operator = ‘%’;
int operand1 = 5, operand2 = 6, result = 0;
switch (operator) {
case ‘+’: result = operand1 + operand2; break;
case ‘-’: result = operand1 - operand2; break;
case '
’: result = operand1 * operand2; break;
case ‘/’: result = operand1 / operand2; break;
default: assert false : "Unknown operator: " + operator;
}
System.out.println(operand1 + " " + operator + " "

  • operand2 + " = " + result);
    } }
    Software Construction
    (2) What to Assert and What not to?
    12 Construction for Robustness and Correctness
    When use assertions?
    § Assertion can be used for verifying:
    – Internal Invariants 内部不变量: Assert that a value is within a certain
    constraint, e.g., assert x > 0. – Rep Invariants 表示不变量: Assert that an object’s state is within a
    constraint. What must be true about each instance of a class before or after
    the execution of a method? Class invariants are typically verified via
    private boolean method, e.g., checkRep(). – Control-Flow Invariants 控制流不变量: Assert that a certain location will
    not be reached. For example, the default clause of a switch-case
    statement.
    – Pre-conditions of methods 方法的前置条件: What must be true when a
    method is invoked? Typically expressed in terms of the method’s
    arguments or the states of its objects.
    – Post-conditions of methods 方法的后置条件: What must be true after a
    method completes successfully?
    12 Construction for Robustness and Correctness
    What to Assert? § Pre-condition: method argument requirements
    § Post-condition: Method return value requirements
    – This kind of assertion is sometimes called a self check .
    public double sqrt(double x) {
    assert x >= 0;
    double r;
    … // compute result r
    assert Math.abs(r*r - x) < .0001;
    return r;
    }
    12 Construction for Robustness and Correctness
    What to Assert? § Control-flow: covering all
    – If a conditional statement or switch does not cover all the possible
    cases, it is good practice to use an assertion to block the illegal
    cases. switch (vowel) {
    case ‘a’:
    case ‘e’:
    case ‘i’:
    case ‘o’:
    case ‘u’: return “A”;
    default: assert false;
    }
    void foo() {
    for (…) {
    if (…)
    return;
    }
    assert false;
    // Execution should never reach this point!
    }
    But don’t use the assert statement here, because it can be turned off. Instead, throw an
    exception in the illegal cases, so that the check will always happen:
    default: throw new AssertionError("must be a vowel, but was: "
  • vowel);
    12 Construction for Robustness and Correctness
    Example
    What statements would be
    reasonable to write at
    position A?
    And at position B?
    • assert a != 0;
    • assert b != 0;
    • assert c != 0;
    • assert roots.size() >= 0;
    • assert roots.size() <= 2;
    • for (double x : roots) { assert
    Math.abs(axx + b*x + c) < 0.0001; }
    12 Construction for Robustness and Correctness
    When to use assertions?
    § Normally, you don’t want users to see assertion messages in
    production code; assertions are primarily for use during
    development and maintenance. 断言主要用于开发阶段,避免引入 和帮助发现bug
    § Assertions are normally compiled into the code at development
    time and compiled out of the code for production. 实际运行阶段,
    不再使用断言
    § During production, they are compiled out of the code so that the
    assertions don’t degrade system performance. 避免降低性能
    § When should you write runtime assertions? 使用断言的主要目的是
    为了在开发阶段调试程序、尽快避免错误
    – As you write the code, not after the fact. When you’re writing the code,
    you have the invariants in mind.
    – If you postpone writing assertions, you’re less likely to do it, and you’re
    liable to omit some important invariants.
    12 Construction for Robustness and Correctness
    Avoid putting executable code in assertions
    § Since assertions may be disabled, the correctness of your program
    should never depend on whether or not the assertion expressions
    are executed.
    § In particular, asserted expressions should not have side-effects . – For example, if you want to assert that an element removed from a list was
    actually found in the list, don’t write it like this:
    § If assertions are disabled, the entire expression is skipped, and x is
    never removed from the list. Write it like this instead:
    // don’t do this:
    assert list.remove(x);
    // do this:
    boolean found = list.remove(x);
    assert found;
    12 Construction for Robustness and Correctness
    Don’t Assert External Conditions
    § Never use assertions to test conditions that are external to your
    program. 程序之外的事,不受你控制,不要乱断言
    – Such as the existence of files, the availability of the network, or the
    correctness of input typed by a human user. 文件/网络/用户输入等 – Assertions test the internal state of your program to ensure that it is within
    the bounds of its specification. 断言只是检查程序的内部状态是否符合规约
    – When an assertion fails, it indicates that the program has run off the rails
    in some sense, into a state in which it was not designed to function
    properly. Assertion failures therefore indicate bugs. 断言一旦false,程序
    就停止执行
    – External failures are not bugs, and there is no change you can make to
    your program in advance that will prevent them from happening. 你的代
    码无法保证不出现此类外部错误
    – External failures should be handled using exceptions instead. Avoid trivial
    assertions, just as you would avoid uninformative comments. 外部错误要
    使用Exception机制去处理
    12 Construction for Robustness and Correctness
    Turn on/off Assert in different phases
    § Many assertion mechanisms are designed so that assertions are
    executed only during testing and debugging, and turned off when
    the program is released to users.
    – Assertions are a great tool for keeping your code safe from bugs,
    but Java has them off by default! Java缺省关闭断言,要记得打开(-ea) § The advantage of this approach is that you can write very
    expensive assertions that would otherwise seriously degrade the
    performance of your program. 断言非常影响运行时的性能
    – For example, a procedure that searches an array using binary search has a
    requirement that the array be sorted.
    – Asserting this requirement requires scanning through the entire array,
    however, turning an operation that should run in logarithmic time into
    one that takes linear time.
    – You should be willing to pay this cost during testing, since it makes
    debugging much easier, but not after the program is released to users.
    Software Construction
    (3) Guidelines for Using Assertions
    12 Construction for Robustness and Correctness
    Assertion vs. Exception?
    § Assertions generally cover correctness issues of program.
    – If an assertion is fired for an anomalous condition, the corrective action is
    not merely to handle an error gracefully—the corrective action is to
    change the program’s source code, recompile, and release a new version of
    the software. 断言àCorrectness
    § Exceptions generally cover robustness issues of program.
    – If error handling code is used to address an anomalous condition, the
    error handling will enable the program to respond to the error gracefully.
    错误/异常处理àRobustness
    § Assertions are especially useful in large, complicated programs
    and in high reliability programs.
    – They enable programmers to more quickly flush out mismatched interface
    assumptions, errors that creep in when code is modified, and so on.
    12 Construction for Robustness and Correctness
    Assertion vs. Exception?
    § Use error handling code (exception) for conditions you expect to
    occur 使用异常来处理你“预料到可以发生”的不正常情况
    – Error handling code checks for off-nominal circumstances that might not
    occur very often, but that have been anticipated by the programmer who
    wrote the code and that need to be handled by the production code.
    § Use assertions for conditions that should never occur 使用断言处理
    “绝不应该发生”的情况
    – Assertions check for bugs in the code.
    12 Construction for Robustness and Correctness
    Use Assertions for pre-/post- conditions
    § If the variables latitude, longitude, and elevation were coming
    from an external source, invalid values should be checked and
    handled by error handling code rather than assertions. 如果参数来
    自于外部(不受自己控制),使用异常处理
    § If the variables are coming
    from a trusted, internal source,
    however, and the routine’s
    design is based on the
    assumption that these values
    will be within their valid
    ranges, then assertions are
    appropriate. 如果来自于自己
    所写的其他代码,可以使用断
    言来帮助发现错误(例如postcondition就需要)
    float latitude;
    float longitude;
    float elevation;
    //Preconditions
    assert latitude>=-90 && latitude<=90;
    assert longitude>=0 && longitude<360;
    assert elevation>=-500 && elevation<=7500
    //Postconditions
    assert Velocity>=0 && Velocity <= 600
    return Velocity;
    12 Construction for Robustness and Correctness
    Combine assert & exception handling for robustness
    § Both assertions and exception handling code might be used to
    address the same error. 断言和异常处理都可以处理同样的错误
    – In the source code for Microsoft Word, for example, conditions that
    should always be true are asserted, but such errors are also handled by
    error-handling code in case the assertion fails.
    – For extremely large, complex, long-lived applications like Word,
    assertions are valuable because they help to flush out as many
    development-time errors as possible.
    § But the application is so complex (million of lines of code) and has
    gone through so many generations of modification that it isn’t
    realistic to assume that every conceivable error will be detected
    and corrected before the software ships, and so errors must be
    handled in the production version of the system as well.
    开发阶段用断言尽可能消除bugs
    在发行版本里用异常处理机制处理漏掉的错误
    Software Construction
    6 Defensive Programming
    12 Construction for Robustness and Correctness
    What is defensive programming?
    § The idea is based on defensive driving
    – You adopt the mind-set that you’re never sure what the other drivers are
    going to do.
    – That way, you make sure that if they do something dangerous you won’t
    be hurt.
    – You take responsibility for
    protecting yourself even
    when it might be the other
    driver’s fault.
    – 眼观六路,耳听八方,一旦
    其他车辆有对你产生危险的
    症状,马上采取防御式行动
    12 Construction for Robustness and Correctness
    Techniques for defensive programming
    § Protecting programs from invalid inputs
    § Assertions
    § Exceptions
    § Specific error handling techniques
    § Barricade
    § Debugging aids
    § The best form of defensive coding is not inserting errors in the
    first place.
    § You can use defensive programming in combination with the other
    techniques.
    12 Construction for Robustness and Correctness
    (1) Protecting Programs From Invalid Inputs
    § “Garbage in, garbage out”
    – That expression is essentially software development’s version of caveat
    emptor: let the user beware. 货物出门概不退换 § For production software, garbage in, garbage out isn’t good
    enough.
    § A good program never puts out garbage, regardless of what it takes
    in.
    – “Garbage in, nothing out”
    – “Garbage in, error message out”
    – “No garbage allowed in”
    § “Garbage in, garbage out” is the mark of a sloppy, non-secure
    program.
    12 Construction for Robustness and Correctness
    Protecting Programs From Invalid Inputs
    § Check the values of all routine input parameters 对每个函数的输入
    参数合法性要做仔细检查,并决定如何处理非法输入
    – Checking the values of routine input parameters is essentially the same as
    checking data that comes from an external source, except that the data
    comes from another routine instead of from an external interface.
    § Decide how to handle bad inputs
    – Once you’ve detected an invalid parameter, what do you do with it?
    – Depending on the situation, you might choose any of a dozen different
    approaches, which are described in detail later in this chapter.
    12 Construction for Robustness and Correctness
    (2) Barricade 设置路障
    § Barricades are a damage-containment strategy.
    – The reason is similar to that for having isolated compartments in
    the hull of a ship and firewalls in a building.
    – One way to barricade for defensive programming purposes is to
    designate certain interfaces as boundaries to “safe” areas.
    – Check data crossing the boundaries of a safe area for validity and
    respond sensibly if the data isn’t valid.
    Defining some parts of the
    software that work with dirty
    data and some that work with
    clean can be an effective way
    to relieve the majority of the
    code of the responsibility for
    checking for bad data.
    12 Construction for Robustness and Correctness
    Relationship between Barricades and Assertions
    § The use of barricades makes the distinction between assertions
    and error handling clean cut.
    – Routines that are outside the barricade should use error handling because
    it isn’t safe to make any assumptions about the data.
    – Routines inside the barricade should use assertions, because the data
    passed to them is supposed to be sanitized before it’s passed across the
    barricade. If one of the routines inside the barricade detects bad data,
    that’s an error in the program rather than an error in the data.
    § “隔离舱”外部的函数应使用异常处理,“隔离舱”内的函数应使用
    断言。
    – The use of barricades also illustrates the value of deciding at the
    architectural level how to handle errors.
    – Deciding which code is inside and which is outside the barricade is an
    architecture-level decision.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值