《Code Complete》笔记(一)
第1章
构建(Construction)的确是软件工程中最主要的环节。特别的,在我们的信息学竞赛这一规模很小的“工程”中,Design和Testing可探讨的空间不大不大。Design过程中出错几乎无药可救,Testing一般不会出什么错;或者说,OI中的Design和Testing不属于“工程”的范畴,可称作工程的只有Construction,也就是Programming。
第2章
在隐喻的层面,软件业界中已经广泛地认识到了增量开发的重要性,而信息学竞赛的语境中还使用着一套相当落后的隐喻(写信?),甚至有很多人从来没用过什么软件工程意义上的隐喻。应该把写程序看成一个“培育”的过程,一点一点做,最终长出珍珠;建造/修饰的隐喻体系也不错。这两个隐喻体系和分点测试的OI在精神层面上是暗合的。
在中国的比赛的环境中,“买得到的东西”比较少,但正因为如此,我们应该更娴熟地掌握和运用它们。比如说,我已经很长时间以来都没有写过qsort了。
规划得当的项目具有“在后期改变细节设计”的能力。我们书写的代码也应当如此。比如说,把我的网络流程序的存储方式由邻接表改成邻接矩阵(或者相反),我可以保证一切需要改变的不超过5行代码。这需要一种成熟和良好的书写模式/习惯。
总的来说,隐喻这种东西对于OI来说,在软件工程的层面的启示并不大,我们使用更多的是利用隐喻来理解算法。最简单的,其实“Queue”或者“Tree”都是隐喻。
第3章
OI中,构建前的前期准备让人困惑。似乎就是想出来算法吧。但是,你真的“想出来”算法了吗?或者说……你真的准备好了吗?在写程序之前,和写程序之后,把思路在脑海中理顺一遍似乎是个好主意。
按照正确的顺序做事情,这很重要,在上一章或上上一章也提过。先把圣诞树立起来,再对它作装饰。或者说,先写好DFS的框架,再去剪枝。(注意这也只是一个类比而已。)熟练的OIer写出的DFS框架应该是很容易嵌入剪枝代码的。
发现错误的时间要尽可能接近引入错误的时间。因为修复错误的代价是随着错误诞生的时间呈指数式增长的。我不确定这是否意味着我们应该在写完每一个函数之后先看一遍再开始写下面的东西,因为看上去太浪费时间。也许做到这一点最好的办法还是尽量的增量开发吧。
选择序列式开发法和迭代式开发法各有不同的理由,他们适用范围就不同。但我认为仅仅一个理由就可以让OI采用迭代式开发法(在这个语境下“增量式”似乎是更好的描述?):分点测试。
“需求”的概念在软件开发中性命攸关,但在OI中似乎真的没有它的位置。“架构”这种东西似乎也一样。
OI中,解决一道题有多少时间需要花费在前期准备上?似乎是因题而异的。唯一可以确定的大约有两点:如果你发现看完题后一秒钟就可以开始写代码了了,那么最好再看一遍;如果这道题的“前期准备”花了10min(或者一个更为妥帖的时间限制)屏幕上还没有一行像样的代码,那么暂时放弃。
第4章
编程语言的选择对软件项目影响巨大,这是经过严格的研究证实的,它甚至影响程序员面对问题时的思维。想必OI中也是这样,比如说你可以看到USACO月赛中从Bronze到Silver至Gold的组别中C/C++对Pascal的比率严格递增。或者说,NOI中使用C/C++的选手比例肯定会比NOIp中高。这也许是互为因果的。
编程约定是一个有用的东西。在我的程序中,它会以变量或函数处的一行注释体现。——变量的意义,表示特殊意义的值(例如-1表示还未计算),调用的先决条件,等等。它们是在实现前写的,而何时需要它们则是一个相当经验性的东西。

matrix67 Said,
May 7, 2007 @ 21:50
我今天在书店看到了,看了命名那一章。