CS巴别塔(1)

为什么开会时需要严防“抢占道德制高点”

Posted in Uncategorized by Kenny Yuan on 2009/06/20

(码字太多无人看,我尽可能简短。不过,140字是没戏)

向熟识的人推广《罗伯特议事规则》有6年多了,但是每每还是会为《规则》中精妙的设计和对人性的洞察而击节。比如这一条:若要提出一个可议之题,必须清晰明确地表述出具体要做什么,而不是一个虚无的大方向(此为转述,非原文)

为什么要有这样的限制?难道说类似《关于加强精神文明建设的提议》这样的,就不能提了么?

这条原则,其实还是在防范人类共有的邪恶本性——不管要做的事情是善还是恶,人们都喜欢找出一个冠冕堂皇的理由,打出一个光明正义的旗号——不论古今中外基本皆是如此。这条议事原则所要防范的就是“先以大义之名取得投票通过,然后再以通过的议案来作恶”的行为。比如:假设议案题为《限制美国的儿童色情传播,保护青少年》,这样具有伟光正风格的议案是很容易通过的,对其后果表示担心的人也容易受得道德上的诘问;但如果议案书写为《为限制美国的儿童色情传播,要求在每台电脑上强制安装过滤和监视软件》,那么,它的真面目就很容易被人识破了。

再比如:《关于加强美国的国家财力的议案》 vs 《为加强美国的国家财力,个税税率增加50%的议案》
又比如:《关于增强美国的国家稳定的议案》 vs 《为了增强美国的国家稳定,授权政府出动军队和油箱驱散抗议人群的议案》
还比如:《关于防止美国的家庭暴力的议案》 vs 《为了防止美国的家庭暴力,强制每户居民在室内安装摄像头的议案》

再再比如:《关于建设美国的和谐社会的议案》 vs 《为了增强美国的社会合谐,授权政府实施新闻审查制度的议案》
又又比如:《关于促进美国的保密建设的议案》vs 《为了促进美国的保密建设,授权政府审查所有公民的通信内容以便过滤涉密内容的议案》
……
我不写什么结论了,大家抬一下头,再看一眼上方的那个粗黑的大标题吧。

Qt的Unit Test Framework简介

Posted in Uncategorized by Kenny Yuan on 2009/06/18

在国内的编程界,QT常常是不入程序员的法眼的,但平时能够听到的批评却有很多——大部分是对着MOC的。 其实QT有许多的好东西,比如在内部使用BSP管理数百万级别绘图对象的Graphics View Framework (这里说的BSP就是游戏编程中用的那个BSP)。除管理海量对象、3维变形、动画管理等功能之外,Graphics View Framework还能基于OpenGL渲染,而不用编写任何gl-开头的函数。

本文要介绍的是QT中的轻量级Unit Test Framework。既然要介绍的是代码框架,我就少喷方块字,直接先上一碟appetizer先:

代码

sample.cpp的内容:

01  #include <QtTest/QtTest>

02  class My1stUT : public QObject
03  {
04      Q_OBJECT

05  private slots:
06      void initTestCase()
07      {
08      }

09      void cleanupTestCase()
10      {
11      }

12      void testAdd()
13      {
14          QVERIFY(1 + 1 == 2);

15          QBENCHMARK
16          {
17              QString (100 * 1024 * 1024, '6');
18              QString (100 * 1024 * 1024, '4');
19          }
20      }
21  };

22  QTEST_MAIN(My1stUT)
23  #include "sample.moc"

上 面的代码构成了一个完整的单元测试。其中,slots是一个扩展关键字,Q_OBJECT用来声明一些专有的macro,#include用来包含头文件 和MOC的结果,QTEST_MAIN用来生成程序的主入口函数:main(int argc, char** argv)。

程序的主要 部分是三个member functions:initTestCase, cleanupTestCase和testAdd。其中,前两个名字是固定的,被测试系统默认调用的函数:initTestCase函数是第一个执行的测 试函数,用来为测试准备环境,如果没有需要,这个函数可以不写。cleanupTestCase的作用是在退出测试前清理资源,如果用不上,这个函数也可 以不写。

