SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 4127|回复: 5

[赏析] 第 4 章 第一组旋钮:检测的力度和方法

[复制链接]
发表于 2013-10-9 10:50:16 | 显示全部楼层 |阅读模式
第 4 章        第一组旋钮:检测的力度和方法
9 V; |' h7 ?8 U! c5 w7 x
制定集成策略,优化集成工作,就好像是在控制面板上调节旋钮、扳动开关,观察或推演项目的六个要素产生或将会产生的变化,看看是不是项目想要的。从本章开始,我们来看看,有哪些可以扳动的开关,有哪些可以调节的旋钮,看看调整它们会有什么样的效果。
" U/ s3 p! H1 z  f+ j+ L5 A( F3 [, V/ P
我们把这些开关和旋钮按照类别分为四组。本章将讨论其中的第一组:既然集成分为三个阶段①,那么我们来看看,集成工作在各个阶段中应该分别投入多少精力,做到什么程度。也就是说,我们应当把按钮拧到什么位置。此外,我们也将讨论具体选择哪些集成工作方法,这就好像是确定应该扳动哪些开关到开的位置。! f* ]) G5 o1 L. _/ Z3 ~, s8 R
" {# T7 J' V8 q, o
尽管我们以笛卡尔式的分析方法①入手,但要始终注意,这些旋钮并非独立存在,它们相互关联,相互影响,一起构成了软件集成的整体解决方案。而我们做集成优化改进的目标,也是为了让项目整体受益,而非局部优化,或提高某个指标。
' X& ^! D/ a4 t2 c6 W5 {( m( W  h& d4 |4 d5 W. Q  Z
①关于集成的三个阶段,见第 2.4节。% q+ W3 J% O  k# R+ D: D
①“把我所考察的每一个难题,都尽可能地分成细小的部分,直到可以而且适于加以圆满解决的程度为止。”——勒内·笛卡尔
 楼主| 发表于 2013-10-9 11:08:21 | 显示全部楼层
4.1 提交前检测力度$ B5 @" F2 q( [3 U- N  U

! u/ E: v" j9 R假定在你所在的项目中,你收到一个提议,要在集成的第一阶段,也就是程序员提交前,通过某种方法,进一步加强质量保证工作。这种提议让人不好拒绝,因为拒绝它就可能被戴上漠视质量之类的帽子。然而,客观上讲,对于某个具体的旨在提高质量的提议,它到底是不是一个好的提议?是不是对项目对企业有利的?这可真不一定,需要具体分析。为了弄清楚它到底是不是一个好提议,首先要研究、实施这个提议的话,会有什么效果。. u" {! A/ b* s# P+ V8 b

  S) {6 P8 V$ v; C) Z' C; {  m有利的一面是,提交的质量会更高。于是,需要在第二阶段和第三阶段继续发现和修复的问题的数量和相应的代价会下降。此外,更多地消除了程序中的问题,减少了程序中问题的数量,也将使后续的开发和集成工作更顺畅。而不利的一面是,在第一阶段加强质量保证工作,需要在此阶段增加更多资源、更多成本,并影响项目时长。有利有弊。利多还是弊多?, m( C. |3 ^  \/ s4 v. x) l

1 s! A+ ]* T" f; p7 h我们先暂不考虑程序质量越高,后续开发和集成工作就更顺畅这一点。我们先只考虑为了将来发布时能达到一定质量,在第一阶段发现与修复更多问题,跟在第二和第三阶段发现与修复这些问题相比,效率是不是更高,代价是不是更低。之后,在第4.3节中,我们再考虑程序质量越高,后续开发和集成工作就更顺畅这一点,补充和修正我们的结论。, ?2 m* c5 g' R
1 f1 e, w. I8 ^, N1 ~" z
从解决问题的成本考虑,越早修复,成本越低,见第 3.6节讨论。所以,一般来说,提交前应该做检测并修复检测发现的问题,这样比晚修复要便宜。

