Fan 的个人资料missdeer 之编出来的幸福照片日志列表更多 工具 帮助

再见,华为;再见,深圳

  昨天是我最后一天在华为公司上班,心情很平静,没什么特殊的感觉,用小妞的话说,大概就像放假要回家一样。对于这样一个为之工作了4年的地方,有这样的心情,不知是我的悲哀还是公司的悲哀。
  我倒是真发现自己越来越处变不惊了,发生了什么事情,都没多少激动的情绪,这也许是因为野心越来越大,眼界越来越高,自然能触及到的我的底线的机会也就越来越小。
  至于华为,我只是觉得心有悲凉,4年时间也没有让我生成一点归宿感。是的,网上有篇博文叫《联想不是我的家》,对于企业来说,它需要的只是利益,最大化的利益,其他的就不是考虑范围内。这样说华为也许有点不合适,至少在我看来,不少老员工,呃,大致界定为已经换工号的那批人,他们中的很多人对华为似乎是很有荣誉感和归宿感的,只不过我没有机会体验那种感觉罢了。
  深圳,这个只适合年轻人的城市,可以体验一下纸醉金迷的生活的城市。曾经我以为自己已经对深圳不存在排斥心理了。但事实告诉我自己,我错了,就在最近遇到的一些事一些人,让我更加对深圳这个城市充满了厌恶感。
  不过无论怎样,都要说再见了,我现在在深圳机场,写下这些话,算是对这4年生活的简单小结吧。再见,华为;再见,深圳!

幸亏我不是做网页的

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

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

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

代码的坏味道

  最近一直在学习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万多,现在回头看来,这个项目中代码的坏味道似乎少一些,但质量却也不行,崩溃经常发生,其他业务逻辑有问题的也不少。
  所以,我就很是困惑啊,别人的项目是怎么样的情况?

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

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

图形程序设计续之子图

  这次的需求中提到,能为一个图形关联一个子图,用该子图来描述该图形的内部结构信息。展现给用户的语意是,当双击一个图形时,则展示该图形关联的子图。
  今天投入去实现该特性,基本没有遇到什么阻碍,因为原来的架构设计可以满足这个需要。当初把用户界面视图绘画层,图形管理器,图形对象三部分独立开来实现,所有用户操作都从视图绘画层接受,将操作信息传递给图形管理器,再由图形管理器转发给各个图形对象进行响应。在那之后,我曾经考虑过,这么做是不是有点儿过度设计,这个图形管理器的操作响应转发功能是不是多余的。现在却发现,这样的实现才刚刚好,一个子图,对应一个图形管理器,视图绘画层要始终跟踪当前起作用的图形管理器对象,任何时刻都只跟一个图形管理器进行交互。这样,没花费多少力气,只是增加了创建图形管理器,维护图形对象与图形管理器的对应关系以及销毁图形对象和图形管理器的功能,就可以实现子图功能了。
  在实现这个功能时,有一个小心得,及早加入dump文件捕获功能很有用的,因为即使是开发阶段,也不是每次都在调试器中运行,所以当在自测试时偶然出现的崩溃现象,可以及早通过dump文件进行定位,而且因为是Debug版本,所以通过dump文件分析出的结果往往比较精准和明确。
  除此之外,还发现一个以前没想到的现象,原来MFC中,CDocument类的OnCloseDocument方法,居然会销毁自己,及其派生类对象,如果要做些扫尾功能,放在派生类的OnCloseDocument方法中时,一定要把调用CDocument的OnCloseDocument方法放在最后。

