On Coding
Situation
大型的代码具有高度的复杂性。复在逻辑上指系统的规模庞大,在物理上指原文件数量多,行数多。杂,指的是每一个子模块都有特异性。 写代码的时候,常常感觉思路不清晰,不知道下一行该写什么:(
具体来说容易陷入几种困境
- 越写越抽象,写到最后自己都没有信心了。完全不知道里面有多少错误。感觉像迷路了。
- 大概知道应该怎们写,但是无从下笔。迈不出第一步。
- 写的很慢。写一行,突然感觉别的地方错的要,回去改好几行。
Plan before start
一开始在全局计划代码需要做的事情是绝对必要的。唯一的问题是,这样的计划可能非常大而化之。 有的地方不切实际,有的地方高估复杂度,有的地方基于错误的假设。简而言之,没有切身的实感。一开始的计划可能脱离实际。
这种计划被称为roadmap。我们并不期望这个roadmap完全正确。但是我们严重的依赖它为我们指明道路。 严格执行,或者完全放弃这个计划都不是好的策略。 大多数人都在执行的最佳策略是:执行,或者反馈,调整roadmap。重新执行。
Loop {
制定计划,
执行,
获得反馈,
修改计划,
重新再执行 (继续执行)
....
}
Zoom in and out
我的方案是,一开始不知道怎么进行全局计划,不知道怎么下笔的时候,就从最细节最容易的地方下手开始写。再复杂的逻辑,分解到最毫末,也是简单的。就从最简单的地方开始下手。 但是不能一直陷于细节。每写30-40分钟应该停下来,zoom out,从更高的地方来重新审视这一段细节在全局中的作用。
- 有了细节的工作。全局的计划不在是纸上谈兵。对整个项目有了实实在在的触感后,全局计划会更加优化。
- 从细节中抽离出来,可以重新审视这个细节在全局中的作用,重新审视各个子模块之间的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)压缩分支内的细节,专注上下文。
软件错误一,代码可以正确的处理case1,case2。于是人类有时会把略微不同的case1.1归入case1,错误的认为代码可以处理它。 软件错误二,根本忘了某个case 软件错误三,肉眼执行错误。逻辑上错误以为执行代码会到达某种效果。Semantics错误。 软件错误四,单纯的大脑出错,把19+28算成37