4 ]  `6 m7 j0 q3 M) Z0 ?然而从发现问题的角度考虑,边际效用递减。也就是说,在提交前,当前质量越高,发现下一个缺陷就越难。再多发现一个缺陷,要耗去程序员更多时间。对于这个缺陷,程序员值得为了在解决它的时候省一点时间,而耗费大量时间来发现它吗?1 |- S+ }, Z  A

( h3 k! s* e' e8 ?% c, {
举例来说,一名程序员在提交前做检测,已经测出来并且修复了不少问题。根据发现缺陷所需时间的变化趋势,他预计发现下一个缺陷要再耗去自己0.5小时的时间,然而提交前修复缺陷与等测试人员发现后再修复缺陷相比,仅仅从 0.3小时降到0.1小时,下降 0.2小时。所以,他就当机立断,不再做进一步的检测工作了,干脆扔给测试团队去测试①。
  E% M" q) i, D
程序员按照这个思路去做事,是不是比较自私呢?不再多测一测,而是扔给测试团队,会不会增加了测试团队的工作量呢?其实关系不大,因为不论程序员提交质量比较好还是特别好,测试团队都是要做全面深入的测试的。. j' {3 d4 \! l% w  b) h

0 k( w% E0 w) g: f8 \* }
当然,多漏给测试团队一个缺陷的话,测试团队的工作还是会增加一些,比如在缺陷跟踪工具里填上这个缺陷,将来还要复核这个缺陷是不是确实修复了。这些增加的工作量,都可以算作发现了这个缺陷后,为了解决它而进行的工作。程序员为了解决它,需要修改代码,而测试人员也跟着忙。

/ T1 V6 v4 L. k; C3 Z因此,我们把前面程序员判断是否要继续检测的方法,稍微改一改,让它更合理一点:如果他根据发现缺陷所需时间的变化趋势,来预计再发现一个缺陷要继续检测的人时,要比在提交前就发现它所节约的解决问题的人时要高,那就不必继续检测了。而这里解决问题的人时,既包括程序员自己的人时,也包括测试人员的人时,如果拖到了第三阶段由测试人员发现这个问题的话。: X2 }3 O* M2 I

: L' z% i" }/ m# I' K9 r% |* R
换句话说,当程序员刚做完代码改动的时候,一定要做各种检测工作,努力发现问题。这个时候,一般也挺容易就能发现问题。但随着时间的流逝,他会感觉到,再发现一个问题越来越难。在适当的时候,他就要放弃了,而不是去一味追求高质量,完美的质量。这样才是对项目昀好的方法。
6 {1 u' S. _$ k# _1 n9 j
那么,具体如何得到那些计算、判断所需要的数据呢?估计呗。根据历史上的经验,特别是根据发现前面几个缺陷的所用的时间,可以粗糙地推测发现下一个缺陷将用的时间。对于具体的某个改动某个提交,这个推测可能会很不准,但是在统计意义上这是有价值的。而解决问题所需要的时间,可以根据经验积累。程序员要想知道测试人员为每个缺陷所多付出的时间,那就去跟测试人员聊一聊。通过沟通,说不定会发现,自己过去的猜测其实跟实际情况差得很远。' R+ m" Z8 n! |) N1 c; q# l3 @

, M8 E; {9 x/ d
以上这些数据,都只能是一些粗略的估计。但这样也总比不做估计和计算,让管理层拍脑袋做结论要好。更比一根筋地只顾提高提交质量或者只顾提高开发速度要好得多。

5 N. P, L5 n  b9 H  m以上是从成本的角度分析。发现和解决问题还会影响项目时长,下面我们将从这点分析,看看如何尽量减少因发现和解决问题而造成的项目时长增加。在你所在的实际项目中,如果你首先想尽力压缩集成成本,请重点考虑上面的分析。如果你首先想尽快发布上市,那么请重点考虑下面的分析。3 c5 I# t( C+ @/ w/ C# c
$ @8 J8 Y4 x. _# o0 k9 a$ M
如果一个项目时长要求很紧,而资源供给充沛,有足够的程序员可供使用的项目,那么应该尽量缩短关键路径,压缩项目时长。在此条件下,对于关键路径上和比较容易跑到关键路径上的改动,可适当降低对提交质量的要求,缩短提交前的耗时,以此缩短以关键路径为代表的,开发新功能的路径的长度。而把发现和解决问题这部分工作尽量转由集成的第三阶段完成,并且充分利用测试和修复缺陷的充沛资源,让集成的第三阶段尽可能并行于程序功能的开发。这样,等程序功能在尽可能短的时间内开发完了,质量保证工作也差不多完成了,项目时长昀短。

; P5 J0 {( o3 T! W& i4 n% y6 y& g也就是说,在这样的项目里,本质上是要使用一个通用的思路:既然要(在保证质量的前提下)尽快完成一件事情,那就投入宽裕的资源,把各项工作尽可能地并行起来,分头完成,哪怕因此而降低了资源的使用效率。在这个例子里,对于一个开发任务,把消除其中问题的时机推迟到集成的第三阶段,而且可能并非由做出改动的这名程序员(他可能又去忙关键路径上的其他开发任务了)来负责修正,这样会降低效率,耗费更多成本。但是这样有利于项目时长的缩短。. f) m5 C+ d, z& _- m+ b$ I( |

1 H: g) G- X. ^/ k
与上一种情况不同,有些项目程序员人手紧张,程序员成为项目的关键资源。在这样的情境里,要想项目时长昀短,要充分利用程序员资源,确保他们高效工作。此时,关注重点是提高程序员工作效率,包括发现和解决问题的效率。因此对项目时长的分析方法类似于前面从程序员的视角对其人力成本的分析:关键是减少每发现和修复一个问题所消耗的程序员的人时总数。
" p5 |2 E& K% u1 N' K
相对应的,当项目的测试人员而非程序员人手紧张的时候,就要让程序员适当多发现问题。当测试人员人手紧张时,常常不得不降低测试的频率,因而推迟每个漏入集成第三阶段的问题被发现的时间。在下一节我们将看到,越到项目后期,这将对产品发布时间有越大的影响。让程序员适当多发现问题,能够减少漏入集成第三阶段的问题的数量,昀终减少项目时长。( D* R# J4 h' z2 C( r) _1 P

4 s( ?& V- k/ Y6 p6 _3 K) i$ P①当然,这样做的前提是,不论是测试团队在集成的第三阶段,还是程序员在集成的第一阶段,都有能力发现这个缺陷。注意,有些缺陷容易通过集成的第一阶段可采用的一些检测方法发现,却难以被第三阶段的系统测试发现。详见本章后续讨论。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-9 11:17:18 | 显示全部楼层
4.2当项目临近发布时

- I+ O# a! {$ h7 \
上一节讨论并给出的,是一般性的结论。它比较适合于项目的早期和中期。在项目末期接近发布时,有一些特殊性。本节,我们分析项目临近发布时的情况。
! L' k7 o) E  u+ P
项目的末期,或长或短,常常是有一段以消除缺陷为主要工作内容的稳定化阶段。此时,程序员主要是完成并提交以修复缺陷为目的的改动,而测试团队则一轮又一轮不断测试。注意,程序员提交的改动,不一定完全修复了已有的缺陷,甚至可能增加了新的缺陷。4 ]+ G# i* V' @  b1 F; O+ c
9 B7 }/ ^# K4 l. w  ^
假定测试人员非常的多,随时可以多人并行进行任何测试以发现问题,那么每当程序员提交后,在短时间内,就能收到反馈,了解本次提交的内容是否有问题,是否仍有缺陷要修复。此时,还需要多少时间才能发布,在很大程度上取决于程序员消灭缺陷的速度。假如此时共有300个发布前需要修复的缺陷,程序员共 10人,每人每天提交的代码,号称修复 2个缺陷,其实新引入或未修复0.5个缺陷,那么每天程序员消除的缺陷总数就是(2-0.5)X10=15,也就是说,大约 20天后,程序就可以发布了。

$ y5 ~7 I) P- A4 Q( e在这种条件下,要想早日发布,关键是提高程序员消灭缺陷的效率,而不是单纯地衡量他提交的质量。每天消灭2个缺陷但引入 0.5个缺陷的程序员,要比每天消灭 1个缺陷而不引入新缺陷的程序员更有贡献。在(自以为)修复了一个缺陷后,程序员要进行检测验证工作。到何时为止呢?如果他连修复带检测,已经花了4小时,估计有 80%的可能性修复了这个问题且未引入新的问题,而预计再花 1小时,能再提高 10%的可能性,有 90%的把握,那就不要再花这1小时了。因为前面的 4小时,工作效率是每小时修复 80% / 4=0.2个问题,而接下去的1小时,工作效率是每小时修复 10% / 1=0.1个问题。赶快提交,然后去修复别的问题吧。
+ A3 Z3 X- Z. _4 l/ Y, j7 b2 q% |5 Q  j: }, n
这种情形是一种理想的情形。实际情况是,测试人员并非无限多,测试有一定的周期。在临近发布时,铺上所有的测试资源,做一轮全面深入细致的测试,如果发现的问题足够少了,指标达到具体项目的需求,就发布。如果发现的问题还不少,就继续工作。由于这是发布前的昀后一道质量把关,通常不敢靠增量测试①来把关,得是全面深入细致的测试,否则风险太大。
, t! l/ a1 n$ J6 X( }/ L8 J
假定进行一轮全面深入的测试需要一周的时间,测试完毕后,若不合格,就马不停蹄开始下一轮全面深入的测试。在程序员方面,简便起见,假定在我们的这个例子中,程序员的数量很多,工作效率非常高,以至于每当发现一个缺陷,在很短的时间内它就被(号称)修复了。那么,在下一轮测试之前,所有的缺陷都(号称)修复好啦。当然,是号称,其实有25%的问题没有真正修复或者新涌现出来,假定这些问题都将在下一轮测试中暴露出来。那么在这样的场景中,对付 300个需要在发布前修复的缺陷,需要多久呢?
3 W% m" }+ A& v, S: }6 m* l7 W
第一周过去了,程序员们号称修复了全部 300个缺陷,但随后的系统测试说明,仍有 300 X 25%=75个。第二周过去了,程序员们号称修复了这 75个缺陷,但随后的系统测试说明,仍有 75 X 25%≈19个。第三周过去了,5个。第四周过去了,1个。第五周过去了,测试表明,终于可以发布了。
6 j: m* x8 \# \0 o. T* _2 ?5 J9 r$ \$ ~$ }" a& a. Q( `
当然,这是个极端的例子。不一定是每个到达一定严重级别的缺陷都必须修复才能发布,或许只测试出5个的时候,就可以发布了。于是,需要三周的时间。

