读书人

怎么像计算机科学家一样思考

发布时间: 2012-12-27 10:17:10 作者: rapoo

如何像计算机科学家一样思考

系列名称:如何像计算机科学家一样思考(How to think like a computer scientist)
包含版本:C++、JAVA、Python
我很喜欢这种教育方式~

附录A:程序开发计划
  如果花费了大量的时间在调试上,很可能是因为没有一个有效的程序开发计划。

  一个典型的不好的程序开发计划就像这样:
    1. 编写一个完整的方法。
    2. 编写更多的方法。
    3. 编译程序。
    4. 花一个小时来找语法错误。
    5. 花一个小时来找运行时错误。
    6. 花三个小时来找语义错误。

  显而易见,问题出在头两步。如果写了一个方法甚至很多方法都不调试,那么得到的代码可能已经多得让你无法调试了。 如果遇到这种情况,唯一的解决办法就是删除代码直到再次获得一个可以工作的程序,然后再慢慢将程序增加回来。编程新手往往不希望这么干,因为他们精心编写的代码实在是太宝贝了。可是为了高效的进行调试,你不得不残忍起来!
  下面是一个较好的程序开发计划:
    1. 从一个能做一些直观事情(比如打印一些东西)的程序开始。
    2. 每次增加少许几行代码,并且每次改动都测试程序是否正确。
    3. 重复前两步直到程序满足预期的要求。
  每次改动后的程序都应该产生一些验证新添代码的可见效果。这种编程方式能节省许多时间。因为一次只增加少许几行代码,所以容易发现语法错误;程序的每个版本产生一些可见的结果,这就使你能不断测试自己头脑中关于程序是如何工作的模型。如果头脑中的模型是错的,在写出一大堆错误代码之前你将面对矛盾(并且也有了改正的机会) 。
  这种方式的问题是常常难于找出下手的地方并得到一个完整正确的程序。我将通过开发一个名为isIn 的方法来演示这种方式。 这个方法取一个字符串和一个字符为参数, 返回一个布尔值: 如果字符出现在字符串中就返回 true否则返回 false。
  1. 第一步,写一个尽量短但可以编译、运行并做一些可见的事情的方法:

public static boolean isIn (char c, String s) {     int index = 0;     while (index < s.length()) {         char letter = s.charAt (index);         if (letter == c) {             return true;         }         index = index + 1;     }     return false; }

  如果稍后还要查看这个方法,那么将打印语句注释掉是一个好主意。但如果这个方法是最终版本并且你能确信它是正确无误的,就可以移出这些打印语句了。
  移出注释可以让代码更加干净,也有助于发现遗留的问题。 如果代码的用意并不是很明显,就应该增加注释来解释清除。要抵制逐行翻译代码的诱惑。例如,这样做是毫无必要的:

// if letter equals c, return true
if (letter == c) {
return true;
}

  注释应该用来解释含义不明显的代码,提示容易导致错误的情况和说明包含在代码中的假设。还有,在每个方法之前给出该方法的用途也是一个很好的做法。
  8. 最后一步是检测代码并确认它是正确的。在这里我们知道方法的语法是正确的,因为编译顺利通过。要检查运行时错误,只有找出每个可能导致错误的语句和条件。
  在这方法中唯一能导致运行时错误的语句是 s.charAt (index)。如果s 是null 或者索引超越了边界那么这条语句就将失败。因为s 是一个参数,就不能确保它不是null,所以只有检查。一般说来方法最好都要确认参数的合法性。while 循环的结构保证了 index 总是在0 到 s.length-1 之间。如果检查全部有问题的条件,或者证明这些条件不可能发生,那么就证明了方法不会导致运行时错误。
  我们还没有证明这个方法的语义是正确的,但在逐步递增的过程中,避免了很多可能的错误。例如已经知道方法能正确取得参、循环遍历了整个字符串。我们还知道这个方法成功的比较了字符,如果目标在字符串中就返回true。最后我们知道,如果循环存在就表明目标不在字符串中。
  在没有正式证明的情况下,这可能是我们能做到的最好情况。

1 楼 juda 2011-06-08 格式不能调整下?

读书人网 >编程

热点推荐