Freigeben über


功能小组模型的过程与质量控制

——Visual Studio开发团队的敏捷实践经验分享(二)

    年初,应InfoQ中文站邀请,Ramesh Rajagopal (Visual Studio Team Architect团队的敏捷开发系列文章的作者)和他的团队在“敏捷Scrum实战营”活动期间接受了InfoQ中文站的邮件采访。本文由滕振宇先生根据Ramesh的回答和团队的翻译编辑而成。如需转载,请先与editors@cn.infoq.com联系。

    原文地址:https://www.infoq.com/cn/articles/vs-agile-practice-part2

InfoQ:在Visual Studio开发团队中,团队一般都监控哪些过程改进方面的数据?Visual Studio 2010支持对哪些数据的监控?

    VS 2010 Ultimate版本本身自带了一些图表和报表。 我在下面列出其中的一些:

  • Team and Individual capacity charts(团队和成员生产力图)
  • Burn down charts(燃尽图)
  • User Story progress(用户故事进展)
  • Task progress(任务进展)
  • Builds status(构建状态)
  • Code Coverage(代码覆盖)
  • Code Churn(代码变化)
  • Issue Trends(问题趋势)
  • Bug Trends(缺陷趋势)

    在这里着重介绍的是一个Code Churn(代码变化)度量。这是一个能够说明系统某一部分代码的变化程度的度量。敏捷开发鼓励通过重构,演进式架构的方式来开发系统,因此不可避免的系统会有些改动。但是我们还是可以通过这个度量去观察我们系统的稳定性。帮助我们发现问题。

    VS 2010 Ultimate版本中另一个很棒的功能就是仪表板(dashboard)。这些仪表板被组织在一起,它们在一张视图上展示了一组相关的度量数据(metrics)。这帮助功能小组成员交流各自负责功能的重要信息。例如:燃尽图仪表板包括任务燃尽图、任务进展、用户故事进展、7天问题趋势以及当前待处理问题。质量仪表板包括测试计划进展、构建状态、代码覆盖、代码变化等。

    敏捷的一项重要原则就是项目进展和问题交流的透明性,只有这样才能保证对问题做出及时调整。功能小组可以根据需要采用不同度量数据。提醒一点:决定采用哪些度量数据以符合团队和产品相关人员的要求,需要一段时间去体验。因此,如果你对敏捷不是很了解,或者你正在带领一个新团队,建议你选取所有的或者大部分敏捷度量数据,然后逐步去除那些对团队不必要的信息。

    例如,在我们的项目中,某些功能团队在一个Sprint中使用燃尽图来跟踪进展情况。有些则不使用燃尽图,因为他们觉得每日站立会议上所提供的信息,足以用于跟踪项目进展和进行调整了。同样的,有些功能团队可能需要使用团队生产力图辅助他们来进行估算下一Sprint能够完成多少任务,而有些团队则不需要这种方式。

    当然,对于整个部门来说,还使用到一些其它的度量来跟踪产品(对于我们来说就是Visual Studio)的整体进展,例如:主干分支上产品的构建状态、价值主张进展、整体缺陷趋势等。由于产生这些报告所需的数据可以很容易地从TFS数据库挖掘出来,所以创建定制报表相当简单。

InfoQ:Visual Studio开发团队的Scrum完成标准(Definition of Done)有哪些?标准是由谁定义的?又是如何演进的?

    很多独立功能小组分别负责多个主题,这些主题集合在一起就构成了价值主张,而这些价值主张帮助达到特定产品发布所要实现的商业目标。管理好复杂的项目,如Visual Studio,需要面临很多挑战,包括管理和跟踪不同功能团队所开发功能及之间的依赖关系、每天成千上万行代码的变化、确保签入代码达到期望的质量等等。

    因此,在代码从功能分支集成到主干分支上之前,整个部门的项目管理团队定义了一套质量标准,只有到达这些质量标准才能将代码签入到主分支。这套质量标准包括下述内容:

  1. 完整的功能说明(主要用于与依赖方交流产品设计)
  2. 完整的开发设计文档(以设计出产品的各个复杂部分)
  3. 完整的测试计划
  4. 完整的安全计划和分析
  5. 完成代码分析和修复错误
  6. 自动化测试达到70%代码覆盖率(防止回归错误)
  7. 完成性能测试并修复性能回归问题
  8. 完成本地化测试并修复缺陷
  9. 完成API检查
  10. 完成所有测试用例,包括集成测试,修复所有优先级为0和1的缺陷

    以整个部门的完成标准为基本标准,每一个功能小组还会会有一个自己的一个完成标准,小组通过自己的反省Retrospective会议,不断地演进自己完整标准。对于功能小组,我们为实现用户故事定义一套完成标准。

  1. 编写用户故事,并要经过复查
  2. 开发人员为产品复杂部分编写设计文档并经过复查
  3. 编写测试计划,包括接受性测试、功能测试、性能测试、压力测试以及集成测试,并经过审查
  4. 所有签入的产品代码要有单元测试,并都要执行通过
  5. 对签入的代码都要运行代码分析工具,并修复报告的所有错误
  6. 编写验收测试用例并且要全部通过
  7. 功能实现能够满足性能要求
  8. 完成探索性测试(Exploratory Testing)并完成缺陷登记
  9. 功能、集成、性能、压力和安全测试都要被执行并且通过
  10. 修复所有优先级为0和1的缺陷。
  11. 完成风险模型Threat Model(数据流图,Data Flow Diagram)

 

 

