All Stories

rdoc流程

  今天听同事讲了rdoc的处理流程,他完全是通过阅读rdoc的源代码来理解的,而且似乎他根本没有多少编译原理的基础的,汗!  总的说来,通过他的讲解,我了解到,rdoc的处理流程基本也是分为词法分析和语法分析阶段。首先,应该说有一个词法分析器生成器,叫SLex,然后由RubyLex提供规则,其实是一组正则表达式,SLex可以说是有一个正则表达式引擎,根据这些规则,生成token,提供给RubyParser使用,基本上是lex/flex做的事情。然后RubyParser根据这些token解析出class和model,建立起相关的实例,解析出相关的注释信息,通过yaml写到文件中。这里有点虎头蛇尾了,不过大体上也能表达清楚想要的意思了。  比较佩服的就是同事仅凭这些ruby源代码,就看到流程来,我怀疑要我上的话,如果没有这些编译原理的知识作铺垫,应该达不到他这样的程度吧!

SVNLabel

  今天把CruiseControl上的label改成svn的revision号了,在公司发现个问题,有一个项目里总是不能正确取到svn的revision号,虽然构建了,但从web上看不到结果,没有日志,晕!回到家,也改了一下,又发现另外一个限制,其实这个可能要算是svn的限制,当时我把源代码从vss迁移到svn时,所有项目都是放在一个目录下的,所以现在svn里各个项目的源代码commit后revision号是累加的,并不是各个项目独立的,于是在CruiseControl上显示的就是几个项目用了相同的revision号了,晕!不过第二个问题应该影响不大,因为照我现在的应用场景,一个时刻只会对某个项目的源代码修改,只要CruiseControl是一直开着的,出现这种冲突的机会也不多。

穿越东西涌

  这次是从西涌到东涌这样的路线。以前听很多人说过,就是自己没去过,这次可是切身体会了一把。  本来自己的负重差不多,不会让自己太累到,结果出发前有2个mm把一些水和水果放到我包里了,结果真的重了好多。  今天才知道,原来东涌和西涌也就是两处海滩游泳场,穿越就是沿着海岸线从一端走到另一端。  沿着海岸线很不好走,大半的是礁石,剩下小半的路程是在山上爬,真的是爬哦,我还带了跟登山杖去,没用上,太难走了。中途一mm要虚脱了,于是我发扬不怕苦不怕累乐于肋于舍已为人的国际共产主义绅士风度骑士精神,帮忙背上她的包,果然又重了很多!  非常不幸的是,在从一高处跳到低处时,左脚踩到一块不平的石头上,于是扭伤了。不幸中的大幸是,已经离终点并不远了,咬咬牙总算也坚持下来了。  拍了一些照片,总的说来,海景很不错,怪不得总会有拍婚纱照的要去海边,今天就碰到两对,呵呵。

软件工程大会

  今天上午去听了软件工程大会的几个议题,发现挺没意思的,没有多少收获。大部分都是炒冷饭,没有激情,没有让人耳目一新的感觉。全是敏捷来敏捷去,持续集成来持续集成去,TDD来TDD去的。  于是下午就没去了,写了几行代码,把log4cxx加到工程中了,用xml格式的配置文件,看起来比较统一,所有的配置文件都是用xml的,哈哈,不过我的配置文件也太多了点。发现还是不能直接在代码中用unicode,编译时没问题,但是链接不通过,不知道什么原因,难道是哪里设置的问题。不过中文倒是可以了,在家里编译的不行,输出全是乱码,而且同事也一直说是乱码,不知道是编译的时候用的操作系统影响的,还是编译器影响的。

感觉像是一种耻辱

  不分还好,一分就郁闷了,感觉像是一种耻辱。

软件可测试性设计

  可测试性设计,即所谓的DFT,今天又一次重重地感觉了一次它的重要性。  系统中有一个权限管理模块,同一个物理用户可以不同的逻辑角色登录系统,系统中以各个逻辑角色为最小管理单元进行权限管理。一般情况下,用户可选择的逻辑角色范围是极有限的,绝大多数用户应该有只一个逻辑角色,当然在测试情况下,情况刚好反过了,基本上每个物理用户会有几个逻辑角色,容易暴露出问题。主要集中在,角色拥有的权限不正常,比如看到了不该看的,看不到该看的,可以做不该做的,做不到该做的。  一直以来,对这块的调试/测试都是很困扰我的问题,主要就是DFT没做好。最开始,把所有业务逻辑和界面绑定在一起,差不多每一条规则都要在界面上点来点去,构造很多与真实环境类似的数据去测试,非常麻烦,不容易遍历到各种情况。  后来将这模块重构了,把业务逻辑和界面分离,用单元测试来保障逻辑的正确性。从DFT的角度讲,这种代码架构方式,就是一种改进,对DFT的改进。  有了单元测试,还不能保证程序能完全正确地运作,因为除了逻辑正确,还有可能其他地方出错,比如输入数据就有问题。在前些天他们测试的一个版本中,依然发现了一些权限相关的问题,让我觉得比较郁闷,因为我一直以为应该是万无一失了的。不过事实摆在眼前,也逃不掉,今天老老实实地在那里定位,不过开始的时候还是异常困难,因为测试场景的千奇百怪,我的开发环境下,有些场景很难模拟。  后来突然灵光一闪,我应该为了方便测试,多写一点代码,多加点功能,比如当前这个问题,我可以加一个特性,能在某种特定条件下,使我可以以任意角色登录系统。说干就干,果然很容易地定位到了测试发现的几个问题的原因。  今天的经历告诉我,在软件可测试性设计方面,有很多值得研究的东西的,天呐!

