主题:【原创】闲聊敏捷编程——测试驱动开发(一) -- 代码ABC
写代码在外行人看来就是一个鬼画符的过程,也许大夫的病历和这个类似。您确定您感兴趣?
xp的peer review是通过结对进行的,设计是通过频繁的沟通和暗喻来做的。这比通常的pr和设计review更有效。xp很容易造成误解的地方就是单个看他的某个过程或实践都是有重大缺陷的,他强调的就是通过所有实践的联合使用来弥补彼此的缺陷,以最小的成本交付产品。
这个问题对agile项目几乎是灾难性。我们现在就在表面做scrum,实际没多少关系。而且项目经理,产品经理,经常互相搞不懂在做什么,有时候需求干脆是开放人员自己做。
agile强调的现场客户,减少沟通反馈成本就失去了意义。
比如我现在最大的问题就是基于某些框架和方案,这往往是难以做白合性质的单元测试,只能用一些框架去做自动化的确认测试,维护成本非常高。而且我感觉也失去了tdd的本意。最适合开发人员写的,应该是百盒才对。
不知道这方面你有什么好建议? 特别是ui这块,很多web 框架都是基本不可测试的。 httpunit或selenium那样的东西,感觉上有些跑题了,而且对应的测试用列的维护台痛苦。
另外测试代码和实际代码的比例达到一个什么程度为好,也值得讨论。tdd虽然给出了一些结果导向的标准,但是实际做下来感觉还是不够清晰。我们有些程序员基本上都只写大方法的,这样的测试覆盖率太低。
说到这,又要提重构了。但是基于历史原因,很多代码也是比较难用勇气做重构的。比如今天就是,2个人pp 重构完了别人的代码,提交以后cc服务器变红。虽然自己基本确定不是改动那部分的任务, 但是因为test case的覆盖率不高,还是需要手工去检查核实,挺痛苦的。这也再次说明没有完善测试用列的重构是非常危险的。
agile开发说起来真是一言难尽,目前看到最接近agile本质的团队还是在国外的时候。国内的所谓agile圈子里做的,很多都是挂个皮而已,有些所谓专家翻译了一堆书,真跟他们讨论起来,发现也只知道皮毛而已。
举个最简单的例子,勇气这一点,国内程序员就很难做到。昨天发现一个资深程序员居然不明白数据库的索引是如何使用的,对基本概念有完全错误的认识,而且对我的提醒还很是自信,特意写了个长邮件调侃了他一下,就是这样,他也只是答复说忘记加索引了,不肯承认自己对索引概念的认识是错误的。国人做事将情面,但是技术人员如果没有勇气把这些面子的屏障脱去,就很难真正有效的进行沟通。
最近跟经理闹矛盾,其中一点就是个人发现几个大牛对数据库的认识很肤浅,由着他们去倒腾性能优化很危险,希望能强制对他们进行一下基础普及教育,结果上下都不感冒。程序员不乐意承认自己不懂基础,经理觉得我是浪费时间,也在打压大家工作积极性。 这算是文化背景的巨大差异了。
算了,比起国内某著名技术人员,号称作了n年的dba,居然连数据库范式都不明白,我们这些大牛也算不错了,用经理的话来说,可以解决问题么,你折腾啥,又不是火箭工程。但是本质上,就少了国外程序员那种不断追求细致,追求细节,追求完美的精英作风。这点我看来也是敏捷的本质之一,敏捷中的程序员不要求是大牛,但是要有追求完美的愿望,而且乐意从小事做起,从细节做起,而我们太多人只喜欢做那些炫耀技巧性质的东西。
UI测试是一个难点,我个人的做法是将UI先抽象成输入/输出模块,然后用Mock技术模拟UI操作完成非UI部分的测试。到具体的UI部件则使用控件技术将复杂UI分割为简单模块,可以覆盖大部分UI功能。最后使用LoadRunner之类的东西做传统的功能测试(黑盒)实际效果是95%以上的代码可以在白盒内完成测试。
我个人不喜欢框架,在不得不用框架的时候我会把框架作为一个软件包。通过Adapter,FADE之类的东西封装一下。把我的代码和他们隔离,只做自己的代码测试。
测试覆盖率其实和你的开发方法有关,一定要记住TDD的一个原则——让未完成的工作最大化。覆盖率不够经常是由于预先设计引起的,这些设计使得程序员忽略的一些必须的测试用例——他认为代码中已经实现了不需要测试。这个原则其实是最难把握的,没有太好的方法。只能在实践过程中慢慢领会。同时XP的结对编程可以在很大程度上缓解这个问题。无奈,结对编程也是一个不太容易掌握的方法。同样的问题也会造成重构的麻烦,在TDD中重构是在每实现一个测试后进行的,也就是你必须保证你的代码一直处于合理的设计状态。
敏捷说起来很好,但实践起来并不容易。由于其中的东西是一环扣一环的,你说的很对,单看其中一个实践其缺陷都很明显,但是这些缺陷都会被其他实践覆盖。而反过来的意思是只要你有一个实践不做,就可能引起其他实践的缺陷。
不懂范式的DBA我见多了(这句话在河里说,恐怕要挨砖)我在讲数据库优化的课程里,下面坐的都是N年的DBA,能说出来的不到一半。
软件开发大部分时间都浪费在找错上。这个角度来看,应该更节约时间才对。
现在一看到喜欢debug的程序员就头痛,很浪费时间。除非是框架技术限制,或者为了看懂别人的代码,调试都是很浪费时间的。
导致开发过程过于复杂,所以迭代也很难明确定义和独立划分,几个迭代之间往往相互嵌套。说不好听一点,看看rational的产品rose的弱智程度,就可以知道rup好在啥地方了。开发了n年,连个undo都没有。
那会研究rup的时候,说实话折腾了半年我都没真正明白迭代到底是啥玩意。为了如何裁剪rup,我们都可以吵三个月。
对了,你是leiyunfei那个同学么?
refactor比喻象是汽车5年一改款之前的每年一升级时的小改,是循序渐进的,是不伤大雅的。
redesign是5年一次的改款,市场定位或有重大缺陷等,需求出现重大改动,而使原来的底盘,引擎,外观等必须重新设计。
或者这是单独的一部分?
但是集成测试是比较容易忽略的,TDD在这方面并没有更好的效果。更何况写单元测试的时间不比实现测试对象的时间少多少。所以TDD并非节约时间,而是尽早发现错误,并且可以在开发早期重构代码,提高质量。