All Stories

整理了一下思路

  今天又没动手,人越来越懒了啊!总是在想,既然功能基本正常,就不要去动它了。就像Martin Fowler在书中说的一样。感觉有心无力,唉,心中有那么一点畏惧和抵制。  不过后来花了点时间,在纸上乱画,针对自动联想功能,清理了一下设计思路。现在的实现真的是很C风格化,所有的代码都是揉合在一个类中,所以相关的功能都在这个类里实现。重构时,希望尽量向OO的方向靠拢,那些设计准则,也要尽量地遵守。  从现存的代码看,自动联想从表现上看,可以分为3类,分别是Auto Completion、Call Tips、Code Snippet。其中Auto Completion是通过已输入的几个字符,根据上下文环境,给出候选的可能匹配的完整token,Call Tips则是在当输入函数调用的实参时,以tooltip的形式给出函数原型以提示,而Code Snippet则是在用户触发了事先绑定的事件时,根据已输入的字符,或者也可称为命令符,自动以代码片段替换该代表命令的字符串。总之这3种特性都是为了减轻编码者记忆负担,减少键盘敲击次数,降低出错概率。  当前的实现是当打开一个文件时,或者截获到换行操作时,进行扫描,记录当前文件及其相关包含的变量和常量的定义,除了名称,还需要类型。这样在输入变量时,可以根据名称进行提示,输入方法时,根据类型可以从数据库是查询到相关方法。所以扫描是为了Auto Completion和Call Tips作准备,Code Snippet不需要这些。  当初实现这些特性时,只考虑到了Ruby语言,所以紧紧围绕着Ruby这个主题开展,代码几乎没留下任何一丝空间以供后续扩展。不过既然这次要重构,无论从设计角度,对象职责上看,或是以后要添加扩展新语言支持,都需要把这块代码剥离出来。一个重要的原则是,剥离出来部分不能再跟界面有耦合了,不然单元测试几乎不能做了。  界面部分还是全都放在控件类中,控件类调用Auto Completion、Call Tips实现类获取待显示的内容,实现类应该从统一从一个抽象类继承,每个实现类可以对应一种(或一类)语法。这里需要引入一个工厂类。原来的助手类应该拆分成两部分,即代码扫描分析部分和信息存储查询部分。其中代码扫描部分也有一个抽象基类,从它派生出对应各种语法的具体实现类,把扫描分析的结果存储到信息存储部分,同时,信息查询部分从信息存储部分获取内容,信息存储部分的数据一部分来自于扫描分析部分,另一部分来自于固有持久化层,可能是一个数据库,可能是一个文件文件,可能是一种外部输入数据结构。这样,任何一部分的变化,都会尽可能少地影响其他部分的实现,而且这些实现除了界面相关部分,其他的应该都比较容易做单元测试,自我感觉设计得不错,只是可能工作量大了不少,很容易让人产生放弃的念头,呵呵!

在VC9下面用CppUnit

  因为主工程是用VC9的,所以想用CppUnit的话,一般说来也是用VC9的。不过很郁闷的是,无论怎么弄,总是不正常,不是编译不过,就是运行就崩溃的,真是奇怪呀!  如果实在不行,就换用VC7.1来用CppUnit算了,毕竟照在公司里使用CppUnit的经验,在VC7.1下是好好的,可以有经典的红条,绿条,也可以直接输出测试报告到文件中,嗯,今天就先到这里,又费了一晚的时间!

不需要分发pdb啦

  话说我已经通过抠早期版本FileZilla的代码,能让程序在崩溃那一刻进行dump,但是却只是知道,dump时,如果有相应的pdb文件在搜索路径下,是可以直接得到详尽的信息的,如果当时没有pdb文件,就只能得到一些看似无用的东东。  其实我错了,大大地错了!也不怪中间各种各样的原因,关键是现在知道只要能保留下可执行文件相配套的pdb和源代码在本地就可以了。当初从别人那里拿来dump文件来分析,是因为搜索路径下的pdb和源代码都是跟那个可执行文件不匹配的!  我居然还想着通过什么策略把pdb分发出去,哈哈,太可爱太幼稚了!现在终于可以安心地发放可执行文件出去了,只是崩溃报告机制需要好好设计一下,如何能及时地把报告从用户处取回,考虑到公司的网络环境和使用政策,还是要费点劲的。  另外又引出一个新问题,配置管理怎么做?嗯嗯,越来越复杂哈!

CruiseControl应用实践

  自从知道CruiseControl之后,一直很喜欢这个东东。这回项目组里开始兴起XP、Agile、Refactoring这些东东,于是我就想着希望能尽可能地向书上、网上写的那样,把CI搞起来,现在这个CruiseControl只用来编译一个发布版本的,照他们的说法,不是持续集成,而是持续编译,而且这里连持续编译都算不上,因为不是自动定时轮循的,而是手工去点一下那个force build按钮。鉴于我一个人在做一个项目,中间也没人过问,极大的自由度,照负责人的说法,试验田。呵呵,这次我就把CppUnit和Code Metric集成了进来。  我首先弄的是Code Metric。工程是用VC++开发的,于是用了一个在公司内被推广的工具Source Monitor,开始时没有仔细看它的帮助文档,还冒冒然给作者发了封邮件,问他能不能提供一个命令行版本。作者还好,回了封邮件说,Source Monitor本来就是支持命令行的,可以通过写一个XML格式的命令文件,通过命令行进行相关的代码度量工作,简单试了试,果然可以,基本能满足要求。然后又看到Contrib目录下有几个XML文件,通过ANT来转换Source Monitor生成的XML文件,太好了,又学到一招简单易用的,通过几个xsl文件,把Source monitor生成的度量数据用html格式呈现出来,在CruiseControl中没找到合适的地方显示,就只好把这些svg、html文件都拷贝到artifacts目录下。  然后弄CppUnit。CppUnit其实是个好东西,好处不用多说,但坏处在于它是JUINT的Cpp port,所以某些第三方的支持就不如JUINT的好。比如ANT是直接支持JUINT的,CPPUNIT就不行。另外,CPPUNIT原生支持的XML导出测试报告并不兼容CruiseControl的输入。走了一小点弯路,在网上搜了一下,发现CPPUNIT有个Contrib下的xsl文件,可以把它的原生XML输出转换成JUINT的XML格式输出,于是乎,就可以被CruiseControl接受了,哈哈。便宜说一下,似乎正式发布的源代码包里是没有这个xsl的,但从1.11.0开始就已经有这个了,需要自己从CVS里找。

