All Stories

轻车熟路的需求实现

  今天去整编辑器了,加上了函数定义的跳转功能,总共大概花了4个小时左右吧,因为没有功能良好的语法解析器支持,所以基本没什么技术含量可言了,就是判断一下当前光标所在位置的单词,假设该单词是一个类的方法名,去数据库中查询一下该方法所在的文件路径和行号,如果有多条记录,则弹出个对话框,列出所有的位置,让用户自己选一个。  下午的时候跟老大说,老大竟然说我做那么快,看来以后得多分点任务。我郁闷!不过做这部分的时候,倒确实有点轻车熟路的感觉。添加对话框,给对话框添加必要的控件,给控制添加必要的消息响应,等等。以及添加新的类,在类中实现该它实现的功能。  不过又想到语法解析器,没有它,做什么都是残废的,唉,什么时候一定要抽时间实现一个。

恢复系统的心得

  从学校出来后,重装系统的次数大大减少,自从买了个本本,只是恢复过一次,今天是第二次,当然不算帮别人装的。  为了减少工作量,有些小小的算不上技巧的伎俩。记得第一次恢复是用的光盘,今天拿出光盘,发现读不出来了,大概是光驱的问题,于是直接选择恢复到出厂设置,反正我的恢复光盘中的内容跟出厂设置差不了多少。  选好后,可以去干点别的事,比如我就出去边吃饭边看电视去了,这样不知道总共花了多少时间,最后一直到设置机器名和用户名密码的地方,这时才需要人工介入。首先需要安装中文支持的MUI包,装完跑到控制面板里设置一下语言,使得界面上可以正常显示那些能完善支持中文的软件。  然后是安装那些必备的软件。  对于那些绿色版、免安装版、安装后更改文件夹后仍然可用的软件,则应该放在非系统分区中。这样下次恢复系统了,使用可以直接使用。比较典型的是Foxmail、QQ、Firefox(它要通过命令行参数实现)等等。  对于必须要运行安装程序才能使用的软件,则根据一般建议安装在系统分区,这样在恢复系统时,也能自动清理掉。这样软件包括Visual Studio、Office(虽然现在实际上不装这个了)等等。  接着是安装系统补丁。有个比较省事的办法,是装个360安全卫士,用它一扫描,发现所有的hotfix,自动下载自动安装,又可以去做些其他事情了。我就打了一会儿游戏,还去洗碗,整理床被等等,哈哈。  做完这些,基本上可算是恢复系统了,但实际上要花很多时间,对于我来说,似乎需要6、7个小时才能搞定!

他妈的中毒了

  还是因为贪心啊,想用盗版软件啊,这下好了,中毒了,不幸中的万幸,不是一个后果很严重的,照赛门铁克的说法,是个误导性的病毒,老说你的机器有风险,还自作主张地把网络给拦截了,有的程序都不能正常使用了,比如foxmail,每次都说打不开socket,暴汗,IE则根本不能打开网页了,幸好一直用的Firefox,不过很多页面上方加了一条腥红的字“Warning! Your system is in danger. You need a full scan of your computer.”,还把很多的超链接的颜色也改成了腥红色,真恶心啊!  盗版软件害死人啊!

