写代码的时候,反复修改是常见的事,修改之后忘记以前是什么样子好像也很常见。
如何才能够回溯那些被自己覆盖掉的代码片段?美国田纳西大学的助理教授 Austin Z. Henley 介绍了自己开发的工具 Yestercode,它能让回溯代码就像播放视频拉进度条一样简单。
这个工具在程序员们聚集的社区 HackerNews 上引发了人们的讨论。
一项研究发现,Java 开发者在写代码的时候平均每 6 分钟回溯一次,这意味着他们经常会需要使用 undo 按钮或 Ctrl+z 让代码恢复到之前的状态。这些撤销动作显然并不是预先可知的,而且随后肯定会接着覆盖重写。
事实上,在另一项研究中,有开发者在 5 分钟内进行了 40 次 undo/redo 操作。当被问及为什么要这样做的时候,程序员的回答通常是:他们在试图回想起被修改部分代码的某个中间状态。那么问题来了,为什么想看到之前写过的代码就这么难?
Undo 到尽头
对于代码工作来说,撤销和重写按钮总是很有意义的设计。但这里会存在一些问题:(1)如果回溯之前的状态,进行了新的更改,之前的状态就会丢失。(2)人们无法看到改前改后状态的直接对比。(3)没有提示符直观指示你在撤销 / 重写历史的具体位置。(4)有些代码编辑器使用全局 undo 堆栈,有些代码编辑器为每个打开的文档使用撤消堆栈,这可能会干扰你执行操作顺序的思维方式。(5)代码编辑器中还有很多动作是不会被加入 undo 堆栈中的(比如修改 debugger 选项),这在调试 bug 的时候会让人头疼。(6)一次回撤一小步,不知何时才能到尽头。
这个吐槽的列表还能继续列下去。
使用版本控制
有人说:「为什么很多程序员都习惯使用 undo/redo?版本控制可以解决所有问题。」
但实际情况是版本控制并不会奏效。当开发人员对代码进行更改时,他们可能会对代码进行很多改动并陷入困境,然后过了一会才能意识到想要的是某种中间版本。这就迫使开发人员在他们得到做出决定所需信息之前,保存一个中间版本。除非每隔几分钟将代码放到 git 库,无论其是否有效,因此版本控制在此并不会有所帮助。
开发人员通常对找到所需信息过于自信,而且他们大大低估了找到这些信息所需的工作量。
复制文件
开发人员在更改过程中,要么复制代码文件,给相关代码截图。他们可能会有这样的想法:「我要把代码弄乱了,在弄乱之前,我要用 Ctrl-A 和 Ctrl-V 将它复制到一个新的标签页中,然后把该窗口放在编辑器旁边,用作参考。」甚至有从业 20 年的开发者也是这样做的。
回到最初的问题:为什么想回头看 5 分钟前的代码就这么难?为什么代码编辑器不能更好地执行这种行为?
使用 Yestercode 来挽救
Austin Henley 表示他早在 2015 年就开始草拟了一些设计方案,旨在为开发人员提供所需的信息,且所需的工作量较少。在他的设计中,开发人员可以一同查看代码的新版本和原版本,同时自动记录重要更改。由于 Henley 可以访问 LabVIEW 编辑器的源代码,因此他为 LabVIEW 的实验版创建了一个带有已启用功能的分支。
尽管 LabVIEW 是一种可视化的拖放(drag-and-drop)语言,但这种设计思想也适用于传统编辑器。然后 Henley 将其演示给了数十位开发人员、经理和其他 LabVIEW 用户,以获取反馈并进行迭代。
之后,Austin Henley 开发了一个名叫 Yestercode 的工具。它可以让你在时间轴上浏览代码历史纪录就像看 YouTube 视频一样。进行回溯编辑时,它可以汇总新的修改,并在时间轴上为这个版本建立分支。在这以后,你可以使用时间轴转到先前的版本,并与当前版本的代码并排查看。以前的版本是只读的,但仍允许人们从中复制粘贴。最后,这个工具还显示注释,以便于人们知晓在更高版本上(比如 diff)进行过哪些更改。
几年前,Henley 花费了一些时间把 Yestercode 做成了 Atom 插件,事实证明它对其他种类的代码也很有用。
这还没有完,Henley 希望能让这样的比较工具接手所有的文字版本,包括 word 文档、电子表格和 PDF,新的工具目前也已有了原形。
这样真的可以行得通吗?等到它正式上线之后,我们就可以评判一下了。