std::copy_if?

  几天没有正儿八经写代码了,今天又咬牙写了一会儿。在完成一个新功能后,开始重构原来的代码,把其中用于BOOST_FOREACH的地方都检查了一遍,看能不能重构掉。在刚有BOOST_FOREACH的时候,我还是觉得它很简单很方便很易用的,也许是当时觉得写for循环来迭代遍历容器步骤繁琐了一点儿。自从用上了boost::bind和boost::lambda以后,渐渐习惯了作用STL中的算法来操作容器,到现在,看 BOOST_FOREACH都觉得很不舒服。
  今天看到的几个BOOST_FOREACH,最后被我改得只剩下一处。其中有一处,需要用copy_if算法,而STL中明显是没有这个东东的,看《C++标准程序库》一书说的,如果要这样的功能,得用remove_copy_if,它是copy和remove_if的结合体。结果我开始用的时候没有仔细看它的使用说明,拿来便用,运行结果总是和我预期的刚好相反。我一开始总以为remove_copy_if,是先像remove_if那样,把满足 op为true的元素都移动到容器的最后,然后把这些元素都copy到另一个容器中。实际上是我想差了,应该是它会把源区间内的所有元素都尝试copy到另一个容器中,在copy过程中会把满足op为true的元素剔除掉。我大汗,这个算法的设计实在不好,我就觉得很纳闷,当年那帮大佬们怎么硬是不提供 copy_if呢?
  回到家看了看boost sandbox中的algorithm库,里面已经实现了copy_if,以及其他几个很实用的算法,看注释似乎是作为TR2存在的,可能会加到C++0x中,但那实在是遥遥无期啊!

几根白头发

  中午去吃午饭,楼梯上遇到王同学,依然是一脸茫然困顿的样子,问我去不去吃KFC,我大汗,这个时候选择去吃KFC还真是意外,问她为什么,说是要去洗头,只好去那旁边的KFC店里解决午饭了。而我原本是去食堂的,根本没带钱出来,两手空空,王同学只带了30元,外加几张KFC的优惠券,两个人就这么冲过去了。
  花光那30元钱,外加一些她车上的几元零钱,基本心满意足地吃完KFC,又让王同学带我去洗头。洗完头,吹干,看起来舒服多了,这几天台风来,气温降,早上都懒得洗头洗澡,确实脏了点。猛然发现自己头顶好几根白头发,恐慌,恐惧,恐怖!

热替换不成功的bug

  升级程序中有一个热替换功能,呃,这个热替换,其实是我自己发明的词,意思是如果EXE、DLL之类的文件正在执行,文件是不能删除的,那么升级时也要能被替换成新版本的文件,而不需要相应的进程退出,这就是所谓的热替换。
  之前也一直陆陆续续有bug报上来,说热替换不成功,但有时候又是成功的,于是也一直没放在心上,把它归结于Windows这个API可能有问题,当然更可能是自己用得不对。直到昨天自己再一次调试时,发现一个诡异的现象。升级程序的可执行文件叫updater.exe,其中加载了 dbghelp.dll,当我升级这两个文件时,必然需要热替换了,结果发现,在文件下载完后,替换确实成功了,dbghelp.dll确实已经是新版本的了,可是当升级程序在弹出提示框,提示用户升级完成后,用户点击确定,提示框消失,那个dbghelp.dll文件又诡异地变回旧版本了!一连试了几次,都是如此,简直就是灵异事件了。
  当然,不可能真是灵异,这种单线程的逻辑调试起来还是比较简单的,单步跟踪了一会儿,就发现,原来在在提示框消失后,会调用一个结束处理过程,这个过程中首先会判断当前是否正在升级,如果是,则中断升级过程,并把已经替换掉的文件还原回去。而刚好这段代码写得有问题,把是否正在升级的标志置位,放在调用这个结束处理过程后了,于是总是会发生回滚还原的操作。问题的解决很容易,只是调整一下两个过程的调用顺序就可以了。

修改升级程序

  今天花了点时间在修改升级程序。这个程序完成后,一直没有进行过有效的测试,而是直接给别人用了,呃,这里的别人指的是部门内的其他有项目升级需求的同事。实际上,至少有3个其他项目中使用了这个升级程序,但我自己却没有真实地体验过。总的说来,这个程序在功能上,基本能满足当前的绝大部分需求,从当初的质量部的地个项目中独立出来后,一次大规模重构,代码结构作了不小的调整,当然这调整的原因是原来的架构已经不能适应后面增加新特性的需求了。
  曾经倒也是规划过一个比较长远的版本计划,呃,也许不能称之为版本计划,称为需求实现计划更合适一些。不过后来还是剩下几条没有实在,因为没有工作量分配过来了。今天的投入则是现在发现,在某些情况下,它会崩溃,这是最不能容忍的致使问题。不过很无奈的是,原来没有使用google breakpad来生成dump文件,现在加入了这功能后,暂时也没能把它弄崩溃,于是也压根不知道问题出在哪里。只能听天由命了!

