Lecture 8: Avoiding Debugging

1 First Defense: Make Bugs Impossible

  • Static checking
  • Dynamic checking
  • Immutability
    • Use immutable type
    • Use immutable reference: use final for declaring the parameters of a method and as many local variables as possible.

2 Second Defense: Localize Bugs

  • Fail fast is a design princeple:: Checking preconditions is an example of defensive programming. For example:
 /**
 * @param x  requires x >= 0
 * @return approximation to square root of x
 */
public double sqrt(double x) { 
    if (! (x >= 0)) throw new AssertionError();
    ...
}

3 Assertions

  • For most applications, assertions are not expensive compared to the rest of the code, and the benefit they provide in bug-checking is worth that small cost in peformance.
  • Java assert statement is a different mechanism from the JUnit methods assertTrue(), assertEquals() , etc. They are designed for use in different contexts.
3.1 What to Assert
  • Method argument requirements
  • Method return value requirements
public double sqrt(double x) {
    assert x >= 0;
    double r;
    ... // compute result r
    assert Math.abs(r*r - x) < .0001;
    return r;
}
  • Covering all cases
switch (vowel) {
  case 'a':
  case 'e':
  case 'i':
  case 'o':
  case 'u': return "A";
  default: assert false;
}
3.2 What Not to Assert
  • If an assertion is obvious from its local context, leave it out.
  • 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. Use Exception instead.
  • Java’s assert statement are designed so that assertions are executed only during testing and debugging, and turned off when the program is released to users.
  • Asserted expressions should not have side-effects, since assertions may be disabled.

4 Modularity & Encapsulation

  • Modularity: Modularity means dividing up a system into components, or modules, each of which can be designed, implemented, tested, reasoned about, and reused separately from the rest of the system.
  • Encapsulation: Encapsulation means building walls around a module (a hard shell or capsule) so that the module is responsible for its own internal behavior, and bugs in other parts of the system can’t damage its integrity.
    • Access control: Keeping things private as much as possible.
    • Variable scope: Keeping variable scopes as small as possible.
      • Avoid global variables.
      • Always declare a loop variable in the for-loop initializer.
      • Declare a variable only when you first need it, and in the innermost curly-brace block that you can. But in dynamic language, like python, the scope of a variable is normally the entire function anyway, so you can’t restrict the scope of a variable with curly braces.

Reference

[1] 6.005 — Software Construction on MIT OpenCourseWare | OCW 6.005 Homepage at https://ocw.mit.edu/ans7870/6/6.005/s16/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值