All Stories

关于打谱程序突然想到的

  今天突然有个想法,关于前段时间的用WTL写个围棋打谱程序的念头,是否可以把棋盘、棋子绘画动作也抽象出来,棋子的位置、走法规则都提取出来,有一组严谨的约束,而且这组约束可以通过配置文件,或者脚本来描述,最后,C/C++代码则只用来完成具体的绘画操作,对这些约束完全一无所知,比如它只知道在哪个坐标画一个什么样的图形,而为什么要画这个图形,这个图形有什么其他的含义,都不是它需要知道的。  如果确实能高度抽象地完成这个描述,那么带来的灵活性则是非常有用的。对于单纯是一个围棋打谱程序来说,也许带来的好处并不明显。但再换个角度考虑,在这一套架构下,很容易通过写少量脚本或配置文件,而不需要修改一行C++代码,一个围棋打谱程序立马摇身一变,成了一个象棋打谱程序,或者五子棋打谱程序了。这样的诱惑,对目前的我来说,实在是巨大呀!  这个想法的灵感,源于Eclipse的编辑器,《Contributing to Eclipse》中有一小段描述可以贡献一个编辑器,当时看到这段描述,甚是激动,差点想把那个IDE项目中的编辑器模块也这样做了。这次又联想到打谱程序,同样是画棋盘棋子的,只要合理设计,理应也可以达到类似的效果。  不过随便想想,以在世界范围最流行的4种棋类(围棋、中国象棋、国际象棋、五子棋)为目标,要想尽可能简单且灵活地实现,还有点困难。如何表示棋子的类型、如何表示行棋规则、如何定义精确的棋子位置以便程序绘制等等,都是摆在眼前最大的障碍。五子棋最容易表示,只有2种棋子,直接落子,虽也有像五手两打,三手交换之类的奇怪规则,但这些似乎都是在棋谱解析部分的工作。围棋则略为复杂,一个明显的问题是,要能计算出死子,并提出棋盘,这个工作如果纯粹交给外部脚本做,怕是会有心无力,但照现在的设计思想又不能让C/C++代码来做。两种象棋就更复杂了,棋子的类型就相比多了很多,每种棋子的合理行棋方式又都不一样,虽然从纯粹打谱的角度讲,比围棋、五子棋也复杂不了多少,但是在棋谱录入时,则很让我头痛了,如何表示一个棋子从一个位置移动到另一个位置,是否可以移动,移动后是否棋子的属性有变化(中国象棋中兵过河可横行,国际象棋中兵到底线可变身),移动后是否影响了其他棋子(吃掉了)等等,关键是一套界面和逻辑的交互协议,不能设计得太偏向于是为某种任务而特意为之,但又得有足够的信息在两者之间传递!

初学lex

  其实学的是flex,从公司网上找的,大概也是gnuwin32中的某个版本。顺便在公司网上又找了些资料来学,纯粹只是看的话,是跨不过那道坎的,所以要自己写几行来玩。生成的C代码倒是能直接用MinGW中的gcc编译,这让人觉得很舒心。开始的时候不明白,为什么写的正则表达式好像不起作用,总是把该扫描分析的文本全都打印出来了,而我明明只是想让它打印被匹配上的那些内容就行了啊,经过仔细观察,最后发现,其实是flex生成的C代码中,自动把不匹配任何自定义正则表达的内容也输出到控制台上去了。所以有两个办法可以解决此问题,一是把匹配内容输出到文件中,另一是修改下flex生成的C代码,把默认输出的那个ECHO修改了。  让它分析一个3万行的rb文件,匹配几种常见的token,如常量、变量、数字等等,速度奇快无比,可能不到1秒吧,想想我原来用Greta写的全文匹配5种模式,不知道要多久,不过幸好在不是很晚的时候发现了这个解决方案。从中已经可以看到曙光,原来我的猜想、直觉应该是正确的。flex可以解析出token,因为我需要的是其中的子模式,所以光是flex还不够,需要借助yacc(现在用bison的比较正常吧)进行语法分析。我猜即使加上了bison生成的语法分析过程,扫描那个3万行的rb文件,得到需要的结果,应该也不会超过3秒钟吧。不过另外有个问题需要注意,flex和bison生成的代码里都有一些全局变量,如果在多线程环境中使用,需要非常小心地进行同步,不过也许,自己也是可以对生成的代码略作修改的吧,尽管这些代码的可读性在我看来真的十分糟糕。