% M  o) ?) Q: y  Z0 I  {' t5 _" t不论是五周还是三周,都是由全面深入的系统测试的频度和程序员提交的质量①,共同决定了产品何时发布。在这种情况下,显然程序员要多花些时间,验证自己的修复工作是否真的完成了,并努力避免新的缺陷出现。
3 P3 K% ]. n( [0 A2 b5 s" j5 t2 i2 M
当然,这并不意味着程序员可以花无限多的时间来检测。花很多时间检测,就赶不上测试团队的下一轮全面测试了,就得等再下一轮甚至更后面的全面测试来复核。
1 O# i% E. S& f0 D& ?
在本质上,此时是活动间依赖关系决定项目剩余时长。当程序员数量足够多,以至于测试团队发现的所有缺陷都可以立刻找到一个程序员来应对时,就构成了这样一种模式:在每个循环中,一个程序员修复一个已有问题,适当质量保证工作,再在提交和归入基线后,由测试团队进行全面深入的系统测试。每个循环均使缺陷数呈几何级数下降,趋向于收敛。5 P) ~0 A8 Q0 p, t; U( f$ g

1 w4 B5 ~" e. E+ T
这有点儿像原子核衰变。要衰变多久,取决于半衰期①和打算衰变到什么程度。在这里,如果打算“衰变”到的程度是给定的,那么关键就是“半衰期”,也就是“衰变”的速率。“衰变”的速率取决于每个循环剩余缺陷比例,比如 1/4,和每个循环时长,比如 1周。而每个循环的时长由程序员花费的时间,平均等待及进行狭义集成花费的时间,平均等待及进行全面系统测试花费的时间共同决定。若程序员花过多的时间在提交前的检测上,比如昀终令每个循环的时长变为过去的三倍,为3周;但仍有缺陷的可能性只降为以前的 1/2,即 1/8,那么“衰变”的速率就会变慢,就不值得。
6 z* C7 B! [) \" d6 _& [9 h* k# s
程序员资源丰富,测试人员资源丰富,这是两种理想情况。在现实世界的具体项目中,在稳定化阶段的早期,缺陷削减的速度常常主要受程序员数量的限制,大量的缺陷等着程序员来修复。若是这样,此时应该更重视程序员的综合工作效率。而在稳定化阶段的后期临近发布时,会变得主要是半衰期这个因素在起作用。此时应该更重视程序员的提交质量,以减少循环次数,早日收敛到可发布的质量。5 _/ d0 T- T* J- W4 c9 G: l% U

8 a. U* c) B  l/ ^' S' B: J2 M6 L2 O$ v
在项目末期,常常对需要修复哪些缺陷有越来越严格的控制:为缺陷跟踪系统里的每个缺陷记录标注缺陷严重等级、重要性、紧急程度等属性,要求程序员把主要精力放在等级高的缺陷上,也可能干脆直接标明哪些缺陷必须在本次发布前修复。在项目的昀末期,甚至可能控制程序员的提交本身,只有修复特定缺陷的少量改动,才允许提交,进入集成分支。这些方法都是为了让程序员把有限的精力集中到本次发布所需要的缺陷修复上。同时,减少因修复不必要修复的缺陷而引入新的必须修复的缺陷。这一点在“衰变”即将结束,项目临近发布时特别重要。

: _0 c7 K( y( S; E/ Y1 P6 S4 q" T1 ~' u+ [/ H( b+ ^0 w+ @6 ?( ?& E0 V
①这里所说的增量测试,是指测试昀近所做的改动相关的功能,测试昀有可能引起问题的部分。详见第4.9节,第 7.10节。5 d9 H/ q6 Z8 s
①这里所说的“程序员提交的质量”,严格地讲,应该是程序员提交并(可能)经过测试团队增量测试后的质量。在第三阶段,除了全面深入的测试外,还有增量测试。详见第 4.9节和第 7.10节。7 T4 A) j# h9 A
①半衰期( half-life)是指某种特定物质的浓度经过某种反应降低到剩下初始时一半所消耗的时间。人们一般在谈论放射性元素的衰变、药物在体内的吸收和代谢等话题时,使用这个名词。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-9 11:26:39 | 显示全部楼层
4.3 为了让后续工作更顺畅
8 m* g; \9 ]2 g$ y8 l3 ?% O  E7 D8 Y
在前两节,我们是以将来软件对外发布时,它需要具有的一定的软件质量为目标,从发现和解决问题的效率这一点,考察提交前应有的质量。下面我们进一步考虑另一个因素:程序当前质量越高,则后续开发和集成工作就更顺畅。我们将据此补充和修正前面的结论。
$ h/ c' P/ j% v3 H" o: h
我们知道,那些挡住了很多后续功能的展现的问题,其对程序员开发新功能和测试人员测试的负面影响很大,有很高的修复价值。而这些问题,通常也是严重的问题,对程序的昀终使用者有很高的修复价值的问题。同时,它们常常还是容易发现的问题。容易发现,而修复价值又大,那么消除它们就是特别有效率、特别值得做的工作。我们就要尽力确保这样的问题不会流传到广大程序员或测试人员手上,因为越多的人遇到,项目的损失就越大。也就是说,要么在集成的第一阶段,要么在集成的第二阶段,总之在基线产生之前,要尽力消灭它们。
# v& b( e: N  ^% ]3 G$ i8 ?4 P1 f$ @; j4 E1 S3 _- o
早发现,早解决,容易解决。这个道理也适用于对付严重问题。如果比较容易就能在集成的第一阶段查出这样的严重问题,那就不要拖到集成的第二阶段,不然解决问题的成本会高。
5 f$ J- O- i$ u" Z8 k( V3 J
另一方面,在提交前到集成的第二阶段,是要汇聚各个程序员的改动。在此阶段对付问题,要让所有依赖于已提交但尚未进入基线的各个代码改动的工作处于等待状态。在对项目完成时间的影响上,这个代价比第一阶段时对付问题要明显高些。
6 ~$ J! c" Q) x, Q( ^6 R" F# Q; F/ f4 F! D
更何况,在第二阶段对付问题,容易形成瓶颈,阻碍更多的后续开发活动。因此我们在集成的第一阶段就要尽量发现和消灭这样的严重问题。再考虑到有时程序员是从集成分支末端而非昀后一个基线取得源代码,因此我们更有理由在集成的第一阶段就要尽量发现和消灭这样的严重问题。

. s3 Y) k1 s" k& v' E; B9 y发现和消灭相对不严重的问题是有必要的,早发现,好解决。这是前两节讲的内容。而与此相比,我们要更重视发现和消灭相对严重,容易耽误后续开发和质量保证工作的问题,尽可能的不让它们跑到基线里,甚至不要跑到集成分支上。! N+ u7 l( X5 |4 X- _
/ s* g+ I+ l7 `2 H0 k
在什么情况下应该调节当前集成策略,在提交前加强对严重问题的检测呢?如果程序员经常因为已有程序质量不高而耽误工作,他们自己为此很头疼,那就和他们一起讨论,要不要在提交前加强对严重问题的检测,避免提交有严重问题的改动。

: _3 `! h8 _) f4 Y- H如果测试人员测试时经常因为基线中的严重问题而无法深入测试,造成测试资源不小的浪费,造成项目时长的拖延,那么就要考虑让程序员在提交前做更多的测试,至少要保证基本的质量。
$ d0 f# f+ x# s5 s7 ^1 G/ I( E' k% N6 v: J
如果由于程序员的提交中经常带有严重问题,而导致集成工程师当前的工作负荷很大,形成瓶颈,经常耽误整个项目的进展,或者他为了减轻压力,不得不遗漏很多比较严重的问题到后续工作中,那么就要在提交前加强严重问题的检测和修复。
/ D. |+ Y4 Y& H9 C2 W& Y; H0 ^  x- y' O2 k5 Q
反之,如果没有这些现象,从统计上看,提交的严重问题不多,到集成的第二阶段时基本能对付,那就不必在提交前再增加很多测试用例或者其他检测方法。毕竟,更大的检测力度,意味着更多的资源、成本和更多的项目时长,是有代价的。

