All Stories
提高软件生产力,意味着可以在更短的时间内交付质量更好的软件产品。软件生命周期的各个环节都对此有着极大的影响,而从开发人员的角度讲,有几件事是力所能及的。 一、提高代码产能。单纯的代码生产力,比如一个开发人员原本一天能写100行代码,经过一段时间的学习和锻炼,相同规模相同难度相同质量的代码,只需要半天就可以完成了。 二、提高代码质量。这个质量指代狭义的稳定性、鲁棒性,代码bug少。这一方面也是通过学习、锻炼可以获得此类能力和经验,另一方向,引入合适的工程方法,比如TDD等良好的实践,也有一定的效果。 三、发扬“拿来主义”。现在可以从各种渠道获得并使用的代码片段、函数库、类库、框架、组件、中间件、软件等等不计其数,并不是所有特性和功能都要自己着手开发实现。只要代码功能满足实际需要,质量在可承受的范围内,可维护性也过得去,以及license没问题,就拿来直接用吧。可重用的,不光是代码,还有架构、设计思想等。形式上,无论是源代码复用,还是二进制组件,都可接受,甚至可执行程序也可以。 四、提高代码复用性。自己写过一遍的代码,尽量不要写第二遍,复用吧!代码重构一种使得代码得以提高复用性的不错的办法。 五、提高架构可扩展性。为了更快更好地实现后续新增需求,高可扩展性的架构是一个良好的基础。可扩展性的对面是可裁减性,假如有一天突然要求去掉其中的一些特性,这种情况也是存在的。这点对经验的要求和依赖比较高。 六、提高架构和代码的可修改性。需求发生了变更,或者原本对需求的理解就有问题,或者发现了bug,这些情况都需要对代码进行修改,别因为一个功能上的小改动而引发代码上的大改动。 七、使用先进的工具、方法和流程。比如眼下流行的敏捷,使开发流程减少僵化。使用优秀的IDE,智能感知、重构、自动代码生成等等。使用版本管理工具,定期对一些代码进行指标度量。 八、宽松、舒适的环境。环境好,对开发人员的身心都有好处,长期收益极大。 九、快捷、方便的求助渠道。向人请教是一种很省事的方法,但很可能影响其中一方的状态。上网搜索则是另一条有效途径。 当眼下软件生产力严重不足的情况下,这是仅剩的几件我能做的事了。
历经约2年的安逸生活,blogger终于又不能访问了,这次的决绝,让我惊异和始料不及,这次似乎不是伟大的GFW动的手,而是人家服务器端直接自己被我屏蔽了,悲叹啊! 命运不能掌握在自己手中的感觉,实在太不好了!
这两天看到TL里从MFC讨论到boost,无论是MFC还是boost,支持和反对的人都有,大打口水仗,我也是个不小的愤青,也去凑合了几下。 因为在公司里的项目用的基本上就是MFC,其中也穿插用了不少boost的东西。说心里话,至少目前我对它们没什么不好的印象,对于boost更是有种赞赏的感情,它在C++语言的基础上创建了那么一个通用的可移植的庞然大物,确实为我节省了不少工作量,这是最让我高兴的原因。 TL上的口水仗最后也沦为抓住一丁点儿瑕疵穷追猛打,实在无聊得紧。在我看来,这么一个东西,它确实对我有帮助,也许节省了10%~20%的时间,这就足够让我继续坚持用下去了。
今天跟一个同事讨论起在项目中使用boost::signals,发现有些情况下很适合,比如我们的程序有时候会做些耗时的操作,而且这些操作过程中可能会去访问子窗口,而子窗口却不一定继续有效,于是可能就会有问题了。原来的办法是保存好这些子窗口的句柄,然后给它发消息。但有了signals就可以稍微做得更好一点,把子窗口的类从boost::signals::trackable继承过来,这样子窗口对象销毁时,会自动把它从信号槽中移除,不再需要自己费心管理它是否有效。另外一点的好处,也是boost的各种类惯用的手段,做为回调,只要签名相同,即有唯一确定的返回值和参数列表,而不用在乎它最终是什么形式,全局函数也好,仿函数也好,成员函数也好,都可以作为回调。 从1.39.0开始,boost中有了signals2,相比signals,它有不少改进,但在我看来最主要的是线程安全和header only。其他的用法倒还是和signals一样。不过无论是boost::signals还是boost::signals2,似乎都没有办法解决一个问题,就是Windows GUI的多线程操作。还是得另外想办法啊! 烦躁!
偶然发现WTL已经出到8.1版本了,可是好像CVS里却没有更新,原来是已经切换到SVN里去了,还枉我时不时地update一下呢! 这次更新号称是兼容VC2008,结果我升级了一下,发现原来的一个使用WTL写的程序工作不正常了,居然接口行为都改变了,晕死!原来的8.0版本在VC2008下使用也没什么问题啊! 郁闷!
这两天在公司里,做那个插件架构,到昨天为止,大概实现了一半了,不过总觉得不对劲。这是一个没有经过实践检验的方案,看了那些已经完成的代码,再联想一下完全完成后的可能的模样,心里老是有点不爽,担心内存占用会不会太大了。 现在这个设计是在原来的基础上修改来的,主要的修改是在一个插件中可以定义多个扩展,插件只是扩展的容器,扩展才是真正实现可扩展性的设施。于是相比原来的设计,现在有了两种独立的对象,插件和扩展,而原来一个插件中只定义一个扩展,在代码实现时可以只定义一种对象。于是现在这种情况下,对现实世界的描述,大约会多出近一倍的信息量吧,这些信息如果全部保存到内存中,预计消耗会很大。本来这些信息是通过配置文件描述的,如果不全保存到内存中,就要能实时解析配置文件,这对运行速度也是一个考验,而且能否快速方便地检索到需要的配置文件目前也是个未知数。 崩溃!
TDD中说的是要先写测试用例,再写功能代码,可是无论如何,我都做不到这一点,我无论如何都要先写好功能代码,再回头来写测试用例。 不过虽然这么做了,但我觉得还是不影响我做单元测试的,哈哈。今天是我将CppUnit换成googlettest以来第一次正儿八经地写单元测试用例,感觉还是比较爽的,有种写代码就是一种享受的感觉。用googletest可以比用CppUnit少敲不少字,而且我猛然发现,不用GUI的TestRunner,也没有什么不好的感觉。 通过单元测试来保证类或函数的功能,最适用的场合是算法性的代码,真是太安逸了。
因为要使得插件支持依赖,比如在插件描述中说明,某个插件A,依赖于插件B和插件C,而插件C又依赖于插件D,那么在装载插件A之前,需要先装载插件D,再装载插件B和插件C,最后才是插件A。 这个依赖关于跟C/C++程序代码中的头文件包含处理方式几乎一模一样,典型的做法就是把这所有的依赖关系最终用一张有向图表示,这样通过DFS可以查找到是否有循环依赖,如果有,可以彻底中断装载过程,或者只是简单地把最后一个回边打断而继续装载。 最终整理出来的插件装载顺序也是很容易的。首先查找没有依赖于任何其他插件的插件,无论是理论上还是实际上,肯定是有这种插件存在的。找到这些插件后,把对这些插件的依赖关系都删掉,这样肯定又多出一些插件是已经解决依赖关系的。再把这些多出来的插件作为被依赖的关系删掉,重复前面一步操作,最终可以将所有插件都顺利装载。
早上起来看了一眼邮件列表,发现boost 1.39.0居然发布,这次好像测试都没有多少消息,怪不得前两天就有人在邮件列表上开始说要1.40.0的release building了,真是快啊。这个节奏还真让人有点手足无措的。 在公司里,用的都是正规release出来的版本,那样每次build出来的lib和dll一般都是没有问题的。而在家里,我都是直接从svn里check out来的,里面有的代码还存在些bug,有些则可能连编译都成问题。本来因为懒得编译的原因,我一直都是只用header only的库的,可最近因为公司里那个项目的影响,用了boost::regex、boost::program_options、boost::system、boost::file_system等的库,渐渐对这些需要编译的库也有点依赖心理了,防范心理也弱了不少,可是svn里的代码几乎天天有所更新,编译的话,就太头痛了。