对目前项目状态的不满意之处

  程序终于改得主要的核心功能比较稳定了,这是最让我觉得安心的事了。这个项目无疑是到我投入时间和精力最多的项目了,中间过程也是竭尽全力、绞尽脑汁、使出全身解数,充分发扬拿来主义,使用了好几个第三方的开源代码,大概列数一下就有ACE、Boost、iconv、zlib等。眼下流行的工程方法,开发方法也被我有选择地用了一些,感觉自己的水平确实也有了一定的提高。  但是我还是对项目、对我自己并不满意,随便列举一下。  对系统的总体架构不满意,目前只有客户端,我的想法是至少要是C/S结构的,但是这样无疑会大大增加工作量,这也是眼下的无奈之举。  对系统的性能和稳定性不满意,这是代码规模稍微大了点就出现的问题,而且一直也是无能为力的,这方面要有所改进,可能会涉及到整体架构的变更。  对开发模式不满意,纯粹的乱搞方式,没有完善的流程和规范,敏捷很好,却没有实行起来。  对程序结构和编码能力不满意,有不少看起来很丑陋的设计,有不少看起来很丑陋的代码,这点基本上可以通过开发人员的主观努力慢慢提高的。  对自动化程度不满意,现在可以在每次build时自动修改资源中的版本号,每次commit后又可以通过CruiseControl自动集成最后生成安装文件,但测试却只有少量单元测试,还有崩溃报告每次只是通过邮件发送到邮箱中,照我的理解状况是有一个后台服务可以自动收集这些崩溃报告,然后自动进行分析,把尽量详细明显的分析报告提取出来,而且对于已知问题可以直接提示用户。  对持续集成程度不满意,中间的各种测试、度量功能没有好好地利用起来。比如圈复杂度度量、源代码行数度量、重复代码行度量、PCLint、单元测试等等,有的没做,有的做了却没关注。  对与客户之间的关系非常不满意,开发人员太弱势,对于需求基本上没有拒绝的权力,在我看来做了一些可有可无的功能,还做了一些愚蠢错误的设计,对于版本规划等主动权也不够。  这些是大的几点,有的是可以通过自己努力得以改进的,而有的则会涉及到其他方面的人,则只能听天由命了,呵呵。

马峦山溯溪

  今天去溯溪了,在一个叫马峦山的地方,早上7点半起了床,出门大概8点,之前想得好好的,到梅林关去坐车到银湖汽车站,再转车到小梅沙,可是到了出门了,就突然改变主意了,觉得转车两次也太麻烦了。于是直接到小区对面坐380B,可以直达目的地小梅沙海洋公园。以前没坐过,对需要多少时间也没有什么概念,但总觉得保守估计也是2个小时应该绰绰有余了。结果实践证明,大约1个半小时就够了,可能是因为早上路上车少人少开得快的缘故吧。  大概提前了半个小时就到了目的地,倒是在车上遇到2个同事,他们本来是参加另一个户外团的活动的,就是出来晚了,人家已经出发不等他们了,于是就让他们加入我们的团。  最后出发的时间基本上比预定的晚了近20分钟,唉!这次溯溪路程不长,而且人太多了,中间遇到好几个其他的团的人。这次大概就走了2、3个小时就到了吃饭的地方,结果等到吃饭的时候,又是差不多3个小时后了,而且最最重要的是,味道实在不咋的,而且7个菜,最后还要平均每人25元,划不来啊!  下山就快多了,不过真的是上山容易下山难,路比较陡,而且很滑,得非常小心!比较累,呵呵。

谁是最可爱的库

  这个标题很恶心,不过暂时想不出更能容易我现在心情的话来了,就先这么着吧。我就是想表示一下对boost的崇敬和感激之情!  昨天发现用boost.graph可以解决我的问题。今天还是继续昨天的遗留问题,boost.graph确实跟STL那样,提供了抽象的,类型无关(真的无关么?我不确定,但我猜应该是)的算法,但是为了能用它,也着实费了我好些功夫。  我只是为了用它的DFS算法,找出一个有向图中的环。为了配合它的使用,我把之前的代码都丢掉了,重新写了一遍,不过逻辑似乎更清晰了。为了取得里面的back edge,要提供一个回调函数,而这个回调函数的参数类型都是模板参数,而这个参数却是包含了我需要的back edge信息。这就困扰了我大半天。翻了很久的帮助文档,也胡乱看了不少它的examples,最后终于发现有一个source函数和target函数,可以取出edge中的前后两个vectex。  解决了,就像一个同事说的,舒了一口气!  昨天还顺便统计了一下我在工程中主动用到的boost库,一共有9个,分别是utility、foreach、bind、function、lambda、graph、conversion、format、tribool,如果没有boost,我的日子应该会难过得多吧,呵呵。