testAdd是实际的用户编写的测试函数,可以写任意多个函数,每个函数的名字也可以任意取(不一定要以test-开头)。这 些函数都会被当成测试用例,在最终生成的可执行程序中运行。与某些C++的测试框架不同,在这里我们不需要去任何地方注册这些测试用例。另外,这些函数的 名字可以在命令行中作为参数,用来手工指定运行哪一个测试。

testAdd中的程序行就是要编写的单元测试了,可以使用QCOMPARE和QVERIFY进行测试断言,还可以用QBENCHMARK测试性能。

编译

编译的过程也很简单,新建一个文件夹,比如名叫test,将sample文件放入,然后运行
1. qmake -project “QT += testlib”
2. qmake
3. make
即可得到可执行程序test.exe(此程序的名字取决于文件夹的名字)

运行

在命令行敲入test.exe -silent,得到如下结果:

Testing My1stUT

RESULT : My1stUT::testAdd():
1,141 msec per iteration (total: 1141, iterations: 1)
Totals: 3 passed, 0 failed, 0 skipped

大功告成!最后介绍一下test.exe的参数(这些参数都是QTEST_MAIN这个macro自动生成的,不用手工编写任何代码)

Usage: test.exe [options] [testfunction[:testdata]]…
By default, all testfunctions will be run.

options:
-functions : Returns a list of current testfunctions
-xml       : Outputs results as XML document
-lightxml  : Outputs results as stream of XML tags
-o filename: Writes all output into a file
-silent    : Only outputs warnings and failures
-v1        : Print enter messages for each testfunction
-v2        : Also print out each QVERIFY/QCOMPARE/QTEST
-vs        : Print every signal emitted
-eventdelay ms    : Set default delay for mouse and keyboard simulation to ms milliseconds
-keydelay ms      : Set default delay for keyboard simulation to ms milliseconds
-mousedelay ms    : Set default delay for mouse simulation to ms milliseconds
-keyevent-verbose : Turn on verbose messages for keyboard simulation
-maxwarnings n    : Sets the maximum amount of messages to output.
0 means unlimited, default: 2000

Benchmark related options:
-tickcounter    : Use CPU tick counters to time benchmarks
-eventcounter   : Counts events received during benchmarks
-minimumvalue n : Sets the minimum acceptable measurement value
-iterations  n  : Sets the number of accumulation iterations.
-median  n      : Sets the number of median iterations.
-vb             : Print out verbose benchmarking information.

-help      : This help

附录

没有提及的其它主要特性
1、在命令行给出测试数据
2、编程方式提供的GUI键鼠事件测试(非屏幕录制方式)
3、线程安全:框架产生的错误消息是线程安全的

最后还要说一句:QT的正确读法是cute,不要读成queue-tee

Tagged with:

Software Naming Fail

Posted in FAIL by Kenny Yuan on 2009/06/11
Software Naming Fail

Software Naming Fail

绅士和码农

Posted in Uncategorized by Kenny Yuan on 2009/06/07
虽然黑猩猩是人类最近的近亲,但是狗才是最能察觉和理解人类情感的动物

虽然黑猩猩是人类最近的近亲,但是狗才是最能察觉和理解人类情感的动物

话说打猎这回事儿,放在几百年前的英国,那可是无比地风光,并且无比地简单。

为什么说简单呢?难道猎人不需要学习许多技巧么?难道打猎过程中的寻找猎物、发现猎物、跟踪猎物,最终杀死猎物,这些事都没有难度么?嗯,如果猎人是独自出行的话,那么所有的这些事情肯定需要DIY了,而且肯定很艰难很劳累。所幸英国猎人都是绅士,绅士都是不自己动手的。绅士们都养猎犬(Hounds)——猎犬不是普通的狗。猎犬是独擅专精的狗,是有大局观念的狗,是有团队协作精神的狗。

