All Stories

做界面真麻烦

  我到现在还是没有掌握到Windows图形界面的真正规则,只能使用各种现成的类库、组(控)件、框架来做界面。很多效果如果默认的控件不能提供,需要自绘什么的,我就傻眼了。  昨天又花了不少时间在做界面上。本来是想在一个Pane上放在一个自绘的ListBox的,结果问题不断,困难重重。其实到最后发现所有的问题都是只要使用适当的窗口风格就可以解决,我大汗!

有关GUI框架的一点事

  今天偶然发现在svn trunk中的wxWidgets已经支持Ribbon了。在更新了代码后,我还特地用VC2008编译了一遍体验了一下。总的说来,可以算是Ribbon了,但感觉没有像XTP、BCG或MFC v9.0中的那么舒服。我看的是它自带的那个sample,还带着Windows标准窗口的标题栏,没有左上角的按钮和下拉菜单,也没有右上角的按钮。不知道是sample中没实现,还是wxWidgets本身就不支持。不过我想么,用wxWidgets本身就说明是重点关注它的跨平台可移植性,就不要关注这种平台特定的东西了,包括那GDI+也是。它既然号称look and feel native,那么代价就是界面不容易做得很有个性,就只适合做些严肃题材的软件了,比如IDE。  今天又看了下MSDN中对VC 2008 Feature Pack中对MFC界面增强的介绍,让我有点儿小小的郁闷,之前是过分谨慎,或者说固步自封了,没早点尝试这个增强库,而一直盯着XTP不放。今天看来,绝大部分需要的特性,在这个Features Pack中是提供了的。只不过现在还没仔细看过它的各个sample的代码,不知道它到底可以实现怎样的效果。

太惨了

  昨天拉肚子,拉了一天,上了5次,拉得四肢乏力,全身脱水,口干舌燥,真是太惨了。好在晚上去二伯家拿了一些药,效果还是挺明显的,早上本来的时候,肚子没怎么乱叫了,经过一晚上的休息,总算也恢复了一点体力!

八年

  今天去市区买电脑桌,我需要的是是圆角的那种,上面还连着书柜的,去找了几个地方,很贵,嗯,至少是超出了我的预计,不过最后还是买了一个那里看起来最便宜的一款。  既然去了市里,就趁此机会去见一下老同学,自从高中毕业以后,至今已经八年多没见,missdeer这个id的由来的那个家伙。昨天在msn上跟她联系过,今天我先打电话到她家,是她妈妈接的电话,我却以为是她在逗我玩,娘俩的嗓音是比较接近,让我差点儿摆了乌龙,还没有多说话而说错话。  倒是想过不少再次见面时的场景,不过现实是让我有点儿意外,她居然叫我去她爷爷家,我比较汗!路上买了点儿水果,呃,确实没这种上人家家里的经验,也没人告诉过我,不过我想有长辈么,带点儿水果应该不算失礼,也不算唐突吧。  实际上,我比我自己想象的要不拘谨得多,这让我自我感觉良好,哈哈。不过毕竟分开得太久了,而且两人的经历差异也太大,让我觉得实在很难找到话题。  这丫头现在瘦得不成样子,164的个子才92斤,真是皮包骨了,还说现在上海就是流行这种骨感的。看那小腿,大概真只有我上臂的粗细了,还是喜欢她以前稍稍有点肉嘟嘟的可爱模样啊!

祝贺伟大祖国60华诞

  嗯,今天是国庆节,是的,我得祝贺,说实话我的心底还是热爱这个国家的,热爱这个国家中的人民的,当然这种热爱并不表示我会同样热爱这个国家的执政党。  上午还是看了国庆阅兵的一部分直播内容,呃,我不是个军事迷,对那些部队装备和武器是一窍不通,不过这不影响我对阅兵式的观赏心情。总的说来,作为一个仅仅60年历史的政府来说,能做到目前这样的程度,真的很不错了,人渣和败类是很难免的,这需要经过长时间的修正才能慢慢做得更好!  祝贺伟大祖国60华诞!