InfoQ:Visual Studio 2010的代码及架构分析功能能够对代码进行哪些方面的分析?从您的经验来看哪几类分析对提高系统的内部质量最有价值?

    Visual Studio 2010提供了多种工具帮助对代码的实现,系统的设计等等进行分析和扫描。 对于托管(managed)项目,你可以将代码分析规则组织成规则集。规则集允许你将一条或多条代码分析规则任意组合以方便管理。Visual Studio 2010自带了不少规则集:

  • Microsoft Security Rules(微软安全规则)
  • Microsoft Basic Correctness Rules(微软基本正确性规则)
  • Microsoft Extended Correctness Rules Microsoft Globalization Rules(微软扩展正确性规则)
  • Microsoft Globalization Rules(微软全球化规则)
    • Microsoft Basic Design Guidelines Rules(微软基本设计准则规则)
    • Maintainability Warnings(微软维护性准则)
    • 等等

    这些规则集帮助你确定在安全、性能、可靠性、全球化、互操作性(与COM对象交互)、可维护性等特定领域中的问题。开发者还可以灵活地创建自定义规则集。比如,如果你的应用程序没有与任何COM对象进行交互,那么你就可以关闭那些规则。

    根据我们的经验,打开所有的规则和警告是十分有用的。很显然,有些规则集(如:安全)对于确保开发人员不会在无意中引入任何可被利用的安全漏洞是至关重要的。运行其他规则集,如性能、设计准则等,也是有价值的。因为这些规则是在设计语言和框架专家的最佳实践基础上制定的,可以帮助开发人员(尤其是初级开发人员)在开发阶段尽早确定和提高代码质量,也可以帮助他们学习最佳实践,成为优秀的开发人员。例如,考虑下述警告“CA1502:Avoid excessive complexity(避免过度的复杂性)”这条原则会检测方法中的圈复杂度(cyclomatic complexity)。过高的圈复杂度意味着方法里面嵌套了太多的逻辑判断(if, switch)或者循环(while, for),也就是一个方法包含了太多的逻辑,违反了单一职责(Single Responsibility),这会造成代码很难读,系统很难维护。

    另外, Visual Studio 2010还提供了一种层次图(Layer Diagram,详细内容参见MSDN “如何创建层次图”,“如何使用层次图审查代码”)。在Visual Studio中可以方便的对项目或者是Assmebly进行扫描,生成层次图。层次图提供了对系统的一种多层次的逻辑抽象,可以帮助开发人员对系统的整体以及局部有一个更好的把握。

    在Visual Studio 2010中,你可以让代码分析作为构建的一部分运行(我们也正是这么做的),甚至可以将其作为代码签入政策(check-in policy)的一部分。质量控制所要求在将代码整合到主干分支前必须运行代码分析,由于我们从开发周期的一开始就决定采用这种做法,这样就避免了处理成千上万的警告了。

    在一个迭代中,测试的种类有那些?哪些是手动的?功能类的自动化测试有哪些类型(比如基于UI的自动化,UI层以下的自动化,集成测试,单元测试等等)?如何在功能小组内组织这些测试?

    通常在每一个迭代中,我们要编写单元测试、验收测试、功能测试、以及一些压力和性能测试。除了这些之外,我们也会编写覆盖完整用户场景的集成测试,集成测试一般会跨越产品的多个功能。

    单元测试是由开发人员设计并实现为自动化测试,针对系统中加入的单个低层API。单元测试会与产品代码一起签入到TFS版本控制系统。

    验收测试和功能测试由测试人员根据项目经理的功能说明书来编写的。

    验收测试用例在所有测试用例中优先级最高,通常为1级(P1),它们覆盖了功能说明书中描述的最基本/核心的用户场景。验收测试用例保证了产品实现的功能达到了用户故事描述的设计。通常情况下,功能说明中每个用户故事对应一个或两个验收测试用例。

    除了最基本的用户场景之外,产品功能的其它扩展或临界情况则由功能测试用例来覆盖。测试人员编写的测试计划包含了功能测试用例。这些测试用例要根据所覆盖用户场景的重要性以及用户可能使用产品的方式进行优先级划分。根据以往的经验,一部分功能测试用例会被自动化,其余的用例则作为手动测试。手动测试的原因有很多,例如:自动化测试技术的局限、时间和资源限制等。

    在项目的周期中,测试人员的手工测试以及早期试用者会发现新的产品缺陷。经常有缺陷会揭示出现有测试套件的测试漏洞。对于其中严重的缺陷,如:功能无法正常工作、产品崩溃或者没有响应,测试人员要为这些缺陷在测试计划中添加新的功能测试用例,并自动化它们以防止再次发生。

