Archives

  • bzr快速入门(3)—- 使用看门人,Gatekeeper

    有没有遇到过这样的时候,一个手欠,或者没注意,一个还没有完全写好的功能就放到主分支上了,而且还很幸运的打到release里面。好吧,你没那么幸运,但是几个经验不是很丰富的小弟把代码随便传上来,你总得看一下吧。 这个怎么搞呢?难道你跑去每个人的地方看看?看着他们跑测试用例?跟着他们做Code Review?一两个人还行,人多呢?要是人不在你身边呢?比如远程开发?如果组织结构更大一点呢?开发团队在开发,测试团队在测试,这样很可能一个没有经过充分测试、检查过的代码版本,就被测试团队抓走了,然后可能就是一堆的问题咯。其实有问题还好,要是有问题没检查出来,那就更麻烦了。 所以,利用bzr的这种天然的DVCS的优势,添加了一个叫做Gatekeeper,看门人的概念。这个概念说起来是很简单的,就是所有的代码,该提交提交,该搞啥搞啥,但是呢,不是提交到主开发分支哪里,而是提交到看门人负责的一个分支上,由他来进行统一的测试审查等等。等完事OK了,他(只有他)再提交到主分支上就好了。这样就保证了所有的问题,低质量的代码,都被看门人挡住了。 看门人可以是一个人,也可以是一个团队,只要能够保证产品的质量就可以了。 比如在服务器,代码都是放在/repo/main上面的,哪么现在根据main生成一个dev.main的分支,所有的人都是基于dev.main进行开发。而测试团队则选择main进行测试,这样开发和测试就已经分开了。然后看门人保证dev.main的质量,当质量达到一定的水平之后,并且代码稳定了,就可以把dev.main merge到main上面了。

    Sep 11th, 2008 | Filed under bzr
  • 初涉敏捷编程

    我们都知道一个设计良好的程序是优雅的,我们也知道单元测试是很重要的,有充足的单元测试就可以尽可能的保证一个程序模块的正确性。这两部分是一直困扰我的部分,如何保证一个设计是尽可能的优雅的,还有就是让单元测试测试到尽可能多的测试点。以前的做法都是提前对程序进行设计,然后进行编码,然后编写单元测试代码,再根据觉得哪里不妥修改代码,修改测试用例。 这里我遇到的问题是 设计阶段不能设计的足够精细这一点非常令我恼火,有的想要给别人看的代码,比如开源,要求你的API设计来不得半点马虎,要设计的很合理。前期的脑纸笔的设计方式,会让细节偏差很大。而合理的API基本上都是通过不断的编码得到的。 单元测试用例并不能覆盖几乎100%的代码当你写好了代码之后,你就懒得写测试用例了,尤其是针对一些不总用到的功能。而写出的用例大多都是一个非常完整的场景,而不是针对某一个小模块的测试。针对性不强。 针对这两个让我极其愤恨的问题,我决定使用敏捷编程,测试先行。 我对测试的看法一直是测试(我承认这是一句废话),我以前都是写了代码(也就过了设计阶段)再写用例,这样程序的API设计大都是凭借对代码的理解捏造出来的,理解的深,功力深,API设计的就相对好一些,理解的不够深,捏造的成分就大,后期自己看着都恶心。但是Kent Beck和Uncle Bob告诉我们测试用例就是在进行程序的设计。其实,一个好用的API,都是经过实践检验的,这样自然要不断的编写和修改代码,而我们把这个过程提前,放在最初要设计的测试用例里面。一个测试用例,就是对一组API的调用的描述,也就是场景重现,这阶段已经就是在使用自己的API,也就是检验自己的API。当然,最初的这部分编码连编译都无法通过,因为你要求的所有东西都没有,但也正因为如此,你才能按照你最舒服的调用方式调用API,而不是受到什么限制。 例如 Query query = xxDAO.createQuery(“Target”); query.addExpression(Expression.eq(“name”, “Testing”); List l = xxDAO.doQuery(query) 这时候,我们没有Query,没有addExpression,没有Expression,什么都没有,但是这代码看着很自然。这就说明如果我们这样设计API就还算不差。下一步很自然的,我们要让这部分代码编译通过,增加Query这个interface[1],然后完成编译。 我认为,到了这个阶段,程序的设计已经完成了80%了,剩下的就是看哪里能够变得更加合理,让臭味更小了。至于所有的实现类的编码,我觉得就是体力劳动了,虽然体力劳动也很累很耗时,但毕竟能够找到解决方法。这时候剩下的事情就简单多了,编写真正的实现类代码,让单元测试通过。 我们应该在编写真正的代码的时候,都是针对测试用例里面使用的API进行编码。这句话的意思就是,我们编写出的方法,应该是测试用例用到的,而不是额外的编写一些暂时没有用到的代码。如果这些将要编写的类/方法没有被测试用例覆盖到,那么要么是这些类/方法暂时没有需求,要么就是测试用例覆盖度不够。哪怕是一个简单的setter/getter,也要有测试用例直接或者间接覆盖到。之所以这样,只是为了避免破窗原理,一个没写,就会有第二个,就会有第n个。 [1]:之所以增加的是interface,就是因为增加的interface更加抽象,行为更加的单纯,并且在测试的时候,可以充分的使用Mock。但是这不是绝对的,在一些纯粹的逻辑的东西,就完全是一个class就能代替的,而无需interface,比如例子中的Expression,用class就比interface好很多

    Apr 30th, 2008 | Filed under 程序设计
  • [Cherrypy]配置设置,静态内容支持

    Cherrypy是一个很不错的python webserver,不过好东西也会让人抓狂的。Cherrypy的配置可以放在一个配置文件中,然后在启动的时候提供出文件名就可以。cherrypy.quickstart(handler, config=’/path/to/conf_file’) 我需要用到的一个功能就是要增加一个静态内容的支持,也就是当用户访问http://localhost/static的时候指向的是我的一个存放静态内容(js,css等)的目录。这个可以使用配置文件的tools.staticfile和tools.staticdir参数设置(相见Cherrypy的StaticContent章节)。但是你写在配置文件中的都需要是一个绝对路径,而我的程序是不一定安装到哪里的,所以只能后期配置。此时的配置信息是分两部分的,一部分是通用的,一部分是静态内容,需要根据当前所在目录组合起来的。 正确的写法是cherrypy.config.update(global_config)然后是cherrypy的quickstart里面的config是static的配置cherrypy.quickstart(handler, config=static_conf) 首先是把全局的配置设置在cherrypy的config中,然后在quickstart里面给出静态内容的配置。 我走了一个弯路,无法正确的使用静态内容 把所有的内容都放在一个配置信息中,使用cherrypy.config.update,在quickstart的时候不给config参数 就原因来说,我查看了一下cherrypy的源代码,他会在quickstart的时候,把config参数应用在tree的mount上,而static content的配置在此时才会起作用的。所以这样做是不行的。

    Mar 14th, 2008 | Filed under cherrypy
  • 给extjs的grid添加一个动作按钮的列,搞不定

    extjs非常好,真的非常好,他的代码写的也很好,很多东西用起来很舒服。 我说的是用起来舒服,并不代表学习使用的时候舒服,其实学习使用extjs真是一个恶心的事情,文档乍看上去很美,但是组织的并不是很好。就好像我写一个FormPanel的时候,里面的items,我需要指定他的显示类型(xtype)就找了半天也无法找到一个完整的类型列表,还是在别人提示下终于抠出来了,原来给放在Ext.Component当中了。好吧,我承认我没有完整的度过API文档,但是你不觉得API文档应该是一个速查手册么? 好了,不啰嗦了,说一下我遇到的问题。实话实说Extjs的Grid还是很不错的,我现在要实现一个很简单的grid,就是前面的几列都是显示相关内容,但是最后一列显示的是几个动作按钮,比如”查看”、”删除”。相信这些都是非常显而易见的东西吧。但是在extjs当中却无法实现。 我想要的 Name Email Action Tom tom@tom.com View 但是我在extjs当中却无法找到如何实现。因为这个View按钮加不上。看文档,未果;Google之,依然未果。只能祭起最后的绝招了,hack源代码。 Grid有两个可以调整的地方,在ColumnModel里面的renderer和editor,但是通过阅读源代码发现renderer只是针对最基本的值类型的,也就是他只是在最终要显示之前的东西进行一下再包装,但是再包装的结果必须是一个值类型(你可以理解成就是一个字符串),如果不是值类型,那么会调用Object.toString()方法。至于editor属性是当grid的一个cell需要有编辑动作时候提供的一个对当前值的编辑器。他必须是一个Ext.Form.Field的子类,而Button不是Field的子类,故,无法使用。我曾经想通过hack extjs的源代码让他按照类似editor的方法添加一个button,但是发现比较麻烦。是因为extjs的代码写的不错,逻辑很严密,这也就说明如果不能把他的结构了然于胸就很难下手去进行大幅度的修改,而模拟editor添加button这个动作,就算是一个大修改,我放弃了。 既然都不可以,那么怎么办?看来只能使用一些龌龊的招数了。既然renderer只能返回一个文本,而这个文本又是会按照innerHTML塞进Cell中的,那么为何不让她产生一个占位的div,然后在grid render之后再操作这些占位div呢?好想法,很容易实现,但是效果不好,生成的Ext.Button太高,把Cell都撑破了,每个Row都有自己的小滚动条了,真是恶心啊。其实这时候只要能修改一下这个row的css,让她的height再高一些就好了,但是发现extjs无法只修改其中一个css,要改就是整个的css class。作罢。 最后采用连接的形式替换了这个button,很无奈。 总结: Extjs代码很不错,是一个优秀的代码,可以用来学习 Extjs代码逻辑严谨,很多思想跟我以前在Hansky时候写的HFC(Hansky Foundational Component,一套类似Extjs的UI框架)的想法都是一样的,说明我没走错路。 给Extjs的建议 提供对Component每一个style向的精准读取设置功能,最简单的增加一个setStyle/getStyle方法就可以了 提供对Grid的更多的支持,允许renderer返回类型为Mixed,这样可以实现更加丰富的grid展示效果 把文档再写好点吧,求求你了。  

    Mar 4th, 2008 | Filed under extjs
Posts Tagged ‘programming’