缺牙的时候,我们不停地试探;软件开发,也应如此

缺牙的时候,我们不停地试探;软件开发,也应如此小时候掉牙了的时候,总是用舌头去舔那个缺口,一直到牙齿完全长出来,似乎
想时刻确定它长到了什么程度。最有意思的是,家长告诉,不要去舔,会长歪
的;越是这样,我们越想确定,它歪了么?我在芬兰有一次坐长途大巴,那个司机的头顶大半秃了。之所以能让我有这么深
刻的印象,是因为那几个小时里,他一直轮换着用一只手去摸头顶。似乎这样能
长出来,或者确定没长出来?我们在构造物品,搭积木,或者盖房子的时候,无一不是如此。我们在每一个步
骤测试,确定产品(此处应作人工制品,但是这字太小资了)确实按我们计划开
发,这一个小部分,也符合我们的预期。中间没有任何测试过程,期待直接完成,是愚蠢的。治病的时候,医生也要不停地测试--抽血,验尿,然后才敢给你下药。我们的所
有行为,都依赖于对世界的观察。谈恋爱的人们,小心翼翼地试探--今天气你一次,明天考验你一下。揪玫瑰花瓣
这种行为,大抵只能用于测试智商,或者投入程度了。软件开发中,我们也需要在每个阶段,测试每个单元是否按我们预想的那样工作。
如果"是",那么我们继续。如果"不是",我们要做的不是继续突进,而是停下来
想想哪里出了毛病。这也是我们设计实验和写实验报告的不二法门。遗憾的是,计算机系的似乎有把实验报告写得很糟烂的传统?那么一页半的代码
和结果,你是打算让我相信,你从头开始敲代码,敲到最后,然后编译就通过了
么。那么,你一定不知道,代码不是从上向下写的。从上向下写,就像画蒙娜丽
莎的时候,把这杰作分成1024行,然后一行一行从下向下扫描。写代码,也是先
写眼睛,再写耳朵,可能再改下眼睛...这样的顺序。即使很短的代码也是这样。所以,在不断的修改中,我们需要始终保证我们的代码还是按我们预想的方式工
作的。这就需要测试。说到这里,我总会回想起小时候做航模,没有耐心等到胶完全固化就想去测试机
翼和机身连接的强度。好在,软件从写出来到测试,快得多。前两天写了500来行java,有如下体会,与测试和观察软件的行为有关。在软件从第一行开始成长的过程中,我这样确定它,此刻,仍然符合我所想的。1. log - 我要知道一切,用户能看到的,用户看不到的,你所想的。这次我没有用log4j。上次用了,这次最初以为这样部署起来容易一些,现在后
悔了。最初在软件的规模就应该有个估计,这种规模对于我来说,就应该有log
了。log4j与System.out.println()相比,一个明显的好处是,在发布的时候,只要把
输出信息的级别在配置文件中修改一下,就可以阻止所有的调试信息输出。而
System.out.println()一行行注释起来,就容易落了这个丢了那个。即使你有那个精力,用在看碟打游戏上岂不是更好。自动化那些非创造性的工
作,始终都我们追求的一个目标。log非常重要的另一个原因,我和典同学一样,很少使用dbg这类东西,也不用
IDE的messages,而是喜欢自己输出到控制台之类的。log4j的输出可以与正常的
用户会看到的输出分开。2. 测试 - 不停地考验就像搭积木一样,我们总是要在可能不稳固的地方设置一两个测试点,输出一些
东西,让我们确认,到这一层,还是稳妥的。不要"相信"代码是正确的。如果它是正确的,那么,运行一下证实,这花不了多
少时间;如果它不正确,你需要第一时间知道真相。在错误的基础之上继续写,
接下来付出的代价,除了失败的经验以外,没有任何收益。Tom Hagen说:"我的
代理人希望第一时间知道坏消息。"放心地一遍遍测试吧,你的代码不会因此而认为你不相信它的--只有上帝(和女
人?)才有这个规定。每当修改一小段代码,就应该测试一下。根据回归测试的原则,任何一处修改,
都可能让原来正确的东西变成错误的。所以,每个修改都应该测试。仍然是那个原则,不要"相信"代码是正确的。下面这个例子,就是我犯的错误。
当时我想,这么简单的修改,就不必测了。直到十多分钟以后,发现这家伙的行
为不正常。可是这个醉汉已经又走出好远了。错误的代码:
: while (i.hasNext())
: {
: String current = i.next();
: if(i.next()==null || value==null)
: {
: return false;
: }
: else if(eval(i.next()).equals(eval(value)) )
: {
: return true;
: }
: }正确的代码:: while (i.hasNext())
: {
: String current = i.next();
: if(current==null || value==null)
: {
: return false;
: }
: else if(eval(current).equals(eval(value)) )
: {
: return true;
: }
: }如果我当时做了回归测试,就可以马上发现错误的代码中副作用-- i.next()不
仅取出了值,也移动了"指针"。这样的错误在C/C++中也常发生。3. 一个小技巧如果我们在回归测试中,不断地观察程序的输出,就需要集中注意力找"不同"。
如果输出是一大摊的话,那就更是麻烦,可能还要翻页才行。这也可以自动化。我们可以先把正确的输出写下来,文件名叫 expect.txt 吧。然后我们把每次的输入写下来,文件名叫 input.txt 吧。
如果你有多组输入,多整几个文件。然后我们这样运行我们的程序:proc.exe < input.txt > output.txt如果你有多组输入,就做个批处理,这样:proc.exe < input1.txt > output.txt
proc.exe < input2.txt > output.txt
proc.exe < input3.txt > output.txt现在,可以看看程序是否按我们期待的运行了,基本不需要眼睛:diff output.txt expect.txt如果啥输出也没有,那就是它俩完全相同。这与自然科学研究的技术路线差不多。先做实验,或者观察世界,得到expect.txt;然后假说,得到proc.exe;最后看看proc.exe运行的结果output.txt与实验结果expect.txt是否一样。如果结果好,那么写论文;如果结果不好,有些人会假装没看到,或者...反正
修改实验结果是不行的,因为还有别人也会做实验。4. 更好的东西上述小技巧可以写成一个批处理,改会代码,编译,然后就跑一遍这个批处理。
最初每次期望与结果都是不一样的,也就是还不成。再改再改,后来,diff不出
声了。大功告成。这个批处理的路子早就被俺们这个学科的古人发现了,并且写成了工具,叫做
JUnit。还有其他语言的版本 cppUnit 啥的。牛人总是N多,所以,我们能想到,必然早就被牛人实现了。就像,剧毒之物五
步以内,必有解药。如果你嫌断肠草药性太烈呢,就自己去动手改进吧。

