大头
Table_bottom

标签云
Table_bottom

分类
Table_bottom

日历
九月
日一二三四五六
303112345
6789101112
13141516171819
20212223242526
27282930123
Table_bottom

评论
Table_bottom

留言
Table_bottom

微博
Table_bottom

热门文章
Table_bottom

随机文章
Table_bottom

豆瓣上谁关注这里
Table_bottom

链接
Table_bottom

搜索栏
Table_bottom

RSS
RSS Link
Table_bottom

功能
Table_bottom

页面
Table_bottom

计数器
519978
Table_bottom

访客统计
Table_bottom

存档
Table_bottom

对方法和工具的依赖

o6z几年前好像就说CSDN软工版都是侃爷,光说不练只知道些理论没有实践经验。

我很惭愧。几年来也就是偶尔上去看看,处理一些违规帖。

确实,问一些很二,很无聊问题的人很多,同时,很二,很无聊的回答也很多。

有时挺让人看着生气。

譬如这个问题:何保证软件质量呢?一般都用什么方法或工具?

我的回答是:我也想知道有什么工具能保证牛奶的质量。

下面是一个我觉得很二的回答,而这个回答可能会得到这个帖子全部20分的一半以上,在那里往往是写字越多,得分越多:

好大的题目啊
质量问题现在越来越受关注
不同的人有不同的看法,不同的人有不同的作用
客户,系统设计人员,项目经理,开发工程师,QA人员,测试人员
PS:突然发现这几个角色我都扮演过,哈哈哈
总之把各个阶段的缺陷控制住就相当不容易了
个人觉得,需求理解和设计阶段是最重要的,此时引入的缺陷,在分析设计阶段被发现了还ok,真正到了后面就闹大了
慢慢总结,关于质量真的有很多话题可以说
说到工具和方法,缺陷跟踪工具,缺陷围堵方法,同级评审,技术评审,需求评审,总之评审是个很好的方法~~就是太花时间和精力
一家之言仅供参考
祝你成功

初学Perl之二

程序有问题,有关字符串匹配。会用index函数去查找字串,那就能找到正确的行。可是运行总是报错,看不懂报错信息。怀疑是语法错误,却不知道错在哪儿。不像C,编译就排查了语法错误。CSDN上乱翻贴,看到有人推荐一个工具Komodo(下载)。装了后打开我的程序源文件,看到一行波浪线,太好了,这里有问题:

  1. $_ =~ m!>(.*?)</a>;