% j* z: R) q4 P5 C% q" Q8 o7 k一般来说,对于很多人一起开发的大型项目,要花费更多的精力来避免提交严重问题。因为在这样的项目中,每个人开一条小缝,这么多人的遗漏,就会汇聚成问题的洪流,让集成工程师招架不住。在第2.5节我们聊过这个事儿。4 q' C) I: w! ^) ^) ~1 J
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-9 11:31:11 | 显示全部楼层
4.4 提交前检测方法

8 i1 ^" Y+ F4 k: A* o# D
在集成的第一阶段,有多种检测方法备选。在第1.7节我们曾经介绍了一系列检测手段:版本合并、源代码检查、构建、运行时测试四大类。那么,应该选用哪些检测方法,如何有效使用呢?
: K6 ~, |3 {5 Z: B9 l- }
在讨论具体检测方法之前,我们先要明确一个重要的原则,那就是,检测要尽量围绕本次改动,而不是泛泛地检测。本次改动,在改动相关的部分可能引入了缺陷,与改动相关的功能,在统计上其缺陷密度较大,发现单个问题的成本较低。同时,由于程序员对该地区熟悉,检测起来也比较有效率,能够更有效率地发现问题。在解决问题的时候更是这样,程序员解决自己的改动中的问题和附近的问题,其效率比较高。因为只有在这种情况下,程序员才比较熟悉相应的代码,才能快速地解决。6 c6 A2 |$ o, ^9 A. u
" v- Q* K3 c& c4 g
没有必要在提交前刻意去搜索并非本次改动带来的问题。与在集成的第三阶段做这样的事情相比,在此时检测,效率很低,因为不止一个程序员要检测相同的内容,为什么不放在第三阶段一次性完成呢?而修复工作同样效率不高,因为要修复的,并不是自己熟悉的改动。总之,一项检测工作,它越有针对性,就越值得在提交前完成,反之就要考虑是不是应该放到集成的第三阶段或第二阶段。

