“背”算法和写代码
高中的时候第一次接触快排的时候,发现即便知道了算法的思想和基本过程,自己写出一个完整的代码,并不是容易的事情。不像做上学题目一样,基本思路有了,基本也就做出来了。当时真的很沮丧,发现写出一个一定程度上可以证明是正确的,都是很难的。当时发现不仅仅是快排,很多程序都不是那么好写,或者说只能写出个样子,却无法放心这样写是不是对的,包括后来的著名的2分查找。当时我就有个疑问,难道学编程,这些基本的东西要背下来么?不会的,不会的。
再后来的日子里,一直伴随着这种失落感,编程接触的也越来越多。有些很容易写出代码,比如动态规划的程序,或者逻辑非常清晰的程序,比如大部分递归的算法。有些很麻烦,基本上要写的时候还要debug,比如一些复杂的数据结构的操作代码,但是这些还算容易从代码上证明基本上正确。最难写的,还是上面提到的某些“短”的代码,比如二分查找和快排之类,如果不知道里面的变量在循环等结构里保持何种关系,所谓循环不变式,只有每次写的时候,从书上认真再去复查,才敢心安。
于是后来开始思考,我要依赖代码重用还是依赖书籍,甚至自己背下来?重用也许是最合理的想法,所以不要再去造轮子。不过,总有一些情况你无法重用曾经的代码,使用一些标准库,然而在很多语言,标准库对于基础算法的封装,并不总是够用的。(Knuth对传统黑箱式的重用就说"有偏见")。另外,从某个意义上,不会造基本的轮子的程序员估计在很多人眼里算不上合格的程序员。
其实大部分情况下都是复制粘贴吧,也许。本质上还是依赖书籍。不过,即便如此,不理解为什么代码这么写,复制粘贴不能解决心中的问题!于是乎,还得把代码的一些关键的地方“背”下来,记下隐藏在i,j后的循环不变式,可能发生的边界问题等等。去年做acm题目的时候,发现大量的时间还是费在一些基本算法的使用上,后来才知道,真正参赛的选手都是要把那些基本算法背的很熟才行的。不过,如何写好算法的代码本身也是个值得思考的问题。一个代码写的好不好,缩进和命名都是表面的,关键是,是不是很尽量能被理解和证明正确性。可读性并不仅仅是文本上的。现实中,我们可能经常看到一些代码,看上去也是工作的,有些复杂,然而,很难看到其中一种条理性:这一段之后,会是什么样的,这个循环每次的入口是个什么样的,我能控制得了。失控的代码,结果总是等到debug的时候修修补补。其实是和自己过不去,代码基本上没办法证明是对的。
我平时写代码还算认真,也喜欢仔细思考每一小段代码的前后(广义上,都算入口和出口)是不是可控的。但是项目一忙,而且很多事情本身就是一个比较让人烦闷的事情,比如merge code,人总是来不及思考,结果让更多的时间给了将来去浪费。
PS,后来,终于在算法导论上看到了快排的一个更优良的划分方式,这个比以前的霍尔的快排要容易理解和证明的多,当时感到十分惊艳,也觉得终于拿掉了当年心中的一个石头。这个算法,好“背”多了。
无论如何,做一个心中合格的程序员还是很难得,还有很长的路。很多人看不起Coder,可是,做一个合格的coder, 也许比很多角色要难很多!而做一个合格的coder,也许是很多所谓光鲜角色的基础,然后,现在看上去很多都是本末倒置。
2 COMMENTS:
2009年4月9日 22:39
姑妈:你的blog在firefox下页面看起来很乱啊,不过这篇我很喜欢。
2009年4月12日 13:48
囧 ,我一般看看IE下面和Chrome下面可是对的,看来现在要看所有的浏览器。。。。。。
发表评论