可是什么问题呢?书上说模式匹配函数(m//)是这样用的:

  1. m/pattern/;

 还说m后的第一个字符是模式分隔符。在一个例子里用!做分隔,我没有正确理解,这是把缺省分隔符(/)换成其他的(!)。因此这样才对:

  1. $_ =~ m!>(.*?)</a>!;

 现在的程序可以跑,但是结果不对。问题还是在这一行。我要取出所需要的字串。哪里不对?应该怎么写?没人可问,继续琢磨。

初学Perl之一

开始学习Perl,起由是想做个小工具,用C也可以,一则不急,二则不忙,那就慢慢做。

先下载ActivePerl,5.10.0 Build 1004。CSDN上看人介绍又下了个perl-lint-mode,也不知道怎么用,先放着。再下载EditPlus做编辑器。

我的第一个perl程序问题是:global symbol requires explicit package name at xxx。

google这个报错信息,知道了问题所在。程序里用了use strict之后,就必须用our或者my声明变量。为什么呢?找到了这个介绍:Use Strict And Warnings。

程序很简单,我只是想试一下命令行参数。

  1. #!/usr/bin/perl
  2. #use strict;
  3. use warnings;
  4.  
  5. $NUM = @ARGV;
  6. print $NUM;
  7.  
  8. #open(TESTFIEL, "test.txt");
  9. while(<>)
  10. {
  11.         print;
  12. }
  13.  

代码之美 - 081104

《当你与世界的联系只有一个按钮时》,Arun Mehta讲的是给霍金教授设计写字和说话的软件。Mehta是一个印度人。

这一篇的翻译一般,也许是译者看原文看得很枯燥,译文让我读得也枯燥。

由于输入只能通过对一个按钮的点击,软件的设计煞费苦心。主要以树型结构为基础,用表实现预测,用缓存提高命中。

有兴趣的可以去这个讨论列表。

P535有一个错误,“在界面的右下方显示了两个数字(参见图30-2)”,应该是图30-1。可我查了英文版,也错为30-2了。

代码之美 - 081022

《漂亮的调试》,Andreas Zeller以ddd的一个bug为引,介绍了增量调试(Delta Debugging),主要思想类同二分,算法好理解,可是程序看不大明白。

程序如下。

  1. def dd(c_pass, c_fail, test):
  2.     """Return a triple (DELTA, C_PASS', C_FAIL') such that
  3.        - C_PASS subseteq C_PASS' subset C_FAIL' subseteq C_FAIL holds
  4.        - DELTA = C_FAIL' - C_PASS' is a minimal difference
  5.          between C_PASS' and C_FAIL' that is relevant with respect
  6.          to TEST."""
  7.  
  8.     n = 2 # Number of subsets
  9.  
  10.     while 1:
  11.         assert test(c_pass) == PASS # Invariant
  12.         assert test(c_fail) == FAIL # Invariant
  13.         assert n >= 2
  14.  
  15.         delta = listminus(c_fail, c_pass)
  16.  
  17.         if n > len(delta):
  18.             # No further minimizing
  19.             return (delta, c_pass, c_fail)
  20.  
  21.         deltas = split(delta, n)
  22.         assert len(deltas) == n
  23.  
  24.         offset = 0
  25.         j = 0
  26.         while j < n:
  27.             i = (j + offset) % n
  28.             next_c_pass = listunion(c_pass, deltas[i])
  29.             next_c_fail = listminus(c_fail, deltas[i])
  30.  
  31.             if test(next_c_fail) == FAIL and n == 2:
  32.                 c_fail = next_c_fail
  33.                 n = 2; offset = 0; break
  34.             elif test(next_c_fail) == PASS:
  35.                 c_pass = next_c_fail
  36.                 n = 2; offset = 0; break
  37.             elif test(next_c_pass) == FAIL:
  38.                 c_fail = next_c_pass
  39.                 n = 2; offset = 0; break
  40.             elif test(next_c_fail) == FAIL:
  41.                 c_fail = next_c_fail
  42.                 n = max(n - 1, 2); offset = i; break
  43.             elif test(next_c_pass) == PASS:
  44.                 c_pass = next_c_pass
  45.                 n = max(n - 1, 2); offset = i; break
  46.             else:
  47.                 j = j + 1
  48.  
  49.         if j >= n:
  50.             if n >= len(delta):
  51.                 return (delta, c_pass, c_fail)
  52.             else:
  53.                 n = min(len(delta), n * 2)
  54.  

1,第三行注释翻译成:“C_PASS是C_PASS'的子集,C_FAIL'是C_FAIL的子集”。想了一想,没错,函数是逐步缩小c_pass和c_fail之间的差异,在书中例子里,也是通常情况下,c_pass是空的,c_fail是“失败全集”。

2,在 j < n 这个循环里,n = 2, i = 0, 把全集分成两部分,如果第一个 if 成立,c_fail等于其中一部分,n = 2, offset = 0, break是否是跳出这一堆if-elif-else?跳出的话回到循环开始,j 没有机会改变,i 也就仍然等于0。我尝试着模拟几种情况,n等于2、4、8,似乎程序跑步到 else 里,j = j + 1 没有机会被执行,i 的值也就得不到改变。也许我对 test 函数的返回理解有误。摇头叹息看不懂看不懂。

作者说在这本书的O'Reilly网页上也有这段代码,于是去下载,下载的代码和书上的不大一样,算法是一致的,清楚多了,一看就明白。再回头看上面这一段,还是觉得不大对。作罢作罢。

文中还提到Continuout Testing。作者说他开了一门课,专门讲授科学方法和增量调试,课程幻灯片和参考文献在:http://www.whyprogramsfail.com/,可是我打不开这个网页。还有增量调试的主页:http://www.st.cs.uni-sb.de/dd/。

代码之美 - 081017

《代码如散文》。Yukihiro Matsumoto自然对Ruby大夸特夸。作者用简洁的一篇散文谈了谈漂亮代码的几个因素,简洁,保守,简单,灵活。

有两句话应该时时记住:

程序中不应该包含无用的信息。

不要重复代码,不要把相同的东西编写两次。

代码之美 - 081016

《优雅代码随硬件发展的演化》,因为题目的诱人,选择读这一章,开了头就发现上当。

磕磕巴巴把前面的问题描述读完,被示例程序14-1难倒了。且不说MATLAB的奇怪写法,LU因式分解我也没搞清楚,于是,这个30多行的程序,来来回回多少遍也看不明白。自然也就不明白作者说的这个代码如何地漂亮。

了解了一下LU因式分解,再去看程序,还是头晕。于是决定放弃看代码,包括后面的FORTRAN代码和C代码。

马马虎虎看完这一章的汉字,一知半解的,大约知道Jack Dongarra和Piotr Luszczek(他的主页上links提供了很多好看链接)在说漂亮的代码如何高效地利用存储器层次结构获得高性能。

代码之美 - 081008

《Linux内核驱动模型:协作的好处》这章篇幅不大,可读得费劲。

上来就有两句话没看懂:在2.4版本的内核中,每一个设备的物理部分都由一段总线特定的代码来控制。总线代码负责各种不同类型的任务,而每一种具体总线的代码之间则没有交互。

后一句的原文是:This bus code was responsible for a wide range of different tasks, and each individual bus code had no interaction with any other bus code.

这里,总线特定代码(bus-specific code)是什么意思?

然后,Greg Kroah-Hartman提出两个问题,1是在解决电源管理问题时,内核需要知道不同设备的连接关系;2是不论哪一台USB打印机先启动,两台打印机的名字永不变。

其他系统的一般解决方法,1是内核中放一个处理设备名的小数据库,2是通过文件系统中可以直接访问设备的devfs类型来导出设备的所有信息。

对Linux来说,内核里放数据库是不能接受的,同时,Linux的devfs文件系统实现中“存在一些众所周知的且难以消除的竞争条件,导致几乎所有的Linux发布的版本中都不能依赖它。”这句话怎么理解?

再然后,作者用一个“简单”的例子展现了,展现了什么呢,我觉得是展现了C语言的复杂用法。如作者所说:是的,非常强大,只要你清楚地知道你正在做什么。

不信就看看这个宏吧: 

  1. #define container_of(ptr, type, member)    ({    \
  2.     const typeof( ((type *)0) ->member ) * _mptr = (ptr);    \
  3.     (type *)( (char *)_mptr - offsetof(type, member) );})

