2010年8月9日星期一

Web与桌面的混合

AQP里一开始就讲Web与桌面的混合编程。回想一下最近做的几个项目,全都是这种模式。这样做的好处是充分利用了Web页面丰富的表现形式和桌面程序对本地资源的控制能力。

2010年7月15日星期四

Delphi 2010 使用UAC的问题


1. 不要引用XPMan单元。
2. 把Delphi 2010生成的资源文件中trustInfo节中的requestedExecutionLevel节点的level属性设置为requireAdministrator。
重新打开工具,编译;OK。

其实最好还是修改程序避免总是使用UAC。

2010年7月6日星期二

Love Explains It All

记着这些日子。

You say the words I need to hear
Dry my tears when I cry
You pull me close when I'm not near

You knows the colours of my mind
Every breath that I take
And still they say that love makes blind

And here I am 
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

I stay awake to watch you breath
So much I should have said
Somehow I tell you when you sleep
I love the silence when you're near
And i love knowing you
And every word you say i keep.

And here I am 
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

Time will pass
Time will change
Everything we know will turn to something else
Turn to something else

Time has shown
Us where to go
And still i wonder why you catch me when I fall
I guess love explains it all

Cause here I am
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

Here I am
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

Love explains it all
I guess love explains it all
Love explains it all 

2010年4月24日星期六

一个软件缺陷的来龙去脉


背景
P软件主要有两个模块C和M组成。前期发现C模块中的A组件存在问题,所以决定由另一项目组的一名开发发员W来改写A组件,暂称A'组件。
我负责修改P软件,以更换新的A'组件,同时修改若干其他问题。由于旧的A组件在M中所用的功能没有发现问题,所以我没有修改M模块。
我修改了C模块,采用新的A'组件,在未经严格测试的情况下,把P软件部署到了客户现场使用。

问题
由于A'组件未经严格测试,存在缺陷:采用A'组件生成的文件无法以普通方式打开。
而P软件通常并不以普通方式打开A'组件生成的文件,只是在C模块中采用A'生成文件,然后在M模块中通过A组件进行操作,转换为另一格式的文件。
但是在少数情况下,也需要以普通方式打开A'组件生成的文件。
很快,少数情况真的出现了,问题显露了,C模块生成的文件不能以普通方式打开。我确定了这一事实后,开始怀疑在M模块中是否能正确进行转换工作,因为P软件的C和M模块的采用的组件是不同的。
客户暴怒、技术支持愤慨,测试人员紧急测试一番,M模块工作正常,P软件工作正常。

反思
如果C和M模块的A组件被同时替换为A'组件,虽然问题不能避免,但出现问题时,不必考虑由于C和M模块中组件不一致会引起的可能性。
如果P软件经过严格测试,出现问题时,就不会考虑M模块功能是否正常,能确切知道缺陷影响的范围。
P软件对于未经严格测试的A'组件,有测试的义务,因为A'组件本身不是一个项目,只是一个开发人员写的组件。


2010年2月2日星期二

够酷够简的Sikuli


Sikuli真的够COOL,样子也真的够简陋,安装好了只有一个Editor,连个Help菜单也没有。不过这些都没关系,阻碍不了它的酷,也妨碍不了它今天0.9.7明天0.9.8的的版本更新速度。

正在开发的程序,界面主要由Flash组成,以前用的自动化测试工具还不能认出Flash中的控件,只好用取坐标的方式来编写自动化脚本了;这真是让Sikuli一显身手的地方。中午开始,把以前用AutoIt3编写的一段脚本,由Sikuli来完成,算是试用。

前两天只看到了Sikuli的四个函数:switchApp、wait、click和find。这四个函数已经够做一些事了。可是今天需要更多,于是看一下API吧,真是少得可怜,当然,毫无疑问这才叫足够简单。好了,既然是Python,import几个模块来用用,def几个函数试试,一切顺利,一小段GUI自动化测试脚本完成了。运行一下,跟之前脚本的功能一样,不过,Sikuli可是更聪明,它能知道需要的界面出来没有。

再看一下Sikuli Test API,哈哈,函数少到不到再少,只有assertExist和assertNotExist两个函数。可是测试不能只看存在不存在,如果能多几个OCR之类的函数,可能用处会更大吧。也许很快就会出现了。

2009年12月17日星期四

换位

毕业时找工作,几次面试的感觉很是不爽。
昨天换了位置,第一次面试别人,于是可以不再单方面的看待面试这一过程了。
应聘者如何表现出自己的技能,面试者如何给应聘者机会来展示自己,这确实需要仔细思考。

最近项目组比较缺人。没有准备的时候,被同事拉去面试一个应聘者,完全不了解任何情况,我跟同事前往洽谈室。路上简单向同事问了下基本要求,然后去人力资源那里拿了份简历看了看。应聘者简单自我介绍后,同事开始跟他谈一些他过去项目相关的问题,我借机把简历仔细看了一遍,接着他们的话题插了几句。最后,问了几个简单的技术问题。

其实我一直觉得面试应该是有一个提纲的,或者更死板一点儿,应该有若干预备问题的,这样的一个提纲,从不同方面来考察一个应聘者的表现。
从面试别人我才认识到介绍项目时对于自己在项目中的工作,以及遇到的重点和难点的解决过程的说明是非常重要的。

究竟需要从哪些方面来考察一个应聘者呢?
我想对于项目组的应用开发来说,从应聘者对软件开发流程的理解、对所用开发工具的熟悉程度、以及对基础概念的了解几方面看就可以了。

2009年12月14日星期一

Detach from Program