有必要系统地学习一下编译原理

  因为我是一个半路出家的coder,除了会写几行C/C++代码外,所有其他计算机科班出身的人会做的事我都不会,这也是我的一大劣势。  其实前段时间就想过,要学一下lex和yacc的用法。有这个想法,主要还在于看到不少开源项目,比如doxygen、source highlight、swig等等,全都用到了相关的东西,而正是因为我对这方面一无所知,所以即使能获取到它们的源代码,我也不知道如何自己编译。  这两天在公司里,遇到一个问题。编辑器里需要auto completion,为了尽可能实现地进行联想,于是以project方式组织时,需要扫描单独文件的上级文件内容,把符合要求的几种模式都识别出来,其实也只有5种。于是我就用了一个比较简单,可以说是笨的方法,用正则表达式去全文匹配一下,5种模式就匹配了5次,当文件内容少的时候,问题不明显,可说是没有问题。当文件有几万行时,就不行了,CPU占用率一下就99%以上了,而且匹配一次就会持续十来秒,5次就可能要1分钟去了。而且这个动作是在打开文件的时候进行,所以如果连续打开多个文件,机器就假死了。这个问题一直在存在,存在大半年了,只不过没人提出来,我也没意识到其严重性。这次跟同事讨论起来,我才觉得不改不行了,但我又想不出好的办法,缺少必要的理论支持,绞尽脑汁也是无济于事的。我的直觉告诉我,用编译原理方面的知识可以解决这个问题,所以学习编译原理也将提上议程。  编译原理一直以来是我最怕学的东西之一,记得很久以前,高中时的某个假期吧,但毫无进展,不了了之。后来大学时考高程,其中有一部分就是编译原理的内容,全靠考前死记硬背,考时胡乱蒙猜。可能其他还欠缺些理论知识的支撑,也是一部分原因吧。  因为想做好编辑器,所以对代码编辑的支持是必不可少的,因此从现在开始,订个计划,学编译原理,lex、yacc使用。

书送到了

  今天上午连续接了两个奇怪的电话。已经有几次了,打到什么布吉五金商行的,结果打到我们这个座机上来了,不过有趣的是,这次这个家伙没有直接挂掉,而是跟我扯起来,说什么交个朋友,有没有兴趣出来干,呵呵,感觉像是个人贩子似的。好不容易挂掉电话,马上就有另外一个人打进来,听背景声音跟前面一个是同一处,但听口音,明显是两个不同的人。这次这个也比较有趣,问我们公司现在招不招人,有什么岗位,待遇如何等等,还说是不是研发的都是高学历的,水平很高的,呵呵。又是好不容易挂上电话,手机又响了,这次是当当网送货的了。蹭蹭跑出去,发现居然是在岗亭门口的一个小角落里,而且看货有好几箱,而送货的只是一辆小自行车,真不知道他怎么把这么多书载过来的,混口饭吃也不容易啊。  打开看了看,建筑类的几本书的纸张质量还真是不敢恭维。《Head First Design Pattern》外面有一张塑料纸包着,好厚一本,拿回家翻了翻,有点后悔,价格定那么高,里面的篇幅实在没多少,很多的插图,很多的空白,浪费啊,看来我还是习惯那种适合苦读的典型的中国教科书啊。《建筑模式语言》有上下两册,精装的外壳,很厚很厚,但里面的纸张远不如《Head First DP》,《建筑的永恒之道》不是很厚,而且不是很大开本,不过奇怪的是,想不到建筑类的书居然也定价那么高。