作者通过介绍Linux内核中解决前面提到的两个问题所需的数据结构和支持函数的演变,来说明协作给Linux带来的好处,还好文末有个总结,否则我又要忘了他要说什么。

代码之美 - 081007

《漂亮的测试》这一章很容易阅读,Alberto Savoia介绍如何写测试用例,漂亮的。

他举例说明如何写漂亮的测试代码,这个过程又是如何使被测代码变得更好。其实,更加强调的是程序员本来就应该测试自己的代码。

有多少程序员像画家一样,常常放下笔,站远点,从不同角度,在不同光线下,审视自己的作品呢?

我很少编写程序去测试自己写的函数,我的同事也一样。我们更多依赖运行整个程序检查结果是否正确,依赖测试组的同事们。

作者介绍的是Java程序员常用的JUnit。

不要给自己找借口,只要想做,办法总是有的。

挑了几个错误,填写到这里。

代码之美 - 081003

收到了《代码之美》,把目录翻来翻去,在33章里找我最容易能看懂的,似乎并没有哪一章让我觉得可以顺畅阅读不用多加以思索的。

最后挑选了第24章《美丽的并发》,作者是Simon Peyton Jones,他用Haskell语言来介绍STM(Software transactional memory),看得我很头大。注意力几乎全被Haskell语言占据了,3、5行的程序段却费了不少脑筋去思量。以至于文章最后作者在总结的时候,我都没有感觉到他说的所有的好处到底在哪里。回头想想,似乎是那么回事,可一到细节,脑子里搅和的还是语言的细节。