一个程序出问题了,我用Delphi附加到远程进程进行调试,下班的时候,我想把本地机器关掉,让远程的程序继续运行。无奈不知怎么脱离开调试的程序。

查看Delphi帮助,明明确确的看到了一条Detach from Program

Choose Run|Detach from Program to tell the debugger that you no longer want to debug a process. It is different from Program Reset in that Reset kills the process you're debugging. Detach from Program effectively ends the debug session on the current process, but it leaves the process running (the debugger no longer controls the process).

但是到菜单里一看,根本就没有Detach from Program这个菜单项嘛,帮助文件睁眼说瞎话?

求助于AQTime看看,结果看到FAQ里这样一条:

Q.: How do I detach from the process that I attached to earlier? 
A.: Currently, detaching is not supported. When attaching, AQtime instruments the process's binary code and these changes cannot be undone.

好嘛,What done cannot be undone。

2009年10月29日星期四

准命令行编译Flash

没用过Flash,但是项目中有Flash的工程,当然希望Flash的编译成为自动构建的一部分。
本来以为可以用Flex SDK来搞定的,但是构建人员没有搞出来,只好回归到jsfl先用这准命令行的方式吧。
还是先放代码

//demo.jsfl
var doc = fl.openDocument("file:///c:/demo.fla");
doc.exportSWF("file:///c:/demo.swf", true);
fl.quit(false);

再加个命令行
flash.exe demo.jsfl 

有些时候,简单解决问题就好。

Invalid floating point operation

诡异事件的出现,多数是由于对其了解不够多。
本来在C++中调用多次的dll,放到Delphi中调用,总是产生“”Invalid floating point operation”异常,很是诧异。
多方搜索,原来要关闭浮点异常。

先放一段Delphi帮助中的例子,恐怕有很多人忘了用完之后设置回去。
procedure NumericExample;
var
  Saved8087CW: Word;
begin
  Saved8087CW := Default8087CW;
  Set8087CW($133f); { Disable all fpu exceptions }
  ThirdPartyRoutine;
  Set8087CW(Saved8087CW);
end;

Delphi帮助中的关于Set8087CW的说明,被我重新编排了一下引用如下(三段话,顺序正好与原来相反)。
It is recommended that you disable all floating-point exceptions when using OpenGL to render 3D graphics. To do this, call Set8087CW(0x133f) in your main form� OnCreate event before calling any OpenGL functions.
This routine allows the programmer to have direct access to the CW. Be aware that using this routine to change the value of the 8087CW will change the behavior of the program� FP calculations. It is the programmer's responsibility to reset it.
The floating-point unit control word controls the precision of floating point calculations, the rounding mode, and whether certain floating-point operations trigger exceptions. See Intel's processor documentation for details.
 
再放一段搜索来的内容增加长度。
Tripping floating-point exceptions
Floating-point exceptions are, as you might expect by virtue of the name, rare. The ones that happen most commonly by mistake in my experience are the zero-divide and invalid operation exceptions. Zero divide tends to happen whenever you have an unchecked normalization operation, such as resetting a 2D or 3D vector to unit length — which works fine, until someone hands you a vector of length zero. Another example would be trying to normalize a portion of audio that was totally silent. When the zero-divide exception is masked, the FPU spits out a signed infinity instead, which sometimes works out in the end. For instance, if the expression is of the form |x/y| > n, then the infinity would give you the correct result.
Invalid operation exceptions are more serious and result from operations that don't have a graceful way to degrade, such as 0/0, the square root of -1, etc. These too often result from the lack of bounds checks. For instance, a common way to determine the angle between two vectors is through dot product, since the shortest angle between two vectors is acos(dot(v1 / |v1|, v2 / |v2|)). Unfortunately, the common way of normalizing vectors is to multiply by the reciprocal square root of the squared length (dot(v,v)), which can give you a not-quite-unit-length vector since the squaring operation discards half of the usual precision. This can then lead to taking the arccosine of a number slightly larger than 1. When such an operation occurs and invalid operation exceptions are masked, the FPU spits out a Not a Number (NaN) value and keeps going. You can also trip such an exception by trying to operate on NaNs, especially by loading garbage data that isn't a valid IEEE finite number.
In general, you don't want to be tripping floating-point exceptions, even if they are masked. The reason is that when the FPU hits one, the fast hardware can't handle it and punts to the microcode, which then takes about twenty times longer. This is especially bad with NaNs since any operation with a NaN produces another NaN, causing them to spread throughout your calculations (NaN disease) and slow down everything massively. You can even crash due to NaNs blowing past clamp expressions, since any comparison with a NaN is false and converting one to integer form results in integer indefinite (0x80000000). Despite the erroneous results, though, NaNs can appear sporadically in a large Win32 program without anyone knowing, and may go unnoticed in a code base for years.
Note that although exceptions are really slow and usually indicate mistakes, the results when the exceptions are masked are well-defined. It is possible, and sometimes reasonable, to actually depend on and test for specific results from masked exceptions. So it isn't valid to simply say "don't do that."

 

2009年10月26日星期一

八小时里的那点儿事儿

又开始一个新项目了,工期不会超过两个月,代码不过万把行。
每个项目都是所谓工期短,时间紧,公司领导很重视。结果就是造就了一堆没人用的小玩意儿。
每个产品后期都会随着一次次的产品评审改来改去,其实那最应该叫做需求评审。
每个领导都有自己的想法,会对产品提出改进意见,但是,如果一个领导需要为界面上的几个普通的元素亲自负责的话,那是不是应该先招聘几个设计师呢。
每次例会都是以这些问题很重要开始,以这些问题会后讨论结束。