炒冷饭

  说话那天还在抱怨嵌入Python真辛苦,后来突然灵光一闪,马上解决了那个执行外部脚本文件的问题!既然现在已经能做到这一步了,接下来就应该考虑,能利用这个能力做些什么事呢?  总的说来,现在我已经有了嵌入4个不同风格各有千秋的脚本语言解释器的经验:Lua、TCL、Ruby、Python。以后如果有需求,我估计TCL是不会再使用了,总觉得它的语法太枯燥了点。剩下三者,对Lua和Ruby的了解稍微多一点点,但也还没达到能用来做独立应用的程度。相比之下,Ruby的那种怪异变态的语法,还是比较吸引人的,还有就是它带了那么多稀奇古怪的库,可以大大减少重复劳动,这比Lua来说,省事不少。但Lua的轻巧,却一直让我觉得是嵌入的最佳语言。实在让人难以取舍呀!  想了想,WIND就只用Lua嵌入了,因为这是一个相对比较追求性能的应用。而WallpaperHelper其实用什么似乎没多少影响,而且照现在的趋势,WallpaperHelper的体积已经不成为主要关心的问题了,功能才是最重要的。另外还想过要写打谱程序的,也要嵌入扩展。StoneBase的功能让人比较满意,但从写代码的角度看,它的架构不行,可扩展已经成了继续发展的必经之路了。但我还没想好,是用MFC,还是WTL,或者wxWidgets来写呢?

让SMTP支持中文

  项目里要有发送邮件的功能,想法非常简单,公司有个SMTP服务器,通过它直接就可以发送到notes中了。网上SMTP的源代码也是一堆一堆的,找了一个CodeProject上的,加上base64编解码也只有4个文件,接口非常简单,于是稍微改了一下,base64本来我就有,就只需要加入2个文件就可以了,附件也能正常发送,很是满意。不过上周五的时候突然发现,主题和内容中的所有中文都变成乱码了,有点气馁,随便又找了几个其他的代码,也是一样。  今天闲起无事,就想改一下。只知道在哪里看到过说要用base64,就能解决这个问题。尝试着先把主题编码了,发现收到后就是编码后的字符串了,这也是预料之中的。上公司的论坛发了个帖,没人回复。后来自己忍不住了,用Outlook Express写了个邮件,主题和内容都是中文,然后打开Wireshark,抓包,比较了一下CodeProject上那个代码发送的,看出区别了,原来也就是加上个charset="gb2312",再base64,就搞定啦!

嵌入Python真辛苦啊

  两年前,就嵌入过python,那时宿主程序是用C++Builder开发的,python还是2.4,没用第三方库,完全用python C API直接操作,而且当时要暴露的接口不多,才4个C函数,当然还是费了不少力气。嵌入python的目的是为了主程序可以实现外部脚本扩展,只有一个很简单的应用场景,点击一个菜单项,就执行一个py文件。首先是要让它能执行起来,python文档有很多C API,例程却极少,记得当时连接1个半月每天至少到后半夜2点才睡,最后累得上wc连掀马桶盖的力气都快没有了。而且很大的问题是,在家里自己的电脑上终于可以跑起来了,拿到公司的电脑上却不行,每天只能晚上回家调,白天再到公司测试,很郁闷,我已经忘了最后是怎么搞的,反正是最后发现在公司的电脑上缺少一个site.py文件,直到这一刻才发现,这是python官方发布包中的一个文件,当时是自己放了一个0字节的文件在那里搞定的。那次这么多精力的投入真是不值,做出东西来本来想得个满分的,结果只打了个C,而且当时指定了4名专家评审,结果只有2个专家发表了评论,另2个还没评论就走到下一环节,直接C了,唉!  今天又看到很久之前写的计算hash值用的小程序CryptTool,核心功能早已完成,就是计算字符串,或文件的hash值,包括多种算法,比如MD2、MD4、MD5、SHA1、SHA256等等等等。后来出于尝试的心理,想给程序加上外部脚本扩展的功能,准备支持Lua、Python、Ruby三种脚本,而且不自己写粘合代码了,而是采用SWIG自动生成。Lua和Ruby的支持很快就完成了,可是Python的却一直有问题,网上翻了不少代码,以前C++Builder中的那个代码也翻出来,都是有问题,那时就搁下来,今天又心血来潮地想弄一下。  最主要的困难还在于对Python缺少了解,但这并不能成为借口,Lua和Ruby不就好好地嘛!这里我用的方法是把外部脚本文件作为module,import进来,但是一直返回一个空指针。实在没办法,PyErr_Print打印的内容又是输出到控制台的,而我的是个标准的MFC写的GUI程序,所以只好另外建了个控制台的测试工程,幸好模块独立性较好,几个文件拷过去略作修改就可以了。通过控制台输出的出错信息才知道,原来是import时,还会连带着import一些python自己的库,于是把python的lib目录添加到sys.path里。另外,如果说import这外部脚本文件时,报找不到该名字的module,就把脚本文件所在的路径也添加到sys.path里。终于可以在import时,执行一遍该脚本了!不过还有另外一个问题解决不了,就是调用Py_Finalize崩溃!在网上找了一圈,也有一些老外遇到这个问题,不过要么就是没有下文,要么就是给出的解决方案不适合我这种情况。因为我是import来执行脚本的,当没有Py_Finalize,而同一进程内再import时,就不会再执行了,作为外部扩展,有一个办法是定义一个基本规范,脚本中一定要实现一个指定名字的方法,再由宿主程序来调用这个方法,但这太不友好了。其实如果能用PyRun_File之类的API来强制运行一个文件的话,也是可以达到目的的,但还是绕回原来的路上去了,我这里PyRun_File这类API死活不能正常执行一个脚本文件,天呐!  于是还剩下一个遗留问题,怎么能解决脚本每次都能执行的问题呢?嵌入Python真辛苦啊!