, i8 e" v! G- L7 B' s! }除了这个重要原则外,还要考察具体某个检测方法在具体情景中的工作效率,考察它发现问题的能力。如果要增加的检测方法很费时间,而发现的问题又很少,或者发现的问题绝大多数已经被其他已有方法发现,那么就不值得增加该项检测方法。而如果新方法跟某个已有方法发现的问题差不多,但明显更省时或更省成本,那就值得考虑用新方法替换已有方法。而如果某个提交前采用的检测方法,能够有效率地发现不少在将来系统测试时很难发现的问题,那就特别值得考虑。
$ T- W& |, ]; b# W2 u
. T% k7 A. o( o+ O2 ]( O( E2 C4 M
下面我们按版本合并、源代码检查、构建、运行时测试四大类,分别讨论具体的检测方法。

' x# \8 D8 s1 y% d/ E* N; R首先讨论版本合并。如果进行了从基线或集成分支末端到工作区的更新操作,那么版本合并当然是被用到的检测手段。更新操作,其本质是合并。在版本合并的操作过程中,合并冲突得以暴露和解决。随后,更多的合并所导致的问题,将通过其他检测手段发现。
7 C, h% m3 J/ k4 l
. }3 U5 i& k, C* \6 X1 s" K
至于是否需要更新工作区,应在何时更新工作区,我们将在第 7章讨论。

8 r5 |4 `' S4 G3 X从工作区到集成分支的提交操作,其本质也是合并。在这一过程中,新的合并冲突得以暴露和解决。但合并所导致的编译构建问题、运行时的问题,就只能流到集成分支上了。
3 ?4 v  p' i2 c, Q3 U. O  U# u0 y. ]. \
不少版本控制工具①由于其本身的设计机制,它禁止程序员在有(潜在的)代码合并冲突的时候提交。在这样的工具里,必须先用集成分支的昀新版本更新工作区,再立刻提交。也就是说,提交时要解决的代码合并冲突,转由更新时完成。

) l7 h4 F, [6 k# I+ v第二大类,源代码检查。这一大类中,代码自查显然是有效的,就好像考试的时候,做完题要自己检查一遍。
/ k. Q5 f9 f7 H
而同行评审也是针对本次改动进行检查的有效的方法,推荐使用。它甚至能检测出不少在将来系统测试时也不一定能暴露出来的缺陷。
+ p% D1 C* D' y3 @8 _4 I
但也要注意评审的效率。比如,引入过多的同行进行评审,边际效用递减,而成本却显著增加。特别是,如果使用开会的形式逐项讨论发现的问题,那么人多的情况下,就可能难以找到大家都合适的时间,评审可能会一拖再拖。又如,由另一个站点、另一个时区、持另一种自然语言的同事来评审,由于工作时间不同、沟通效率低,常常会显著延长通过评审的时间,影响项目的进展。这需要审慎地权衡。
+ }( \, N8 G# P
! P( k( f% _1 P" u
近几年,类似 Gerrit这样的基于网络的代码评审工具日渐流行。这样的工具通过网页形式展现待评审的改动,并且可以让评审者在(可能)有问题的改动旁边加上评审意见,而改动代码的人也可以用此方式与评审者交流。显然,这对于由分布在世界各地的志愿者一起完成的开源项目来说,是很大的方便。

4 E2 z. o4 b: t( M0 y+ G而传统的评审方法,先由评审者各自查找并记录发现的问题,再开会逐项讨论的方法,也有其优势。一对一的交流沟通,面对面是昀有效率的方法。因此,当评审人数少,且都在一个站点时,仍值得使用这种传统方式。而当有些评审者因不在该站点等原因,不便面对面沟通时,可利用前面所说的评审工具做辅助。总之,两种方法,因地制宜,相互配合,能够发挥昀好的效果。, a! s: j! o1 m; X" p

7 b' W9 B# X  S0 I; [* d! F0 L1 W) ?
一般来讲,应该等所有的评审意见都被妥善处理后,再提交改动到集成分支。但是如果由于种种原因,评审效率较低时,也可灵活处理。比如,当改动的质量已经比较高,而收集全部反馈意见尚需时日时,可以考虑不必等待全部的反馈意见就提交到集成分支,陆续到来的反馈意见可以在后续的提交中再体现。
7 o' X# D* d) L/ o* k# M" }$ q% f( u
也可以考虑把已经具有一定质量,但尚未通过评审(或其他检测方法)的改动,通过“胡志明小道”①送给急需它的程序员(们),让他们基于未通过评审的改动A,开始依赖于这个改动 A的新的改动 B。
2 U# C$ A/ u- a: o5 g9 @; x9 y1 g
GitSubversion都是这样。4 v, {+ u$ {. ?" ^- ^5 Z
①胡志明小道是越南战争期间,胡志明领导的军队在崇山密林中修建的通往南方前线的秘密运输通道。

: J1 O9 }; p: b$ d8 c, W
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-9 11:39:43 | 显示全部楼层
如图 4-1所示。- d# c2 ~% Q7 t, J9 U% O) m9 [  F
$ _" a% {  V0 J. w
将来这个改动A提交到集成分支后,再同步新的改动 B,让新的改动 B基于集成分支的新的末端(或包含了A的基线)。如图 4-2所示。
1 `4 f2 Y! K8 j* L# N

% e9 N* N) E0 @8 y0 V  \1 x与同行评审相比,结对编程可以让评审者被评审者编程过程中,并行地思考,实时地提供反馈。把串行变成并行,因此可以减少等待,降低项目时长增量。如图 4-3所示。; C- g: ~0 w" u9 G, x4 s3 ~
' C+ p& y) q( x
9 J* \$ h% R: k$ B
源代码检查这一大类中,自动的方法,也就是静态程序分析,与人工的代码评审相辅相成,发现人工代码评审容易漏过的问题,并保证程序遵循已制定的各项规则,值得使用。但要注意,受具体技术的限制,在一些情形下,静态程序分析无法针对本次的改动,进行小范围的检查。它必须对程序全部源代码进行检查。如果因此造成检查时间格外的长,比如数个小时,那么就要重新思考是否要在集成的第一阶段使用它了。可以考虑把它挪到第三阶段,多攒点问题再检测,以期待一次多检测出一些问题,并显著降低对项目时长的影响。

