在最近几次与客户面对面的交流中,我有幸分享了我们团队如何在日常工作中进行敏捷软件开发。毫无疑问,这在中国开发人员中是个热门话题,我也想利用博客这个平台与更多的读者进行书面的交流。当然关于敏捷开发利弊得失的争论有不少,而相关的开发模式也分成了TDD (Test Driven Development), Scrum, XP(eXtreme Programming)等流派。就我个人而言,一个团队是否严格遵循某种既定的敏捷方法并不重要,但一定得选择并采用一种(或几种)最适合自己开发团队和开发项目的。我认为重要的是团队能否遵循《敏捷软件开发宣言》所涉及的12条原则。
在我深入这一议题前,请允许我介绍一下团队:我们属于微软开发工具部(Developer Division,以下简称DevDiv),这个部门拥有几千名软件工程师,核心产品Visual Studio系列的用户从软件开发爱好者一直到大型企业里的专业开发人员及架构师。
大量而且复杂的依赖关系、代码改动、紧迫的开发周期等因素使管理软件开发生命周期并按时发布高质量的Visual Studio产品极具挑战性。为了降低风险和复杂度,DevDiv在开发Visual Studio 2008过程中采用了功能分支架构(Feature Branch Structure)和功能小组模型(Feature Crew Model)。其实这一方式之前已在Office开发团队的实践中取得不错的效果。它的最大好处之一就是使负责某个功能的团队在独立开发过程中有更大自由。由于篇幅所限,在这篇博文中我将侧重介绍我们团队是如何进行敏捷软件开发的。
我们团队负责Visual Studio系列中的Visual Studio Team System Architecture Edition,帮助架构师、运营经理及开发人员以可视化方式构造面向服务的解决方案、降低(软件产品开发的)复杂度。目前我们已开发了基于UML和DSL几个建模工具。这基本上是一个全新项目。
从产品开发来看,我们属于全球分布式开发,团队分布在三大洲的四个城市,包括亚洲的上海,北美洲的雷德蒙和夏威夷,以及欧洲的剑桥。为了尽可能减少分布式研发对团队间交流所造成的障碍,我们尽量使功能小组的成员集中于一地。基本上,每个功能小组的核心部分都在某一个城市完成,在其他城市可能会有个别工程师参与相关开发。例如,我们在上海就有一个功能小组,其他一些工程师在雷德蒙的公司总部工作。但有时,基于客户场景的特殊要求,我们也会将一个功能小组拆分成若干个,由多个城市的团队同时开发。
在本文后半部分和之后的系列文章中,我所谈及得敏捷软件开发流程都是同一个功能小组所遵循的,即是我们中国团队所遵循的。
我们中国团队主要负责开发基于UML的核心图形设计工具,包括即将发布的Logical Class Designer, Use Case Designer。此外,我们还负责在项目中提供建模元素视图功能的Model Explorer。我们所采用的敏捷开发方法是Scrum的修改版。就如我之前提到的,我们认为敏捷开发方法和技术没有哪一种是万灵丹,适合自己才是最好的。我们的团队中已有两位工程师参与过Scrum实践,也因此促成我们最终选择了它。
下面是一个我们敏捷软件开发流程的概要视图:
产品待开发事项(Product Backlog,视图的左上角)可以被视作一份这个团队以优先级排列的、需要完成的功能需求单:来自相关产品利益相关者(Stakeholders)对产品提出一系列高端要求。例如,我们最初的要求是为客户增加逻辑级(更抽象的)和物理级(更靠近代码)建模提供支持,由此衍生出了高端功能需求,诸如开发在逻辑级方便客户生成逻辑模型、兼容UML的关系图和开发帮助创建无力模型的DSL关系等。然后我们会对将要支持的UML关系图种类按优先级进一步分解(UML共有13种不同的关系图)。产品利益相关者的意见会驱动整个优先级选择过程,最终我们得出五个最重要的关系图:Logical Class Diagrams, Use Case Diagrams, Sequence Diagrams, Activity Diagrams 和Component Diagrams。于是,团队依据当时对产品和市场的了解,以故事标题的形式完成一份产品待开发事项。无疑,整个开发工程中一旦要求发生变化,也会导致需求排列优先级的变更。
在与客户的交流中,我被问得最多的问题之一是是否需要在敏捷开发过程中创建架构模型设计。和咨询公司一样,我的答复也是:视情况而定:)。围绕Big Design Upfront (BDUF), You Are Not Going to Need It (YAGNI)以及让团队在开始实施新功能时“重构”现有的代码/设计等所存在陷阱的争论也不少,其中有不少值得借鉴。尽管如此,我坚信设计初期存在这么一个阶段可以尽责地做架构设计以生成高端架构。例如,你打算建一个网上贷款流程的应用程序,你可能需要决定在这个架构里有几层。当然,能有这样一个基于最初要求的,并可能随着项目进展有所变更的架构是很重要的。在我看来,重构在敏捷开发中有其重要地位,但是如果是变更基础架构的“大重构”代价就太大了。如果大家感兴趣,我将在之后的文章中与大家探讨架构在敏捷软件开发过程中所扮演的角色。
在我们团队所遵循的敏捷软件开发实践过程中,我们的项目被分解成类似Scrum的若干个四周sprints或迭代开发周期。尽管没有测试驱动开发(Test Driven Development)或结对编程(Pair Programming),但我们的开发人员会编写单元或签入测试(Unit/Check-in Test)来检查功能,开发和测试工程师也会在一起调试、调查或评审某个特定问题和变更等。我们还会使用极限编程(eXtreme Programming)中的使用者故事(User Story)模式。事实上,我们的产品待开发事项和每个迭代周期中的待开发事项(Sprint Backlog)都会以故事的形式被追溯。这些使用者故事就是描述一个系统的最终用户会如何使用某个特定功能。
通常,我们都会在一个Sprint阶段的最后一周计划下一个Sprint阶段:通常负责某个功能的团队(主要是主管们)会依据团队需要侧重的故事来进行由下至上的计划;然后再与产品利益相关者对项目中故事优先级的规划相协调;协调后的需求优先级清单一般会在Sprint的第一天完成。团队于是评估这些使用者故事,并完成设计初稿、实施成本,确认故事完成的标志。依据这个设计和成本,团队将承诺这个Sprint将完成的内容。
今天先谈到这里,下一篇博客我将谈谈我们团队在Sprint阶段的运作。
祝各位读者新年平安、喜乐!
Ramesh Rajagopal
Visual Studio Team Architect 中国团队经理
翻译:郑洁
校译:钱量