呃,csdn blog expert?

  今天,也是无所事事地点开在csdnblog来看,并不特意是为了看什么,只是一种下意识的行为。惊讶地发现,居然成了博客专家,我狂晕!就凭我那一年有数的几次心血来潮,偶尔想到了,才会用 Windows Live Writer顺便把文章发到那上面去,到目前为止,也总共才8w多的访问量,其中不少还是自己点的,排名居然也有1500。自从确定在blogger上放置blog以来,对那的关注度实在很少很少。
  由此可见,csdn真是没落了啊!想当年,大一上学期,几乎天天跑去网吧,混迹于汇编和C/C++板,下学期买了个电脑后,开始学习 C++Builder,就在C++Builder板混,当时的技术氛围多浓厚啊!可是现在,那些已经消失N久的id,也早已从记忆中淡出!
  呃,csdn blog expert,还真是让我觉得有点尴尬的称号呢!

想去北京

  不知怎的,昨天我突然想起北京这个一直只在书报、电视、网络上才能得到些许印象的城市来。
  想到是不是该挑个什么时候去北京玩一下。想想在北京,认识的人还真不少,有中学同学,有大学同学,有以前一起灌水的网友,有以前的同事,甚至还有关系比较奇怪的,当年帮人家做毕业设计的,呃,勉强可以算是朋友吧。
  想到这些人,就更想去那里旅游一下,顺便想去爬下长城,逛逛故宫。想做的事情还真多啊!

证明自己在这个世界存在过

  昨天上午跟大领导谈了后,基本确定下来辞职的事实。这2周多来,几次同领导们沟通,都被问及到底是什么原因要离职,我都一直以身体抱病需要休息,家人意见要我返回老家以及失恋之后精神不济,工作状态极差等等这些事情做为理由。嗯,其实我说的都是事实,当然也许还有一些没说出口的原因,毕竟作出一个决定,尤其是对自己来说是个关系比较重大,影响比较重大的事情,肯定是有很多原因掺杂在一起,只不过有的比重大些,有的小些而已。
  昨天中午跟王同学在食堂吃饭,我兴高采烈地跟她讲我怎么和领导沟通,我要怎么处理剩下的事情,以后我有什么理想等等,荣荣就说我好兴奋啊,还真是脱离苦海了。兴奋只是暂时的,之后便是接踵而来的麻烦事情需要处理。
  星期天在江江家打牌时,看到一个电视剧,里面一个坐在轮椅上的青年男人歇斯底里地大喊“我受够了,我什么都没有,我没有钱,没有健康,没有爱情……”,沉重地拨动了我的心弦。那不正是现在的我的真实写照吗?记得前些日子跟王同学在QQ上聊天,她还说“可怜的胖胖,出来几年,带着一身病回去了”,我当时可真是郁闷坏了,我可不希望这样被人同情,被人怜悯!但那却是事实。当在电视上听到那几句嚎叫时,我的心情很压抑,不过好在我马上想清楚了,我跟电视上的人是有区别的,最大的区别就是我没有绝望。我仍然对自己的未来充满了希望,尽量到目前为止,情况并不乐观,但我的选择是挣扎,而不是放弃。我不过分乐观,保持着一点应有的悲观和警惕,却不失强大的自信。我有的是远大的而自认为还算高尚的理想,并且坚信自己一定能通过努力在这条路上走下去,直到收获成果。
  这些日子的所见所闻,加上和人讨论得到的启发和自己的思考。我略有点惊讶地发现,原来自己还是有点儿事业心的,只不过跟旁边的大多数人都没取得过一致意见而已。就说那天去江江家打牌,事后回想起来,真觉得有点后怕,人多了还可以一些打个牌,聊个天,要是两个人这么静悄悄的下午呆在家里,可以做些什么?还有上次,小思宇来深圳,把我叫去一起去小妞家里,那第二天下午,4个人打牌打累了,就一个一个倒在客厅的沙发上睡过去了,我也觉得后怕。那不是我想要的生活,至少不是现在的我想要的生活,那太缺少激情和活力,懒洋洋而无所事事是我很害怕面对的状态。我希望在自己有精力有能力的时候,做些事。难得活一次,做一回人,总得做点事情,留下点痕迹,证明自己在这个世界存在过……