5 C1 r$ f: r) F( U% F. b+ c+ r当然,这意味着分析和解决静态程序分析所发现的潜在问题的成本将有所增加,因为要再走一遍改动代码再检测再提交的流程。此外,由于潜在问题流入集成分支,可能将烦扰开发工作和质量保证工作,需要权衡。5 n! u: C- Z% f" h- @8 `% ~& @, G
; e) Q2 Y1 M; w* B8 {% m  E3 C8 z
第三大类检测工作是构建。显然,构建是必不可少的检测手段。因为不进行构建,就无法进行测试。并且,如果源代码中尚有令构建失败的问题就提交,将严重干扰后续工作。

8 ]2 e4 z. R. k) S$ k% f程序员通常采用增量构建①来大幅缩短构建时间。增量构建尽可能利用已有的构建成果,只构建与上次构建时相比,源代码的改变所导致的必须重新构建的部分。我们说过,检测要尽量围绕本次改动进行。增量构建体现了这一点。当然,增量构建可能不够可靠,增量构建失败不一定是因为源代码本身有问题。如果这种情况过于频繁地发生,严重干扰程序员,那作为权益之计,就要重新考虑全量构建了。同时,要寻找构建方面的专业人员,解决增量构建不稳定的问题。6 X8 [. v$ [7 O! d5 Q4 d! D

4 i% `+ x, ?! `. h! Z
第四大类,测试。测试这一大类当然也是必不可少的检测手段。测试要围绕本次改动进行,才能有效率地发现和解决问题。适当的单元测试,是很有效率的检测方法。并且,它能够轻易查出一些系统级测试不易覆盖到的问题。
! z  W( `5 d; T% b+ j
单元测试有清晰的边界。本次改动了哪个或哪些模块,就做针对哪个或哪些模块的(一部分或全部测试用例)单元测试用例。本次改动没有碰的模块,就不用做该模块的单元测试,因为测试结果跟本次改动之前比,不会有任何变化。
+ v# [+ O+ d- A
: V: A' {- T! e9 |. H. ^% V
此外,不仅要做模块级的单元测试,一般还要做更高层级的测试,直到测试系统整体表现出来的功能符合预期。我们将在第 5章详细讨论测试的层级。

2 P+ _0 K0 i" K6 ?) Q& h: ]除了测试功能,对于可能将给性能带来较大影响的改动外,也要考虑在提交前就有针对性地测一测性能。* E. W3 ]4 `* h% h; D3 f

9 l* _4 }# B8 D: }' r7 ~! Q
要格外重视确保程序不会出现严重问题,因为提交严重问题,将严重干扰后续工作。因此针对可能出现的严重问题,要做好相应测试,即便是预计这样的严重问题发生的可能性不高。为防止这样的严重问题,应该做一些粗略测试,确保程序具备基本功能。
$ @7 }/ x" l8 I4 o& X7 s
这样的粗略测试,其测试用例的挑选,应基于以下原则:首先,测试应该是系统级的,而不是模块级的。因为测试的目的是保证程序外在的基本功能。其次,粗略测试是为了确保那些基本功能,因此针对细节的测试不在此列。昀后,即便是不太可能被影响到的基本功能,也应该测一测,因为万一出问题,影响很大。当然,几乎肯定没有问题的基本功能,也就不用测了。7 ^) X9 h  `8 V+ j& f. ]( i1 b

+ N- s# M0 x& k1 p7 L0 H
有些项目中,强制要求提交前必须进行一个固定的测试集的检测,确保提交不会出现测试集所覆盖的严重问题。这是否合适,也要依实际情况而定,关键是检测的效率。如果这个测试集挺大,内容不少,纯人工测试,而某次提交跟这个测试集里绝大部分测试用例都没什么关系,几乎不可能因为这个提交而出问题,那使用这样的固定的测试集,就不合适。比如修改手机软件中某个游戏中的字幕提示,就几乎不可能影响打电话、发短信等功能。硬性规定进行这样的测试,并无意义。

  K' Z, s3 @2 ?) K' I一般来说,自动测试是件好事情,因为一个自动测试用例一次写成后,可以反复多次使用,每次成本很低。这样,就可以做更多的测试,让提交质量更有保证。举例来说,在某个改动之后,要进行针对所在模块的单元测试。在过去,由于测试是人工的,有些不太可能出错的测试用例,就被权衡下去了,不测了,有问题只好等集成的第三阶段再说。而现在,测试是自动化的,因此很轻松就把该模块上的所有单元测试用例再运行一遍,确保没问题。这使得在不增加甚至减小了提交前检测成本的基础上,让提交质量更高,进而减少了多日后在第三阶段暴露出问题时,要付出的代价。
" z; G6 \/ f( s$ H, O5 a2 c
! }6 w8 n8 J+ i! N1 s0 [, s
另一方面,由于自动测试用例反复运行时的低成本,就可以在每完成很小的一块改动后,就进行与之相关的全面测试,然后提交。包括自动测试在内的各种自动化,能够有利地促进频繁提交,持续集成,进而享受持续集成带来的好处(详见第7章)。
然而自动测试也有其弱点,自动测试用例的编写需要一次性的投入,这个投入可能不低。有些自动测试需要频繁地维护,投入也不小。因此,有些测试适合自动化,有些就不适合。在第8.3节我们将详细讨论。举例来说,单元测试的自动化,已经比较成熟,有比较广泛的应用。
: _8 r, R) n9 Y9 B
在测试这一大类中,测试驱动开发( TDD)正在获得越来越多的理解和支持,在第 1.7节我们已有所介绍。) i3 H7 y9 R$ p
/ i: {: A% ^! P: F4 i- V
①详见第 8.4节介绍。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

SCMLife推荐上一条 /4 下一条

QQ|小黑屋|手机版|无图版|SCMLife.com ( 京ICP备06056490号-1 )

GMT+8, 2018-7-22 01:45 , Processed in 0.076308 second(s), 8 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

快速回复 返回顶部 返回列表