幸亏我不是做网页的

  看到一篇义愤填膺的博文,正气浩然。又看了一下文中的链接,一篇广告帖引起的口水仗。不过倒真是看不惯那作者的作法,死不认账。又看到其他人的跟帖,我不禁庆幸,幸亏我不是做网页的!  不过说到底,我的专业领域C++方面,应该也是有这种问题的,不过我自己没怎么接触到而已。在我准备大举进入本行业之时,有候捷在那里做了不少出色的教育和科普工作,从此弯路就极少走了,想看的书,基本都是挑公认的最顶尖的专家写的最优秀的书籍。而过了那么一小段时间后,自己也基本上具备了识别并挑选出优秀书籍的能力。  不过今天看到那些讲什么ASP、AJAX、JS的书,我还是很庆幸,那个行业似乎比C++的混乱多了啊!

图形程序设计续之自动调整连接点

  本来计划是明天才开始做这个功能的,不过因为着急着要尽快走流程办手续,只好把这最主要的任务尽早实现了。  总的说来,基本算法是完成了,不过还是有些小bug。大体的算法是这样的:三类连接线,包括折线,样本曲线和贝塞尔曲线,其中两种曲线要都Flatten一下,最后变成一组前后相连的线段,然后将这组线段分别与矩形的4条边计算交点,把离交点最近的跟踪点作为新的连接线的一个端点。  这里要注意的是计算交点的顺序问题。也就是说,如果是从连在矩形上的端点开始遍历那组线段来计算交点,那么应该以最后一次的交点作为最终结果。而如果是从另一个端点开始遍历计算交点,那么应该以第一次的交点作为最终结果。  其次是中间点的调整。像折线,一个比较简单的做法,把交点与端点间的所有连接点都删掉就可以了。而样本曲线则应该调整中间的切点位置,贝塞尔曲线则是调整两个控制点的位置,以免新生成的曲线因为中间那些点的牵引而仍然横穿矩形。

图形程序设计续之添加子对象

  今天大概花了两个小时吧,加了右键菜单添加子对象的功能。这个功能的实现,有几个部分需要关注。  首先是图形绘制部分。这是需要修改最少的部分,因为之前的工作已经实现了子图,子对象就是在子图中添加的对象,只需要在相应的响应函数中实现添加子图,在对应的图中添加对象即可。  其次是右键菜单动态生成。这部分也不是很麻烦,只要识别出当前点击位置是什么图形,该图形在业务意义上可以拥有哪些子对象,就可以拼装出一个完整的右键菜单。  最后是花了不少精神的配置信息读取部分。本来配置信息都是从配置文件中读取的,因为并没有对配置文件与配置项的对应关系做严格的限制,所以原先的设计中,把配置项的信息基本上都是做成实时读取的,今天又要拿来用一次,就显得原来的设计似乎不是很方便。不过我还是没做更多的改进,仍然沿用原来的做法,实时读取某个对象可以拥有的子对象的类型信息和其他描述信息,以便于添加到右键菜单和后面的创建子对象 。  今天的任务基本完成。数了一下代码量,这个项目总共才4.7Kloc,挺少的,很出乎我自己的意料之外。这么算来,假设我在这个项目中已经投入20天,那么有效产量大约是230行每天,比自己订的目的500行每天少了一半多啊!