反正我记住了,最大的好处是使并发程序的模块性更好。还避免了不少常犯的错误。

这一章里的代码有下载。

我还想知道,Haskell多用在什么地方?记录下Haskell的官方网站,那里可以找到很多信息,下载很多东西。

再记下这本书的英文版勘误信息。

 

说不清,写下来

很多时候,人们并不打算为其口头的表述承担责任。因为“说得轻巧”,往往就脱口而出。

事后如果出了问题,可能确实记不确切自己曾经是如何说的,也可能不承认的效益更大。

而人们对于必须写下来的东西,会慎重很多。其程度是纸笔写下 > email/电子文档 > 口头表述。

所以在承担责任的扯皮中我建议无论接受上级的任务指派,还是和其他同事关于工作内容的交流,使用email。

重要事宜,打印,签字。

如果同事不愿意回复email,只是口头传达。告诉他口头之外,再发一封email,以免你遗忘。发给他的询问email同时cc给你的上级和他的上级。

责任承担的扯皮

组织结构:

Z是内容部员工,B是技术部员工,A是B的上司,同时也是总管。就是说,A也是Z的上司。

事例:

一个特殊任务,A口头告诉Z可以使用免费代码,具体代码问B。

Z口头问B,B口头告知是F代码。

Z使用了F代码。

次日,发现出错了。

A追究是Z做错了,先声称自己从来没说过可以这样做。

Z回答B告知使用F代码。

A说B称从未说过。B事后称其说的是FX代码。

怎么办:

1)与B当面澄清,是否有曾去询问一事。有则是如何回答的。

2)以后,对于上司口头交代的任务,听完后说:“好,我知道了,请你再发一封email给我。”如果不愿意发email,就把接受到底任务写一封email发给上司,问他是这样吗。发出后电话或口头告知。

3)对于在和其他部门同事合作中,任何需要对方确认的事,务必使用email。记录下合作过程中每个人对自己的工作内容所做的判断和选择。

PHP初学——字符串

PHP的语法也实在是搞,表示字符串可以用双引号",也可以用单引号'。

和C一样也是用'\'转义,如果串里要显示'\',双引号得这样'\\';单引号,'\'就可以了。

既然'\'表转义,如果要表达单引号',在使用单引号的情况下,这样写:

  1. 'this string has a \' quote.'

就是说,在单引号内的'\'是转义字符还是'\'它自己,取决于它后面的内容。

这不是找麻烦嘛。