感谢你们需要我

感谢你们需要我明天教师节,今天马老师的同学请老师吃饭,也带上了我。凡有同学们聚餐,我都是跟同学们一桌。今天不幸开始的时候被马老师留在他那
桌,希望我熟悉一下一年级的同学们。建一说:"你一会过来不",我说"很快"。后
来局面演变成了轮番敬酒的时候,我终于找到了机会,回到另一桌。跟同学们在一起,没人敬我酒,也不必回敬。大家喝得也挺HIGH的。后来,我和
大E跟建一谈人生;很晚,最后只剩下了我们,还有个服务员小伙子在一边整理一
堆台布。散了以后,我跟瀚哥到华润万家,21点多了。我趁超市没下班赶紧跑到楼上,给
二猫买了她要的草莓酱。作为惊喜,又带了一瓶蓝莓酱。下楼,跟瀚哥变人生,到11点多了吧。天很冷,但是我们声音很大,所以没有进
旁边的KFC。我冻得小腿转筋,瀚哥一直抱着肩膀,一身可怜单衣,哆哆嗦嗦。之间或之间或之或,短信一干人等,通报我的行程。到家的时候,摸着黑听到二猫一声大喊"爸爸"。然后结巴着跑出来了,说什么我
开灯我关灯啥的。我给她蓝莓酱,问"你要的是这个不?"这是她不要的。中午的时候,她因为只想
要一瓶,放弃了这个愿望。她说:"也挺好。"哈哈。我拿出草莓酱,二猫满床蹦。我告诉她,我记得,是逗她玩的。我要去工作室,要吃饭,要工作。二猫说"爸爸那我还想你呢"。我威胁,你要是不睡我就更得走了。二猫哭着说了几遍,才说清楚:"你要是走
了,我就更睡不着了。"抽空上网看邮件,包师弟此前电话告急的事,原计划此时回电,他已经解决了。
恩,他正占线,短信"不电话你了。"我因为女儿而成为父亲,因为学生而成为老师,因师弟而成为师兄。我们,因为
他人的存在和需要而具有存在的价值。谢谢你们,谢谢你们需要我。从什么时候起二猫突然跟我这么亲近了呢?二猫妈说,从我给二猫上视唱练耳课
开始。其实二猫现在还远不知道,她的爸爸五音不全,自己也唱不准音,更不用说听音
了。就像,我的学生,有的仍然不知道,我们之所以艰难度日,是因为作为老师
的我没有足够的能力--带来项目的能力,理论上的深刻,或者创造性的想法。我不过是你们年少时的玩伴,就像幼儿园、小学、初中、高中,陪伴过你们的那
些老师。当年,你是多么地崇拜他信任他,直到有一天你发现自己比他长得还
高,更有远见,能力更强。其实,一切都没有变化。我一直是你们年少时的玩伴,而不是能伴随你们一生的
师长。那些希望...只是少年眼中的光环。还好,我陪伴你们度过这样的少年时光。所以,谢谢你们需要过我,在此时。