让我们来考察一下在打猎过程中,猎犬是如何工作的。

要打猎当然要寻找到猎物。嗅猎犬(Scent Hounds)、指向犬(Pointers)和蹲猎犬(Setters)就是专门来找猎物的。嗅猎犬是用来追踪像鹿和狼一类的猎物的味道的,其中最厉害的寻血犬可以追踪十几天以前的猎物的味道。巴吉度就是一种出名的嗅猎犬(休闲品牌的老祖宗“暇步士”的商标就是一只巴吉度)。指向犬一般用来猎捕飞鸟,它在找到猎物时会笔直地站立,并将鼻子指向猎物的方向,一动不动地等着猎手前来查看;蹲猎犬在找到猎物后会蹲下不动并保持安静,等待猎人的进一步指示。蹲猎犬是用来寻找鹌鹑和野鸡之类的猎物的,所以蹲下不动是合理的。

找到猎物之后,根据猎物种类的不同,有不同的处理方式。如果发现了鹿和狼之类的猎物,狩望猎犬(Sighthounds)就要上场了。狩望猎犬根据狩猎目标的不同分为猎鹿犬、猎狼犬和猎野免犬等。著名的灰猎犬(Greyhounds,灵缇)就是狩望猎犬。一般来说,狩望猎犬有着符合空气动力学的尖尖的嘴,小小的耳朵,短短的毛和细长的腿,以及发达的胸腔(心肺功能强健),它们的血红蛋白数量也很高。所有的这些都是为了能够敏捷而长久地奔跑。狩望猎犬能够紧追猎物不放,耗尽猎物的体力,并在追逐的过程中咬伤和杀死猎物。狩望猎犬就是一般人概念中的那种“追着受伤的小鹿不放”的猎犬。如果发现的是鹌鹑和野鸡之类的猎物,蹲猎犬可以进一步接受指令,将猎物激飞(Flush),从而给猎人举枪瞄准的机会。激飞猎犬也能做到追踪和激飞这两件事,属于竞争上岗者。

在杀死猎物后,狩望猎犬和蹲猎犬的任务就结束了。这时候需要寻回猎犬(Retrievers)上场了。寻回猎犬中有两种很出名的猎犬,金毛寻回犬和拉布拉多寻回犬。寻回猎犬的作用很简单:将死去的猎物衔回到猎手身边(有意思的地,很多寻回犬的饲养者却并不知道)。金毛寻回猎犬是用来在陆地上寻回的,拉布拉多是用来寻回水中的猎物的(比如野鸭子,一般中弹后都是掉在水里的)。寻回猎犬需要有足够强壮的身体,并且对人友善。在打猎的过程中寻回猎犬需要安静,在寻回的过程中不能咬坏猎物(的皮毛)。这些特点使得它们在无猎可打的今天变成了绝佳的宠物犬。在美国AKC注册的犬只名单中,十几年来,一直都是拉布拉多排第一,金毛排第二。

有些猎物生活在洞穴中,比如狐狸、兔子和獾。众所周知,对付不寻常的敌人需要不寻常的手段。梗犬(Terriers)就是用来对付穴居的动物的,它能够封堵、活捉或者杀死穴居的猎物。因为需要和泥士打交道,一般梗犬都需要有短而硬的毛。实际上,梗犬的名字就是拉丁文的“泥士”(Terra)。著名的达克斯猎犬(Hachshund,又名腊肠犬)就是专门用来猎獾的。短小的四肢让达克斯猎犬能够钻入到洞穴中将獾赶出或者杀死。另外说一句,獾是一种凶猛的动物。能够杀死獾,说明了腊肠犬的凶猛。所以不要指望作为宠物饲养的腊肠犬的脾气能好到哪里去。

打猎的绅士们很幸运,因为他们有猎犬作为帮手,自己基本不需要动手,或者只需要扣扳机而已;写程序找臭虫的程序员们很不幸,因为他们所有的事情都需要亲历亲为,“一切全靠自己的双手”。

这就是绅士和码农的区别。