rgb to yuv

 

  1. void RGB2YUV(BYTE *in, BYTE *out, DWORD len)
  2. {
  3.         int r,g,b;
  4.         int y, cb,cr;
  5.         int i;
  6.         int data;
  7.  
  8.         for(i=0; i<len; i=i+4)
  9.         {
  10.                 r = *(in+2);
  11.                 g = *(in+1);
  12.                 b = *(in);
  13.  
  14.                 y= (0.257*r + 0.504*g + 0.098*b + 16);
  15.                 cb = -0.148*r - 0.291*g + 0.439*b + 128;
  16.                 cr = 0.439*r - 0.368*g - 0.071*b + 128;
  17.                 if(y <16)
  18.                 {
  19.                         y = 16;
  20.                 }
  21.                 else if(y>235)
  22.                 {
  23.                         y = 235;
  24.                 }
  25.  
  26.                 if(cb <16)
  27.                 {
  28.                         cb = 16;
  29.                 }
  30.                 else if(cb>240)
  31.                 {
  32.                         cb = 240;
  33.                 }
  34.  
  35.                 if(cr <16)
  36.                 {
  37.                         cr = 16;
  38.                 }
  39.                 else if(cr>240)
  40.                 {
  41.                         cr = 240;
  42.                 }
  43.                 *(DWORD *)out = 0x7f000000 + ((DWORD)cr<<16) + ((DWORD)cb<<8) + (DWORD)y;
  44.  
  45.                 in += 4;
  46.                 out += 4;
  47.         }
  48. }

 

Windows 98 源代码

 

  1. /*
  2. 微软最高机密——Windows 98 源代码
  3. 项目:Chicago(tm)
  4. 项目发行日期:1998年夏天
  5. */
  6.  
  7. #include "win31.h"
  8. #include "win95.h"
  9. #include "evenmore.h"
  10. #include "oldstuff.h"
  11. #include "billrulz.h"
  12. #define INSTALL = HARD
  13.  
  14. char make_prog_look_big[1600000]; /*使程序看起来很大*/
  15.  
  16. void main()
  17. {
  18.  while(!CRASHED) {  /*如果不崩溃*/
  19.   display_copyright_message();  /*显示版权信息*/
  20.   display_bill_rules_message();  /*显示比尔的规则的信息*/
  21.   do_nothing_loop();        /*进行空循环*/
  22.   if (first_time_installation) {  /*如果是第一次安装*/
  23.    make_50_megabyte_swapfile();   /*创建50M的交换文件*/
  24.    do_nothing_loop();        /*进行空循环*/
  25.    totally_screw_up_HPFS_file_system(); /*将HPFS文件系统完全搞乱*/
  26.    search_and_destroy_the_rest_of_OS/2(); /*搜寻并删除OS/2的所有残余信息*/
  27.    hang_system();  /*挂起系统*/
  28.    }
  29.   write_something(anything); /*随便写一些信息*/
  30.   display_copyright_message(); /*显示版权信息*/
  31.   do_nothing_loop();  /*进行空循环*/
  32.   do_some_stuff();
  33.   if (still_not_crashed) {  /*如果还没崩溃*/
  34.    display_copyright_message(); /*显示版权信息*/
  35.    do_nothing_loop();    /*进行空循环*/
  36.    basically_run_windows_3.1(); /*基本上运行Windows 3.1*/
  37.    do_nothing_loop();  /*进行空循环*/
  38.    do_nothing_loop();  /*进行空循环*/
  39.    }
  40.   }
  41.  
  42.  if (detect_cache()) /*如果检测到缓存*/
  43.   disable_cache();  /*使缓存失效*/
  44.  
  45.  if (fast_cpu()) {  /*如果CPU很快*/
  46.   set_wait_states(lots); /*设置等待状态*/
  47.   set_mouse(speed, very_slow); /*设置鼠标(速度很慢)*/
  48.   set_mouse(action, jumpy);  /*设置鼠标(动作跳跃)*/
  49.   set_mouse(reaction, sometimes); /*设置鼠标(有时反应)*/
  50.   }
  51.  
  52. /* printf("Welcome to Windows 3.11"); */
  53. /* printf("Welcome to Windows 95"); */
  54.  
  55.  printf("Welcome to Windows 98"); /*输出“欢迎使用Windows 98”*/
  56.  
  57.  if (system_ok()) /*如果系统正常*/
  58.   crash(to_dos_prompt); /*崩溃(到DOS提示符)*/
  59.  else
  60.   system_memory = open("a:\swp0001.swp", O_CREATE);
  61.   /*否则打开a:\swp0001.swp作为系统内存*/
  62.  
  63.  while(something) {
  64.   sleep(5);   /*睡眠5秒钟*/
  65.   get_user_input(); /*接收用户输入*/
  66.   sleep(5);   /*睡眠5秒钟*/
  67.   act_on_user_input(); /*对用户输入起反应*/
  68.   sleep(5);   /*睡眠5秒钟*/
  69.   }
  70.  
  71.  create_general_protection_fault(); /*产生一般保护错误*/
  72.  blue_screnn(); /*蓝屏*/
  73. }
  74.  

 

