有没有一种管理方法,无需额外的测试活动,就能大幅度提高产品质量?L型代码结构就是其中一种候选方案。
缺陷的来源
要减少缺陷,就要先弄清楚到底缺陷是从哪里来的?就我自己的经验而言,大概20%的新手,制造了系统中50%以上的缺陷;而若将人群扩大到80%的新手+中等水平的人,估计他们能制造95%的缺陷;而剩下的20%的高手,可能只制造了5%的缺陷,甚至更低。
这种情况,甚至在高手主动承担最艰巨的部分任务的时候,也是如此。实际上缺陷主要来自于编程者的编程素养,这使得及时团队中即使有一些高手可以做到接近0缺陷,但只要有新手在,程序一样Bug乱飞。
“川”型代码结构的质量
若所有队员各自负责一个或一些功能,每个人都从上层页面、中间的业务逻辑、底层的数据访问一直做下来而互不沟通,代码中缺陷会如何分布呢?
典型的情况,是高手负责的那个模块从上到下都没什么问题,但这不能阻止别人的代码经常出问题,所以整个产品的质量不会很好。
在某些缺少管理的团队中,这种开发模式很常见;但在某些敏捷开发团队中,人们也常常采用这种方式,即人们各自“主动领取”任务,然后独立完成其所有分析、编码、测试工作,然后提交任务。
“三”型代码结构中的质量
若所有队员按层次(一般是表现层View、业务逻辑层Model、数据访问层Data,如果是MVC模式,还有控制层Controller)开发,又会如何呢?
这个模型我所在的团队多次用过,质量明显优于纵向分工的“川”型代码结构。之前多次提到的那个23开发+2测试的团队,开始就是用的“三”型代码结构。
这个模型提高质量的原理是:若将被反复访问的Model和Data等底层代码交给高手完成,则这些代码中本身的缺陷就会很少;由于“反复使用”相同代码,一处发现缺陷,其他处的缺陷也被同时修改,缺陷的修复成本很低;而未来新开发的功能,再次调用这些代码时,则可以直接享受到接近零成本、零缺陷的效果。
三型代码结构的质量问题主要在业务,即即使模块级别的缺陷不再变得很明显,但业务逻辑的错误往往仍然存在,代码准确无误地互相调用,但最终形成一个错误的逻辑结果。这一点在高手们都在忙于设计高度复用的底层模块,而相对的新手进行业务开发的时候尤其明显。当年的2个测试人员,也是为了解决业务测试才聘用的。
三型代码结构的另外一个问题是“需求镀金”。由于多数底层代码都要先于上层代码出现,所以经常有过度设计的情况。当年我做的第一个底层库,就差不多有50%的功能没有实际被用到;尽管这一情况后来得到了改善,但由于很难预测哪些有用哪些没用,镀金问题一直存在。镀金问题虽然一般不会导致灾难性后果,但若高手们50%的时间在镀金,生产力的浪费也是很严重的,工作效率大打折扣。
L型代码结构的质量和工作效率
L型代码结构的诞生
在我自己的经历中,L型代码是由川代码演化而来的。
我发现若有一新一老两个程序员分工,独立完成各自的代码。则一般出现以下现象:
1. 新程序员完成的功能少;老程序员完成的功能多。
2. 新程序员倾向于把代码不分层次地编写成一个大块;若需要自己复用,则可以拷贝粘贴。
3. 老程序员倾向于把代码分层次;尽管只有他自己会复用,但仍会主动提炼类和函数。
4. 尽管两者从不沟通,老程序员的可复用类却可能覆盖新程序员的绝大多数需求,包括绝大多数的数据访问Data级别的代码,以及一些底层业务逻辑代码Model和界面代码View。
比如若一个人开发“产品管理”模块,要管理“产品线–产品–版本–发布”等层次;而另外一个人在开发“部门管理”,要管理“公司–分公司–部门–团队–小组”等层次,除了显而易见的数据库访问代码、缓存等可以互相复用外,树形结构的业务代码也可以复用,而显示他们的界面甚至都可以复用。
若老程序员已经开发了这些可复用代码,新程序员就可以直接使用他们。
5. 老程序员不会发生太多的“镀金”现象。
原因何在?因为他没有“专职地”开发底层库,而是根据自己的需要开发了底层库。我们自己的数据(没有仔细度量)是,我们的11000行代码中,大约有2000多个函数(居然平均4.5行一个),印象中被删除的无用函数数量大约只有50个以下,远远低于原来做过的50%左右的主观感觉。
但也不用担心老程序员“因自己需要”产生的函数不能满足新程序员的新需要,若复用设计做到足够好,新程序员很少需要再编写什么新函数了。
L型代码结构的管理
不过,要让代码真正复用,需要做一点小范围管理——在松结对编程和139团队模式下,困难不大——具体包括:
1. 每当高手新增一个可复用类或函数时,“告知”一下团队。
在我们的环境中,“吼一声”足够了。
2. 当新手想用或开发什么可复用类或函数时,问一下高手。
这个很重要,新手常常也有主动复用的冲动,不过重新发明轮子的可能性居多。
3. 当新手的需求引发底层库改动时,可以采用松结对编程。
一般允许新手查看和改动底层库,这是一个很好的学习机会;通过转移知识,高手也可以把底层库的维护转交给新手,避免成为新手的工具包(在三型代码中,往往正是如此)。
高手可以在修改时提供一些指导,比如用10分钟先描述一下原来的工作原理,并建议在哪些地方进行改动。
新手常常想没事就打开这些底层库一探究竟,不过我发现这种无动机的学习效果很差。应该抓住新手需要新底层代码的机会,让他们学习并接手某些底层。
L型代码结构的质量
L型代码的质量与三型代码大致相当,多次重用导致缺陷无处藏身。
实际上L型代码的底层库甚至不太需要单元测试,质量就可能很高了。因为任何缺陷都会被不同的上层应用所发现,无需人为测试。(这个造成了另外一些问题)
L型代码结构的工作效率
由于高手只在需要时才开发底层代码,所以镀金被有效杜绝。
L型代码结构因此成了一种高质量高效率的编程管理方法。
L型代码存在的质量问题
前一段时间,我们突然被L型代码产生的缺陷而困扰。这些缺陷从哪里来的呢?
由于开发接近尾声,我们决定访问一些早期就开发了但很少使用的上层功能来进行一些有限的测试。结果发现由于它们与新功能调用相同的底层,而底层每次因新功能被改动后都没有回来验证这些旧功能是否还能运行,所以这些功能中很多已经不能运行了,甚至无法打开页面。
这件事后来的解决方法是:自动化回归测试。我们花费大约一周建立了多数功能页面的回归测试,每次提交代码前(有可能修改了底层代码),都会习惯性地跑一遍,确认所有功能都正常运行。若失败,则修改后再提交。
应该说,任何形式的复用包括L型代码结构,都应该配合自动化回归测试。
本文来自于陈勇的博客,经授权转载。