通常,验收测试和功能测试是在用户界面(UI)层实现的。在我们的测试团队中,我们利用不同UI自动化技术来实现测试用例的自动化,如:Visual Studio Extensibility Model(Visual Studio 扩展模型,DTE)、Microsoft Active Accessibility(MSAA)、WPF的UIA(User Interface Automation)、以及Visual Studio 2010种的Coded UI Test Framework(Coded UI测试框架)等。

    在完成标准中有些特殊的要求比如性能测试、压力测试等等。这些需要一些特殊的工具或者技巧。为了确保我们还是确保每个团队独立完成每一个用户故事,减少了对外的依赖。每个功能小组都有相应的人员能够完成这样的任务。为了保证工具的标准以及知识共享,我们会建立有一个虚拟团队,比如所有做性能测试的测试人员的团队,这个团队会负责发展性能测试的工具,框架以及知识分享。这样我们就能达到一个平衡。

InfoQ: 作为从来没有接触过Scrum的团队,如果我们想借助Visual Studio的Scrum模板引入Scrum,有哪些建议?

    在选择何种战略有利于团队采用Scrum时,有几个因素需要考虑:团队和管理层对改变其流程的意愿、团队的规模、项目性质等。

    根据我的经验,有几种行之有效的办法。第一种是单纯从项目管理角度采用Scrum。由于Scrum是一种围绕项目管理的方法,并不要求技术实践,这可以使新的流程更容易被接受。当然,团队应继续延用当前的技术实践,因为这些都是项目成功所必须的。这种变化可以逐步推行,以帮助团队解决他们当前问题。例如,假设团队已在某一次迭代中已无法如期完成功能。项目经理(或Scrum Master)可以开始使用TFS工作项记录迭代(里程碑、Sprint或其他何种术语)中开发人员的任务,使用燃尽图追踪进度。这些燃尽图可为团队及早发现和纠正行为提供帮助。又如,如果团队在迭代进行到一半时发现他们已经落后于目标进度了,就可以减少那些最不重要功能相关的任务,以帮助他们赶上进度。一旦团队认识到了燃尽图的价值,那么在下一次迭代中,Scrum Master就可以引入另一个新的概念了——比如,制定Sprint计划以确保团队在开始时不至于承诺过多的任务。Sprint计划中包含的用户故事可以作为工作项录入到TFS中,团队可以随后创建“任务”工作项来实现这些故事,并和从前一样开始跟踪进展。现在,假设在下一个Sprint中,团队开始发现已经实现的故事中出现产品质量回归,Scrum Master就可以引入持续集成(Continuous Integration )的概念(这是一个技术实践方法,可以极大地帮助团队尽早发现产品缺陷)。这可以通过创建一个Team Foundation Build的构造定义来实现。Team Foundation Build中可以配置构造,使其不仅能编译团队的代码,还可以运行测试。我们可以将构造配置为Continuous Integration(持续集成,每次签入代码后都会开始一次构造)、Rolling Build(滚动构造,在构造期间发生的签入都将积累,直到构造完成进入下一次构造过程)、Gated Check-in(门控签入,构造并运行测试,只有在所有测试都通过的情况下才提交变更)等等。这种在Visual Studio 2010中逐步引入Scrum实践已解决团队当前正面临问题的做法已被证明是有效的。

    另一种方法是建立一个小型的功能小组(由愿意尝试变革的团队成员组成),使用Visual Studio来实践Scrum。当其他团队看到该功能小组是如何确定问题、提出修正、并在每次迭代结束时向客户交付产品后,再让他们也采纳这些最佳实践就变得容易得多了。