代码的坏味道

  最近一直在学习Martin Fowler的《重构》,并且对照我参与的一个已经投入至少15人年,历时3年,约20万行,目前仍然在继续开发维护的项目,让我觉得触目惊心,其中的代码,到处充斥着Martin Fowler所谓的坏味道,而又困惑重重,不知道别的项目代码质量是如何的。  下面就都只是随便举一下项目中的实际情况为例,项目是用MFC开发,使用了Codejock的Xtreme Toolkit Pro界面扩展库。  重复代码。有3处计算MD5的实现,分别由3个开发人员完成,大概实在是这种实现的代码在网上太容易找到了。另外有一个特性,可以与另一个服务进行文件的上传、下载、更新、同步,而文件因为类型不同,做这些操作时某些细节有细小的差别,但实现中却是为每一类文件具体而完整都实现了一遍这些操作。  过长的函数。有的开发人员就是习惯性地写出长函数。整个项目中,圈复杂度超过100的有4个函数,超过20的不知道是几十还是上百个。  过大的类。有一个类的cpp文件,是18000行,另外有一个类的cpp文件是10000行。还有CMainFrame类的cpp文件,用Source Insight打开后,在列出函数列表的窗口中显示“Too complex to parse”。  过长的函数列表。有一个cpp文件中共9个函数实现,每个函数的参数都超过7个,而且含义晦涩,自从原创人员两年前离职后,没人敢去动那块代码。  发散式变化。前面提到的一个18000行的cpp文件,是一个视图的实现。如果要给该视图的右键菜单中新增加一个菜单项,并进行响应,需要修改不知多少个函数,记得曾经有个开发人员,花了一周时间都在为了一个新增的菜单项。添加代码没花多少时间,时间花在添加后,因此引发的问题上。  霰弹式修改。有两个模块都需要一个高亮显示语法关键字的编辑功能。有一个基本的控件封装类,但要修改一些代码时,总是要很小心地去从头检查一遍另一模块的实现是否受影响。我的理解是,这个控件封装类的抽象不够通用,或者两个模块的相似度并不高。  基本型别偏执。这样的代码在项目中不好找,不过有类似的。项目中使用MSXML操作xml数据,在各个模块的实现中,都直接聚合了一堆MSXML的接口指针,操作xml的方法,和业务逻辑、界面响应完全混合在一起。  Switch结构。很多处又大又长的switch结构。  冗余累赘类。有两个(派生)类过于考虑以后的扩展性,而那种扩展性的需求至少在未来2、3年内是遇不上的。  夸夸其谈未来性。有一个快捷键处理模块,从项目刚开始就已经实现完成,但后来一直没被用过。项目没有开始实际编码前,超过5个人,花了2个月制订了各个模块需要暴露的COM接口,结果到现在3年了,真正实现的接口也才10个左右。  中间转手人。CMainFrame类已经成了各个模块用来转发消息的场所。一个重要的原因是界面与业务逻辑耦合,很多业务处理需要MainFrame转发到相应的界面实现类中进行处理。  狎昵关系。无论是各个Pane还是MDIClient,都与CMainFrame存在着这种双向依赖关系。  异曲同工的类。两个有交互的模块,居然各自定义了一组数据结构,用来描述现实世界中的同一种事物,中间又由CMainFrame来完成这两组数组结构之间的转换。  纯数据的类。很多时候,为了向线程函数传递一些数据(超过一个DWORD的量),就专门定义一个纯数据的类。  被拒绝的遗赠。两个平行的模块,一个类是从另一个类继承过来的,而明明有很多那被继承的类的功能,在派生类中是不需要的。呃,被继承的就是那个18000行的类。另外还有那两个需要编辑功能的模块,曾经居然也是一个类从另一个类直接继承,导致在派生类中变成不需要什么功能,就加些代码,把那部分功能屏蔽掉。  过多的注释,有一个开发人员,喜欢在自己编写的函数开头部分写上几十行注释,呃,全是算法描述和伪代码。  在公司4年,我参与过的略有规模的项目,除了这个外,另外有一个,基本是独自一人完成,代码量最高峰是7万行,后来路过不断的重构,在仍然有新特性增加的前提下,代码量缩减到4万多,现在回头看来,这个项目中代码的坏味道似乎少一些,但质量却也不行,崩溃经常发生,其他业务逻辑有问题的也不少。  所以,我就很是困惑啊,别人的项目是怎么样的情况?