牛哄哄的boost.graph

  偶然发现需要一个遍历有向图的算法,而且遍历不是主要目的,而是为了找出所有环。翻了一下《算法导论》和《算法概论》,对遍历算法有了个大概的印象,用DFS或BFS就可以,不过要找出环,就晕了。  同事说只要记住游走的路径,如果在一条路径遇到已经访问过的节点,就是环了。虽然说起来简单,但我想用代码实现起来我还是觉得吃力的。  另一个同事说,用boost.graph好了,我早想到了,但出于天生的那点畏惧感,总觉得没那么简单。抱着试试看的心理,看起boost.graph的文档来,惊讶地发现,原来这些常用的图算法都已经封装好了,只要以规定的格式准备好图的数据信息,然后调用一两个函数,就能实现遍历或找出环,实在是太牛了!

用boost.function和boost.bind解耦

  话说昨天被XML摆了一道,发现一种不同模块间交互的方式,就是使用回调。在早期的C语言实现中,回调函数的使用极其简单,Windows的API中就有很多使用这种方式的,可以是一个普通的全局函数,也可以是一个类的静态函数。在C++时,可调用体多了一种类成员函数,这种调用体在被调用时依赖于一个实例指针,因为编译器会自动在该函数的第一个参数前再插入一个函数,即实例指针,作为回调,就稍微麻烦一点。关于可调用体的封装和泛化,可以参考《Modern C++ Design》,中文版《C++设计新思维》。  昨天最后的结果是用boost.function,不过并没有发挥出它应有的作用,还是傻乎乎地把实例指针也传过去了,这跟直接使用原始的成员函数指针没有什么区别。后来想起来,有boost.bind的配合,可以把一个可调用体再作封装,以boost.function的形式而行为上类似于那些脚本语言的closure。在这个案例中,就是把实例指针绑定上去,这样另一个模块就根本不需要知道回调函数的原始类型了,无论是C风格的全局函数,还是类成员函数,在boost.function和boost.bind的联手作用下,都是一样的外表。这带来一个极大的好处,两个模块从此彻底解耦了。

又被XML摆了一道

  要做一个配置界面,用户通过该界面可以修改一些系统配置项。本来配置项是一直都有的,不过不需要用户修改,都写死在配置文件中,这次有了新需求。大体上分成两个部分,一部分用于操作配置文件,另一部分当然是用户界面!  配置文件是XML格式的,用MSXML组件的CString封装版本来操作,用这样封装版本的好处主要有三点:一、所有接口都用CString而不用BSTR,方便与MFC程序交互;二、封装的方法中有一些简单的出错处理;三、有一种简单的用于跟STL中算法适配的迭代器,方便操作节点列表。  问题出现了,图省事,我直接在界面类中获取配置操作类中的DOM数据结构,想直接在界面类中遍历XML,结果发现每个节点想取属性时都会异常。开始怀疑是迭代器封装有bug,于是换了几种访问元素的方法,还是异常。后来猜测难道是不同线程使用COM的原因,想想也没有多线程啊,加上CoInitialize和CoUninitialize,还是异常!于是病急乱投医,想会不会把操作XML的代码全都放在配置操作类中,就好了呢。说干就干,因为要根据读出的配置信息操作界面,所以需要一个通知界面类的方式,我选择了callback,又因为callback是个界面类中的一个成员函数,所以越弄越复杂,最后为了能少写点代码,或者说看起来直观点,动用了boost.function,其实不用它也不会麻烦多少。好不容易全都改过来了,还是异常!我已经接近崩溃的边缘了,再异常就是我神经要异常了!  所谓柳暗花明,最后无意间看了看配置文件的内容,猛然发现根节点下的第一个子节点是条注释!用DOM解析时,注释也是一种节点啊,昏,耗费掉我差不多2个小时,又被XML摆了一道。