继续学习设计模式

  还是没干什么事,看了一阵书,话说昨天把《设计模式解析》第二版还掉了,其实旁边的同事又马上借回来了,于是乎我就拿来看看,看得囫囵吞枣的,不过也比直接看GoF的要省力得多。其实一直以来我都很少会认真仔细地从头到尾看完一本技术类书籍,很多书甚至是只看了前言、序,或者目录就直接丢到一边了。虽是这样,就算没完整看完一本书,像那种武侠小说中描述的那样,像我这样的小虾,向大师学习时,能领悟到个一招半式也是受用无穷的了。  到今天为止,大致了解了Adapter、Facade、Bridge、Strategy、Abstract Factory这几种模式。简单地说来,Adapter是为了转换接口,Facade则是为了封装并简化接口,Bridge说是把抽象和实现解耦,在我看来,实际是把几种不同类的概念分类,避免组合爆炸,Strategy是为了封装算法,Abstract Factory则是封装一系列相关的类的实例化过程。在阅读《设计模式解析》的过程中,我还发现一个比较明显的现象,有些模式,或者说有些解决问题的方案,其实都是通过将问题细化,将较细粒度的变化进行封装来实现的。比如书中讲述Strategy模式时,一开始例举的是直接继承,在论述了该例的缺点后,才抛出新的方法,其实就是把更小更精确粒度的变化提取出来并进行封装。在讲述Bridge模式时,也有类似的倾向和做法。再回想《重构》一书中,作者Martin Fowler则是更激进的做法,如果要给一段代码添加注释,则把这段代码提取出来,用有意义的函数名来阐述代码的作用。这从另一角度促使了小粒度代码段的生成。  《设计模式解析》一书的写作风格也是让人比较舒服的。作者会花一些章节进行理论或实际例子的讲述,再用一些章节描述模式,再讲述一些通用的理论,如此穿插的作法,反正我书看得少,正是第一次看到,感觉比较容易让人接受并领悟。

静不下心来

  我就是缺乏定力,就是忍不住去做些无聊的打发时间的事情,就是不愿意去做些有实际意义的事情。早上起来就觉得很烦躁,也不知道是哪里出问题了,仔细想想好像也没有什么重要的事情,但总是静不下心来。  白天在公司里糊里糊涂地过了一天,看了一点书,《设计模式解析》,书写得还是比较合我的口味的,不过下午的时候去图书馆,把这书还了,因为快到期了,以前没怎么看,后来觉得有用的时候,却是借期快满了。虽然只看了前半本,但也觉得略有斩获。前半本有不少内容是通用性的概念,有些概念我一看就觉得就是这么回事,不过自己却肯定总结不出这么精辟的来。

XUL,也不错的一种选择

  今天在公司网上看到一人发了个Komodo IDE,装来看了看,猛然发现它是基于Mozilla XUL技术实现的,有点诧异,居然还真有用XUL技术开发的商业软件。然后就跟公司里的另外一个人讨论了一下,那人比较了解XUL,在去年还做过技术选型工作。  从中我了解到,有一种叫Remote XUL的技术,可以使得通过Firefox浏览某个页面,界面效果跟通用的桌面软件差不多,但实际上却真真实实是部署在远程服务器上的。其他能达到类似的效果的有JAVA Applet,或者MS的ActiveX,好像Adobe现在在搞的AIR也差不多,有种让人惊艳的感觉。看来该是有必要学一点这方面的新技术了,一直以来觉得跟Web相关的,都不是很感冒,但现在看来,它混淆了B/S和C/S,即桌面和浏览器的概念,很有意思啊,比如,假设有一种能适应各种浏览器的这类技术,那么做一个Web版的IDE什么的也不是问题了。  除了这种远程部署的界面技术,还有其灵活的可扩展框架也是让我感兴趣的。那人的胶片中对Eclipse RCP和Mozilla XUL进行了简单的比较,结论是更看好XUL的,不过我个人的观点看来,两者单纯从可扩展性上讲,各有优缺点,不相上下吧。XUL体系使用C/C++实现具体的界面控件,然后用XML描述界面布局和事件响应,用JavaScript完成实际的业务逻辑,响应XML中定义的事件,调用C++代码作出具体的动作。XUL要创建出新的界面控件比较困难,只能用已有的控件组合成新控件,所以像Firefox就实际上提供了扩展和插件两种不同的机制,扩展就完成只使用XML和JavaScript实现,而插件就可以实现比较高级的像内嵌Flash播放器之类的功能。总之,简单看来,相比Eclipse的实现方案,XUL并没有哪里特别不如,或哪点特别突出,只能说也是一种不错的机制。倒是让我多了解了一种扩展方式,自己设计可扩展的软件架构时,倒是要好好考虑一下了。