令人讨厌的字句

令人讨厌的字句0. 哎哟威1. 梁老师,《海洋》一开头还是有点可怕的好吗..突然一片水涌上来的感觉句式:XXX,好吧。例句:这种情况都是这么处理的,好吧。2. 小郁闷,小得意,小一千句式:小XX例句:一个月下来,我怎么着也能弄个小一千。3. 林夕,句句倾城的男人句式:XX样的男人例句:科比,神一样的男人4. 草泥玛,尼玛5. 当下6. 举措7. 分享8. 好可爱句式: 好XX例句:这朵花真是好好看啊。9. 我讨厌的东西还是少,凑不到10个了,就此打住。 以后再补充。

标 题: C语言中史上最愚蠢的Bug(zz) 转载

发信人: josephpei (Nikon,感动常在), 信区: CProgramming
标 题: C语言中史上最愚蠢的Bug(zz)
发信站: 水木社区 (Fri Aug 26 15:59:46 2011), 站内http://coolshell.cn/articles/5388.html本文来自"The most stupid C bug
ever",很有意思,分享给大家。我相信这样的bug,就算你是高手你也会犯的。你来看看作者犯的这个Bug吧。。首先,作者想用一段程序来创建一个文件,如果有文件名的话,就创建真正的文件,如果没有的话,就调用?tmpfile()?创建临时文件。他这段程序就是HTTP下载的C程序。code==200就是HTTP的返回码。else if (code == 200) { // Downloading whole file
/* Write new file (plus allow reading once we finish) */
g = fname ? fopen(fname, "w+") : tmpfile();
}但是这个程序,只能在Unix/Linux下工作,因为 Microsoft 的?tmpfile()的实现?居然选择了 C:
作为临时文件的存放目录,这对于那些没有管理员权限的人来说就出大问题了,在Windows
7下,就算你有管理员权限也会有问题。所以,上面的程序在Windows平台下需要用不同的方式来处理,不能直接使用Windows的tmpfile()函数。于是作者就先把这个问题记下来,在注释中写下了FIXME:else if (code == 200) { // Downloading whole file
/* Write new file (plus allow reading once we finish) */ // FIXME Win32 native version fails here because
// Microsoft's version of tmpfile() creates the file in C:
g = fname ? fopen(fname, "w+") : tmpfile();
}然后,作者觉得需要写一个跨平台的编译:FILE * tmpfile ( void ) {
#ifndef _WIN32
return tmpfile();
#else
//code for Windows;

七种武器:怀念键盘

七种武器:怀念键盘用计算机的人,把工具视为武器。所以,我们有很多武器。有些,是花哨而炫目
的,有些是沉重得没有声音的。键盘,是一种武器。老家伙的武器。时代发展,老家伙们不断地落后于时代,看这个也不惯,那个也不惯。最后,就
变成了一群被时代淘汰的人。我也会是其中之一。典典同学不知道从哪拍了张mazhazi的照片,放在人人网上,叫嚣着让大家认那
是啥。mazhazi是一种类似于蚱蜢的昆虫,就是"只恐双溪舴艋舟载不动许多愁"的那个。
mazhazi和蚱蜢之间的区别我就不说了,这不是重点。重点是我答了那是mazhazi
以后,典典同学说,"老头不许说话。"恩,你,还有你,你们也有一天会变成老头的啊。老头们会认为最佳的输入工具是键盘,而不是鼠标。我们大部分时间手指都是放
在键盘的基本键位上,而不是鼠标上,那很累手。而且,我们认为手放在鼠标上
仅能获取信息,而放在键盘上是为了对这个世界发出我们的声音。当然,我们也没有那种键位错误――因为打CS太多,食指不是放在F上而放在D上。键盘曾经是最常用的输入工具,那个时候鼠标20元一个,我根本就买一起。所
以,学ORCAD,一种绘电路图和仿真的软件,整个课程,我都是用键盘对付下来
的。考试的时候也没鼠标。键盘定位,真是比鼠标准确多了。我所怀念的键盘,最初的一个,很寒碜。每当同学们抱怨这所学校或学院多么糟烂,机房开放时间怎么地的时候,我就讲
讲我当年3块钱2小时机票的事。你看,我老啦,老家伙又能说些什么。其实我没讲更早的故事。我的第一个键盘,是我手工做的。当然不能接在计算
机,那时机器都放在跟保温箱似的屋子里,难得有机会碰一下。我做的键盘是木
头板上,每个键位的上面粘着海绵,海绵的顶上粘着我从计算机课本上剪下来的
键盘字母。我为我的高中能提供计算机课程而感激至今。虽然,整学期我们只编了解一元二
次方程的那个程序,BASIC,苹果II。有人说,男人总会找到一个复杂的令他向
往的东西。当时我还不知道这句话,但是我想,这个就是我想要的东西了。现在,仍能感到当时的激动。机房那美妙的塑料味。我在这个键盘上练了最初的指法。同时用来练指法的,还有英语林老师的机械打
字机。所以,我现在仍然打字很重,能把IBM笔记本敲得跟机械键盘一样响。后来,我赖吧吧地想跟一位好友的男朋友学五笔来着,自己找来了字根表啥的。
但是人家不教,那个时候计算机很贵的。机时也很贵。唉呀,往事如烟哪。现在我中文打字估计能稳定在60―80左右吧,比思维和说话慢
不少,估计比我写字略快。英文打字大约每分钟正确击键200次左右。大哥同学,每分钟300,我认为他不是
人类,平均每秒钟5次。小数字键盘,我很少见到像我一样用规范指法的,除了银行的。中指在5上,0用
拇指,回车和加号用小指。小数字键盘是打一个游戏练的。那个游戏叫做 大时代的故事,讲北伐战争、抗日
战争前、抗日战争中后期的故事。你扮演一个军阀,打别人。用小数字键盘回答
问题,把兵带到某某省吗,骑兵对坦克冲锋吗,花钱在某省发动XX运动么?历史
上的牛人们,战斗力真的很牛,甚至一直打到缅甸。抓到的将军们可以招降,再
招降,再招降,或者杀了,日本鬼子只能杀,没有招降选择。记得是汉堂的游戏,打过关以后,小数字键盘很熟了。最上排的数字键盘,一直不熟,不能盲打,所以对各种笔记本的键盘很痛恨。后
来用EMACS,慢慢习惯了,一个一个数字熟悉起来。现在大部分能够盲打了,包
括它们的上档字符。讲C++还是JAVA课的时候,同学们跟我讨论过我用键盘的利弊。有人希望我用鼠
标操作,这样他们方便记住在哪里找到编译菜单啥的。我后来没有坚持按他们的
希望去做,一则我找那些菜单挺费劲的,没太记住,二则我一直不明白这也应该
算是传授的内容么,换个界面就找不到啦?三则,我其实那个时候就眼神不太
好,看清菜单是件困难的事。就像我用WORD也全屏,不是显摆或另类,而是我长
期用15英寸球面显示器,实在看不清那些按钮,屏幕上也没那么大地方。说到这里,我想起了用着大显示器,却只有巴掌大的地方是代码的孩子们。我真是老啦。最后一件跟我老了有关的键盘的故事。我痛恨加工过的那些键盘。国人制造商们
特有这个瘾,在键盘上加些没用的或者非常不常用的东西。比如待机按钮啦,关
闭按钮啦。他们在那里污染键盘布局空间不说,还特别容易在按光标移动键的时候按上。为
此,我砸碎一个,而且再也不用这种垃圾了。键盘,就像你身边那个最可靠的人。古龙小说里写着的,某坏BOSS被打了,床一
翻个就没影了。话说他的床下面24*7有个家伙在那里划着艘船等着。键盘就是这样,那些按键一直在那里。你可能已经忘了VC编译的快键盘是什么,
但是你的手指还记着。我们,有一些人,可以永远记着,有另一些或另一个人,一直守候。无论鼠标、
语音输入、脑电波,无论有什么样的变化,他就沉睡在那里,当你需要的时候,
给你确定的支持。你甚至不必看你的手指,就能知道他的动作。因为他从不改变。所以,我想说的武器不是键盘,而是可靠。--
Sincerely,
YANG Guifu
School of Computer Science and Information Technology
Northeast Normal University
Changchun, P.R.China
----
杨贵福
无不大工。