前言

调试比编写程序要困难两倍。如果你在编程时使出了所有聪明,那你要如何调试它呢? – 《The Elements of Programming Style》

调试功能是 Snap! 相比于 Scratch 的最大改进之一。

这个改进极大增强了可理解性, 尤其是复杂程序的可理解性。没有调试功能, 构建和理解大型程序都是令人生畏的。

在调试中理解程序,而不是通过阅读代码来理解程序, 是 Smalltalk 的传统之一。在 Smalltalk 中, 所有的开发工作都可以在调试器中完成, 人们喜欢以调试为中心的编程(这导致了测试驱动, 测试驱动(TDD)范式最初来自 Smalltalk)。作为 Smalltalk 的后代, Snap! 具有出色的调试能力。

我们在施乐帕克实验室的工作并不是研究计算, 而是研究人 – Alan Kay

Smalltalk 鼓励用户与程序交互, 并在交互中建立理解。这是人类习惯的认知方式。 我们生活在物理世界中, 物理世界的交互性极好(一致性也极其出色), 我们在出生之后,不是通过阅读这个世界的说明书(物理学)来理解世界的,而是在交互/反馈循环中理解这个世界。

宇宙最不可理解之处, 在于它是可理解的 –爱因斯坦

调试这个程序

(可参考 视频教程)

我们可以通过调试这个简单程序来弄清楚 Snap! 的所有调试功能:

这个程序非常简单, 它将循环 1000 次, 每次会把当前循环计数说出来, 程序在运行过程中会修改一个全局变量。 通过暂停和恢复程序, 并观察变量的变化, 对比你的预期和实际结果, 在这个过程弄清 Snap! 的调试功能。

红色箭头所指的之处是 Snap! 中与调试有关的东西:

  1. 单步运行(step)开关, 点击开启时, 程序将单步运行, 当前运行的积木将被高亮。 用户可以通过 slider 控制单步运行的速度, 拉到最左边, 每次运行一个积木
  2. 暂停和恢复程序
  3. 程序将停止在这个积木位置。类似其他编程语言的断点

条件断点

如果你只希望在 i==50 时暂停程序, 可以这样做:

其他调试技巧

前边的调试都属于断点调试

打印 log 是另一种常见的调试方法, 介绍 3 种打印 log 的方式

  • say
  • debuglog
  • console.log

say

使用 say 积木是最简单的 log 方式, 它每次只能显示一条信息,适用于简单调试。

debugLog

debugLog 的想法是使用一个变量(列表)来存下所有记录的信息.

我在 dynatalk 库 中使用了这个技巧:

@邵悦 在 MicroBlocks 也有类似做法 如何使用MicroBlocks中的 log4M 日志库,实时监控程序进程

或许我们应该在 Snap! 中将 debugLog 剥离为一个库, 就像 @邵悦 在 MicroBlocks 里做的。

console.log

使用浏览器的 console.log 来记录 log:

我们可以通过 JavaSccript function 来使用 console.log。 你需要先开启 JavaScript 扩展。

FAQ

启动和停止按钮如何影响程序生命周期?

  • 启动: 只影响绿旗触发的程序
  • 停止: 停止所有正在运行的程序

值得注意的是, 它们都不会重置程序的状态! 诸如本文例子中的 test 变量状态不会被重置(动手做个实验试试)

如何调试自定义积木?

开启调试模式的情况下, 展开自定积木, 会逐个高亮运行内部积木:

参考