重构ReviewTools

  今天决定开始对代码审查辅助工具动手,结果发现这个代码写得太复杂了,彻底晕死!本来看起来似乎是个很简单的小程序,功能也算比较简单,就是能添加一些信息,把这些信息保存到一个文件,到需要时能从文件中读出这些信息,另外一个功能是能把信息输出到Excel文件中,或者以一定规则输出到Lotus Notes中。  结果发现,为了跟Excel和Lotus Notes交互,必然使用到了COM接口,然而奇怪的是,原来那个作者把对Excel和Lotus Notes的操作简单地用VBS封装了一遍,结果是另一种脚本COM组件的形式出现,再在MFC程序中调用这些脚本组件,实在是不必要。  其次,因为本程序设计的是能在Source Insight中激活并添加信息,所以需要Source Insight的扩展来支持,也许是Source Insight的宏能力比较弱,原作者就设计成在C盘根目录下放置一个很小的cmdline.exe,让宏直接把所有信息当作命令行参数传入给这个小程序,通过它来调用主程序,于是为了在不同进程间传递数据,便把这个主程序设计成了一个进程外组件了。唉,又是COM,烦死人了。我也要把它改成不用COM的,用Event、File Mapping、Metux、Command Line Parameter应该能解决这个问题。  再次,界面上有个TreeView,TreeView的Data域不知道绑了多少数据上去,晕死!关键是不要绑MSXML的COM接口指针上去啊!  最后,我要在这个基础上重构的话,工作量比重新做一个大概少不了多少了!

好久没有shopping了

  去东门逛了一下午,买了件比较板的衬衣,一条黑色的休闲裤,薄薄的,适合夏天穿,为了搭配这身衣裤,还特地买了条皮带,这样800大洋就花出去了。然后是一双休闲类的皮鞋,又是400多大洋。好久没有这样添置自己的行头了,也许真应该好好地改变一下自己的外观形象,明天穿着人模人样地去公司晃悠一下。  不过逛得好累哦!

失落啊

  中午疯丫头跟我说,明天她就去那边了。不免有点失落,以前测试组的同事一个一个地全都调走了。虽然早就知道她一直忙着调动的事情,忙着去那边面试,忙着跟这边的领导周旋,直到前不久,大概也是因为正好赶上了产品线整合以及部门整合,领导也变动,终于同意放她去marketing那边。今天还偶然看到她居然,有纹身,而且不是在很明显的部位,呵呵,还骗我说是贴纸贴上去的,太假啦!

昨天搞到2点

  昨天突然下决心要搞一下月历显示部分。惰性总是我的最大困扰之一。慢慢调试,发现其实要实现这个功能代码并不需要多少,大概不到100行吧,之前实在是高估了困难以至于一直懒得,也是怕的去动手做了。不过虽然代码量不大,到最后可以基本稳定地用也是花了不少时间去慢慢修改的。  今天去驾校上了理论课,由于晚上睡得晚,早上起得早,加上中午还没午觉睡,于是上课时间都被我用来睡觉了,都不知道讲了些什么。  回到家大概5点左右吧,还算早的,于是又写了一会儿代码,把农历也显示出来了,哈哈,虽然原来打算能让农历显示在右边或下边,可以灵活配置,今天实现的时候发现如果要显示在右边,似乎比较麻烦,还让它只能显示在下边吧,嘻嘻。  这样就可以使用那些大块留白的皮肤了,真是happy呀!  再把配置模块做一下,就基本可以拿出去让人用一下了,只是GDI+输出文字时,有时候会输出不是预期的效果,原因至今不明,还待以后慢慢定位。

其实log4cxx也不错

  简单看了看log4cxx的例子,上网找一下相差的资料,它自带的例子实在是太简单了,虽然知道它源自于log4j的移植,但到底它移植度有多少就不得而知了。从网上找到的资料看来,log4cxx对log4j的配置文件支持就很完备,直接在外面写一个配置文件,程序中只要添加一行装入配置文件的代码,然后所有的修改只要针对配置文件进行就可以了,不需要修改程序源代码,真是方便至极呀。  尝试了一下给WallpaperHelper加入日志功能,对于这样一个完全不需要追求运行性能的桌面应用程序来讲,加入日志功能似乎只有好处没有坏处,至少可以在程序出现问题的时候根据日志记录定位问题发现的现场状况。  偶然上apache的网站看了看,自从我从svn里check out出源代码来编译了一把log4cxx以后,某一天居然正式发布了0.10版本,气愤,于是只好再update一把,重新把各个VC版本的都编译一把,这个确实让我觉得有点烦,这类工作最好完全自动化,自动从svn里更新代码,自动调用ANT来编译,而且要能自动应用多种版本的VC来编译,然后分类打包好,唉!CruiseControl本来是做这种事情的好东西,不过我却没有完成利用起来!  在boost的news group上看到,1.36版本居然不打算正式支持VC7.1了,晕倒,看来迁移到VC2008还是正确的哈!