再次开始学习设计模式

  虽说好久好久以前就认识到设计模式的重要性,也好几次都决心要认真系统地学习一下,但是每次都没能坚持下来,每次看到GoF的书,立马一个头变成两个大,实在是枯燥乏味啊。倒是总能看到那么多人,学这么枯燥的东西津津有味的样子,然后头头是道是品头论足,心中不免有一丝的羡慕,什么时候自己也能那么熟悉并熟练地应用这些设计模式该有多好啊!  当兴趣渐渐从纯粹的编程语言技巧转移到架构设计、软件工程方面上来时,就有意无意地拿起《重构》、《敏捷软件开发》、《重构与模式》等书看。这些书有一个比较有趣的特点,就是互相引用,于是,我发现不懂设计模式已成为我前进道路上最大的障碍。我要进步,就必须要清除所有的阻碍,所以我要再次开始学习设计模式。  仔细考虑一下,为什么之前我每次都会放弃,是因为GoF那书太枯燥抽象了。所以要去找几本通俗易懂的书来先补充一下这方面的不足。《设计模式解析》第二版似乎还算入门级的,从公司图书馆中借到一本,抽空要快速看一遍。看网上的评论,《Head First Design Pattern》更加适合初学和进阶,所以要看看。另外,看到这些书中都提到了Christopher Alexander写的书, 有中文版《建筑的永恒之道》和《建筑模式语言》,这是关于建筑学的书,但是软件架构设计就跟建筑学有类似的地方,而且设计模式的起源据说就是从Alexander的研究中开始的,就当开阔眼界也好,也买来看看。  我并不是想做一个软件架构师,我只是想能轻松地写出结构优美,弹性十足,易于维护的程序来。

居然还有人想试用这东西

  今天有个项目部的主管来找我,问我那流程平台工程做得怎么样了,他们部门目前新员工多,觉得这个工具或许可以解决当前的问题。我比较诧异啊,居然还有人想试用这东西,说实话现在这边的状况是,尽量快点甩手,从此解脱。我早就不胜其烦,厌倦了没完没了在上面投入。那位主管说得很有理,说这东西做好了很有价值。这个我当然也知道,如果做好了,当然有价值,关键是上头的决心有多大,愿意投入的成本有多少。一直就是我一个人在折腾,一个人折腾么,给我足够的权力和资源也好,偏偏也没有,要指手划脚地作些不合适的决定。  今天我突然想到,要是早知道会拖到5月底这么久,早期的设计就可以做得好一点,2个月有2个月的做法,3个季度有3个季度的做法,唉,这应该可以算是一个失败的案例了。  回顾检讨一下失败的原因:1、前期的规划没做好,开始以为时间不足,就迫使强制采取了些不良设计;2、用户需求一直不明确,以及用户需求实现比较困难;3、我做为唯一的开发人员,心理上有所抵制,积极性不高;4、开发编码工作没有计划和任务跟踪;5、缺少测试支持等额外资源的投入;6、现在看来,因为其他因素的影响,似乎开发投入人力也不够。  暂时只想到这几点,不过也很难过了,唉!