Situation

大型的代码具有高度的复杂性。复在逻辑上指系统的规模庞大,在物理上指原文件数量多,行数多。杂,指的是每一个子模块都有特异性。 写代码的时候,常常感觉思路不清晰,不知道下一行该写什么:(

具体来说容易陷入几种困境

  1. 越写越抽象,写到最后自己都没有信心了。完全不知道里面有多少错误。感觉像迷路了。
  2. 大概知道应该怎们写,但是无从下笔。迈不出第一步。
  3. 写的很慢。写一行,突然感觉别的地方错的要,回去改好几行。

Plan before start

一开始在全局计划代码需要做的事情是绝对必要的。唯一的问题是,这样的计划可能非常大而化之。 有的地方不切实际,有的地方高估复杂度,有的地方基于错误的假设。简而言之,没有切身的实感。一开始的计划可能脱离实际。

这种计划被称为roadmap。我们并不期望这个roadmap完全正确。但是我们严重的依赖它为我们指明道路。 严格执行,或者完全放弃这个计划都不是好的策略。 大多数人都在执行的最佳策略是:执行,或者反馈,调整roadmap。重新执行。

Loop {
    制定计划,
    执行,
    获得反馈,
    修改计划,
    重新再执行 (继续执行)
    ....
}

Zoom in and out

我的方案是,一开始不知道怎么进行全局计划,不知道怎么下笔的时候,就从最细节最容易的地方下手开始写。再复杂的逻辑,分解到最毫末,也是简单的。就从最简单的地方开始下手。 但是不能一直陷于细节。每写30-40分钟应该停下来,zoom out,从更高的地方来重新审视这一段细节在全局中的作用。

  1. 有了细节的工作。全局的计划不在是纸上谈兵。对整个项目有了实实在在的触感后,全局计划会更加优化。
  2. 从细节中抽离出来,可以重新审视这个细节在全局中的作用,重新审视各个子模块之间的protocol是否合理。

DFS Approach

人类的大脑类似电脑:既有信息处理的能力,又有短期存储,又有中期存储,以及长期存储。这像极了计算机的多级存储:L1/L2 CPU Cache, Memory, Disk。 人脑特别的地方在于,人脑内短期塞入的信息越多,分析能力越会下降。塞入的东西越少,分析能力越强。举例来说,只看迷宫的一角,人可以很容易的看出正确的路线。 如果迷宫的全图都在眼前,人脑则可能当机。

正确的处理方法,当然是不要尝试把迷宫的全图塞进脑袋。而只是专注于迷宫入口的一小块区域。分析,列出可能的路线1,2,3. 接下来,顺着路线1,视野进入另一块小区域,专注进行分析。列出可能的路线1.1,1.2,1.3。如果有的子自路径都进入死胡同,或者开始兜圈。则退回探索路径2。

以上所述的处理方法,就是典型的DFS。同样的,也和上一段提到的从最细节下手一致。 然而值得注意的是:人类无法像电脑一样精准的执行DFS。所以需要常常zoom out来验证大的线路有没有误差和偏移。电脑却不需要zoom in and out。

人脑的弱点是(1)没有办法把大量信息放入缓存而不影响信息处理(2)没有办法完全准确的处理 为了解决问题一,人脑自动发明了模糊处理,人脑没有focus on的大块信息,会自动被忽略掉。使得信息处理可以流畅,加快。 为了解决问题一,软件工程发明了modularity。 为了解决问题二,人们会反复的核对检查自己的工作,甚至请人进行交叉检查。 为了解决问题二以及问题一的副作用,软件工程发明了单元测试。单元测试当然可以捕捉人类的逻辑错误。单元测试还能够捕捉人类的模糊处理带来的错误。下面会具体的说。

Bugs in your code

有过写代码经验的人都知道,没有测试就没有正确的代码。人脑的能力是有极限的。

  1. 人脑没有办法在同一时间塞入大量的资讯,进行无错误的处理。
  2. 人脑擅长载入较少的资讯,进行超级精细化的处理。
  3. 当其中的某一部分的内容迅速膨胀的时候。有两个选择,(1)进入分支,抛弃上下文。(2)压缩分支内的细节,专注上下文。

软件错误一,代码可以正确的处理case1,case2。于是人类有时会把略微不同的case1.1归入case1,错误的认为代码可以处理它。 软件错误二,根本忘了某个case 软件错误三,肉眼执行错误。逻辑上错误以为执行代码会到达某种效果。Semantics错误。 软件错误四,单纯的大脑出错,把19+28算成37