今天面了几个人

  也算是体验了一把面试官的感觉,好好玩哦,看着有些人紧张的样子,想想当年自己在学校时那紧张的情形,只能感叹时间的匆匆流逝!

用Beamer作幻灯片后想

  昨天在公司里说到,以后要多作培训,多作交流,这种事情我倒是有点儿兴趣的。培训、交流,那么幻灯片是必不可少的,于是回来后就开始捣鼓Beamer。
  因为就我了解的用LaTeX做幻灯片就只有PDFScreen和Beamer两种方式,而看过实际效果后,更喜欢Beamer生成的那种。以前也用Beamer做过一个非常简单的,这次我想好好研究一下,可以做出一些比较好看的效果来。
  经过昨晚和今天上午的折腾,基本掌握了一些常用的用法。总的说来,还是比较满意的,虽然速度上比较起PowerPoint这种工具慢了不少,但心中还是比较满足的,主要还是熟练程度上的不足,以及缺少良好的工具支持(呃,就是直接拿UltraEdit编辑的)。所以更坚定了我要做一个TeX代码编辑器的想法。
  因为这半年来使用MediaWiki的粗浅经验,让我对TeX的用法有了更多的理解。这所谓的“所想即所得”实在只是为了就对Word之流“所见即所得”才勉强杜撰出来的词汇。在我看来,这个TeX的设计思想,就是典型的西方人的思维方式:懒散、直接、天马行空。对于几千年来接受着严谨、务实、勤勉思想熏陶的中国人来说,一时间还真有点转不过弯来。在TeX中用这样的描述方式:我把这些文字作为标题,把那些文字作为章节名,还有些其他的就是正文,而至于标题、章节名和正文应该用什么字体,什么大小,什么颜色,什么对齐方式则不是当前我应该关心的事;而我们往往已经习惯了这样的做法:我把这些文字设置成黑体四号,居中对齐当作标题,那些字是楷体小四,左侧对齐,当作章节名,还有剩下的就宋体五号了,首行缩进两个字符,就是正文该有的格式。
  就这么对比着来看,所见即所得容易催长用户做出花哨的排版,用户放了较多的精力在如何定制排版格式上;而TeX的所想即所得则比较适合于循规蹈矩的排版任务,在排版过程中可以少费脑筋。这也就是我说西方人的懒散、直接、天马行空的原因。由此也更好理解,为什么Nokia的手机里没有树型结构的文件系统,全靠文件名来索引;为什么wiki也是这样只靠文章标题进行检索;为什么国外品牌的PC机硬盘只有一个分区了……

铁打的营盘流水的兵

  在食堂跟江江、bobo一起吃过晚饭,晃晃悠悠走向F3,没想到在楼下遇到疯丫头,最近见到她有点多啊,前不久教授来深圳,一起吃饭时就见过一次,再之前是马姐姐召集大家吃饭,也见过。她在这边刚开完会,于是就和她聊起来,我告诉她我要辞职回家了,她倒是表现出一点惊讶的样子,比较有趣的是她也跟我说一个“绝密”的事,她老大同意把她调到北京去了。
  这让我越来越觉得用“铁打的营盘流水的兵”这句话来形容我司实在太合适了,真是半军事化的管理,连里面的人这方面的行为都很半军事化啊!想想我进公司这4年来,陆陆续续离开(不一定是离职)的人中,有多少是跟我比较熟的。雨烟离职去了北京,跟老公一起走的;教授是最近才离职的,不过中间也是几经波折,现在是去tsinghua读博了;骨狗是个比较有趣的家伙,离职前的告别邮件还是中英文双语版;小思宇是去巴基斯坦陪彭彭的;孙同学没离职,却想方设法调到武汉去嫁人了,瀑布汗;还有一些不是很熟的同事、同学离职的;剩下几个准备行动的,这中就包括疯丫头,猫猫也许算一个吧,一直嚷嚷着要去南京;小丫头说是年底会去上海,也算是一个吧,也是一直吵着要离职的家伙……总之,大的趋势看,都是往着离自己老家近的地方挪,嗯!