补充编译警告

在实际的工程中,往往会出现callback函数的参数类型,定义和实际使用的并不一致。要注意强制类型转换。

在某个 struct 定义中使用了 union,而此 union 中定义了两个结构,第一个结构包含5个 UINT8 类型的成员,第二个结构包含1个指针类型成员,1个 UINT16 类型成员,1个 UINT8 类型成员。工程中两个结构都会使用到,而编译器无法知道程序使用的是 union 中的哪一个成员,默认为第一个。由此产生类型不匹配的编译警告,这里有产生错误的隐患。

一些资源

http://digilander.libero.it/robang/rubrica/serial.htm  --  Serial Programming Guide for POSIX Operating Systems

http://www.embed.com.cn/bbs/index.asp  --  嵌入开发网

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html  --  ANSI C Yacc grammar

http://www.51eda.com/bbs/index.asp  --  中国EDA技术网

http://bbs.driverdevelop.com/columns.php?action=columns  --  驱动开发网

http://www.linuxpilot.net.cn/  --  Linux Pilot

http://www.linuxworld.com/  --  linux world

http://www.linuxjournal.com/  --  linux journal

http://www.salon.com/tech/special/opensource/  --  the free software story

http://www.gentoo.org/  --  gentoo linux

http://www.linuxfocus.org/  --  linux focus

http://www.debian.org/intl/zh/mailing_lists  --  Debian 中文计划邮件列表

http://www.debian.org/MailingLists/  --  debian Mailing Lists

http://www.sgi.com/tech/stl/  --  Standard Template Library Programmer's Guide

 

一些资源

方便自己经常看看。

http://home.lzu.edu.cn/cjj/  --  一个C/C++学习小站

http://www.qaforums.com/  --  sqaforums

http://www.testage.net/html/index.html  --  测试时代

http://www.soft.com/  --  software research

http://www.sqe.com/stareast/  --  software testing

http://student.zjzk.cn/course_ware/data_structure/web/main.htm  --  数据结构

http://blog.csdn.net/jinhao  --  C++

http://blog.csdn.net/gigix  --  透明

http://blog.csdn.net/kathywp  --  DirectX

http://fanqiang.chinaunix.net/  --  永远的UNIX

http://www.iu.hio.no/~mark/unix/unix_toc.html  --  The unix programming environment

http://www.chinalinuxpub.com/  --  linux php mysql

http://cvsbook.red-bean.com/cvsbook.html  --  Open Source Development with CVS, 3rd Edition

http://www.gnu.org/software/libc/manual/  --  The GNU C Library

http://www.menuetos.net/  --  Menuet OS
 

编译警告

一个项目,编译出近千条warning。

大部分大部分大部分是下面这四条导致的。

      1)局部变量定义后使用前没有初始化。
      2)函数体在调用处后,调用前没有声明。
      3)类型转换。
      4)比较运算符两边变量的类型不同。

 

计划啥?

有人问:“在做测试计划时,如何估计软件的缺陷数量?”
这实在是一个很二的问题。
做计划的时候干吗要去估计Bug有多少?
有人回帖说:“作测试计划的时候,是应该估计一下该软件的BUG数量,BUG集中点,以及修改该BUG的难度与时间,如果这些不估计,那编写测试用例的时候无法对某些重要模块作出着重测试”。
神了,做测试计划的时候都能估计出修改Bug的难度和时间了,也别计划了,赶紧解Bug去吧。