技术开发 频道

“XP 精华”重访,第2部分

    至于风险,请考虑一会儿项目为什么会失败。其中一个主要的原因就是太依赖个人英雄。如果承担项目的英雄意外阵亡,那么您的项目可能就完了。结对的本质是要散播知识。结对的两个人应该经常切换角色。如果结对的两个人的角色都很固定,他们就会被困住。

    尽管有不少人推崇结对,也有很多强有力的观点来证明结对,但大多数开发者仍讨厌这种思想。或许这是自尊心的问题。我相信,大多数开发者在内心深处都想当英雄。结对使得这一点几乎不可能实现。就象我在 Extreme Programming Applied: Playing to Win(请参阅参考资料)中所写的那样:

    每个人都可以坐在其他人的旁边,并时常不经邀请就发表一些意见。许多人可以完全投入并尽力使结果更好。但真正理解结对的人知道那意味着要去喜欢另一个人。
    就象我在那本书中所说的那样,我讨论的那种爱是通过行动表现出来的,不是浪漫的那种。如果您爱另一个人,您就会尽力去发现他的优点,并帮助他成长。您将是耐心的、亲切的、不嫉妒、大方的、谦逊的且有礼貌的。这种热情的人与人之间的关系,即使是只几个小时,大多数人也不感兴趣,而开发者毕竟也是人。这是一种激进的思想,并不适合每个人。但它也可以为您的职业生涯带来最有益的经历。

    重构(未改动)
    重构是一种改进代码但不改变功能的技术。XP 团队在重构时毫不手软。开发者进行重构的两个关键时机是:在实现一个功能之前和之后。开发者设法确定更改现有的代码会不会使实现新功能更容易。他们查看自己刚写好的代码,看看有没有办法简化它们。例如,如果他们看到有抽象的机会,他们就会进行重构,从具体的实现中除去重复的代码。这里要注意的重要一点是,您应该要么设计并编写新代码,要么重构现有的代码。不要试图一次进行这两种工作。

    虽然 XP 建议您应该编写可能运行的最简单的代码,但它还建议您应该不断学习。重构使您能把自己学到的东西结合到代码中去,同时又不会破坏测试。它使您的代码保持简练。这意味着代码存在的时间会更长,为后来的开发者引入的问题更少,并为他们指引正确的方向。

    重构的目的是改善现有代码的设计。团队应该拥有程序员测试和客户测试的自动化套件。前者应该在任何时候都通过,而后者应该达到客户所要求的程度。运行测试。重构代码。重新运行测试。有程序员测试失败了?修正它们。有“必需的”客户测试失败了?修正它们。如果您无法修正它们,请逆序恢复您刚刚试过的重构。如果不进行测试,修改代码就会象猜谜一样。重构时,如果代码崩溃了,测试将告诉您。

    集体所有权(映射到集体代码所有权(collective code ownership))
    团队中的任何人都应该有权修改任何代码来改善它。每个人都拥有全部代码,这意味着每个人都对它负责。这种技术可以让人们对代码片段进行必要的更改而不用经过各个代码拥有者个人的瓶颈。每个人都负责这一事实消除了无代码所有权所带来的混乱。

    说每个人都拥有代码并不是说无人拥有代码。没人拥有代码时,人们可以随处进行破坏而不必负任何责任。而 XP 说,“如果是您破坏的,应该您来弥补。”团队应该有一些必须在每次集成之前和之后运行的程序员测试。如果您破坏了某些内容,您要负责进行修补,无论它位于代码的哪一部分。这需要极度严格的纪律。

    我已经注意到有些团队成员根本不执行这个方法。一想到有人会弄乱“他们的”代码,他们就受不了。如果想成为一个 XP 团队的一部分,您就必须共享所有代码的所有权。如果您不那样做,这个小组最终就会碰壁。代码的某些部分将脱离限制,这使得系统很难进行更改 — 这种情形是我们要设法避免的。如果某个人这样做了,团队需要指出这一点并鼓励他改变。如果他拒绝改变,就强烈建议他改变或离开。如果他仍然拒绝,那就告诉他走人。不要在这一点上妥协。

    持续的集成(未改动)
    每天多次向系统集成新的更改,并自动重新构建整个系统。运行了所有的测试后才能发布更改。如果一次测试失败了,您有两个选择,修正它并集成,或者不集成。只要有一次测试失败无法修正就意味着您不应该进行集成。

    持续的集成并不意味着每秒都要集成,但它的确意味着您应该尽早并且经常集成。每天集成是不够的。在每天的八小时时间内,我开始有了这样一种讨厌的感觉,我是不是还没有至少每隔几个小时集成一次,是不是没有集成更多次。这听起来会引起许多人的恐慌。再一次,测试应该赶走这种恐惧。测试告诉我集成是否“工作”,是否可以安全地发布给小组的其他人。

    YAGNI,或称“您将不需要它”(映射到简单的设计(simple design))
    在“XP 精华”中,我和 Chris Collins 写道:“XP 的诽谤者声称这个过程忽略了设计。”他们仍然在这样批评,他们依然是错的,但我认为 XP 迷们有时太急着针对这种异议进行辩解了。

    这种异议真正要说的是人们对紧急设计(emergent design)这种思想感到不舒服:允许系统设计不断出现变化,而不是开始时就设法把一切确定下来。确定一个方向,标出一些重要之处和转折点,然后开始进行。您可以在学习的过程中做一些调整。不喜欢这种方法的人会把它曲解为不守纪律。实际上,这是在目前的经济情况下最现实的开发方法。

    典型的重量级方法建议您做的不过是提前完成大部分琐碎的设计任务。这就好象是拍一张静态的地平线的照片,静止不动,然后尝试画一张如何到达那里的完美的地图。如果需求是固定的,那么这算是一种好方法。如果您在刚开始时就知道系统需要做什么以及它需要如何做,您就可以预先进行大部分(如果不是全部)的设计工作。但实际上,大多数开发者都在探索他们以前没有充分解决的问题,或者正在实现以前还没有尝试过的解决方案。目前,大部分系统都是为在不断变化(而不是每十年才变化一次)的市场上进行竞争的商业设计的。

    在这样的环境下,需求随时都会发生有影响的更改,需求的稳定只是个白日梦。这意味着大型的、提前的设计是不合适的。刚开始时,您根本无法知道最终您将在哪里结束,甚至不知道想在哪里结束。您最好是确定一个大致的方向,并在进行的过程中做一些小的、经常的调整以满足不断变动的目标。XP 要求每一步都尽可能简单,这样就可以按必需的频度改变方向了。我们一直设法使用在任一点都可能工作的最简单的设计,并根据不断出现的实际情况改变这种设计。

    按照 Kent Beck 的说法,可能工作的最简单的设计是具有下列特征的设计:

    运行所有的测试
    不包含重复的代码
    清楚地表明程序员对所有代码的意图
    包含尽可能少的类和方法
    要求简单的设计并非暗示所有的设计都将很小或者无足轻重。只是让它们必须尽可能简单,并且仍能工作。不要包含不准备使用的“额外”功能。我们称这样的事物为 YAGNI,表示“您将不需要它(you aren't going to need it)。”换句话说,在设计时不要考虑您可能需要的内容。在下一次反复中,您可能会发现您根本不需要它。相反,您只需编写测试,然后编写足够的代码使其能通过测试。通常您只需做这些设计即可。应用 YAGNI 原则并不表示让您永远不要提前考虑事情,但的确意味着您不要考虑得太远。

    方法协作
    所有的 XP 方法在一起工作并互相补充。对于程序员方法尤其是如此。然而,某些程序员方法(例如,测试推动的开发与结对程序)可以独立施行,而其它方法(重构、集体所有权、持续的集成与 YAGNI)“依赖”程度较大,需要其它方法就绪它们才能够工作。

    就象我以前所说的那样,重构而不进行测试我会感到不安。同样,没有测试告诉我是否破坏了某些内容,我就会发现集体所有权非常荒唐,持续的集成也是不可能的。至于 YAGNI,我认为如果没有测试推动您实现那种简单性,它不可能使您的设计简单。如果能够根据将来可能发生的错误来构建,这种诱惑实在难以抵挡。有趣的是,我注意到这些依赖性方法中的大部分方法都依赖于已经做过测试。(或许方法是特别重要的。)

    虽然大多数方法可以独立施行,大多数都不可以。如果您有了一些测试,您或许能够进一步零零碎碎地采用更多其它的测试,但您为什么要这样做呢?把方法放在一起使用,让它们互补可以使团队取得令人吃惊的成功,并且可以开发出更好的软件。如果您认为自己不会喜欢某种方法,您可以忍住“绿蛋与汉堡(Green Eggs and Ham)”的诱惑并设法坚持一段时间。您可能会感到惊讶。如果您尝试过了某种方法,但仍不喜欢它,您可以不用该方法去尝试别的方法,但我认为您的速度和结果会因此而受到负面影响。

    我仍坚持原来在“XP 精华”中的建议:整体大于部分之和。您可以实现单个方法或者一个小型方法子集,比不使用任何方法得到更大收益。但您只有在实现所有方法的情况下才能获得最多的收益,因为它们的力量来自于它们之间的相互作用。刚开始时可以把书本上的内容作为基准来执行 XP。一旦理解了方法的交互,您就拥有了让它们适应您自己的环境所需的知识。请记住,“进行 XP”不是目的,只是实现目的的一种方法。目的是快速开发出上好的软件。如果您的过程有了一些变化,已称不上是在进行 XP,但结果仍能让您战胜自己的竞争对手,那么您已经成功了。

0
相关文章