`
longgangbai
  • 浏览: 7340168 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

软件开发管理中的最佳实践——日构建和持续集成

阅读更多

XP方法中把日构建列为软件开发管理中的最佳实践;敏捷软件开发中也把持续集成当作是保证软件项目成功的一个原则。无独有偶,2003中国软件(600536,股吧)技术大会,上海微创软件公司技术总监蔡培讲述了微软公司的软件开发管理,演讲中提到微软软件开发管理中的一个重要实践,也就是日构建。(日构建和持续集成本质上是一样的,只是前者的频度是每日一次,而后者则并未限定频度。为了便于讲述,本文中不再区分这两个概念。)

 

  关于日构建的作用和意义,书籍和网络上已有相关文章介绍,本文不再赘述。本文假设读者已经充分认识到日构建或者持续集成的好处,并且正打算把它应用到企业的开发管理流程中去,但是对于如何做日构建和持续集成,无论从技术上还是管理上还比较迷茫,那么这里将务实地与大家交流一下相关的一些的经验。

  1.1. 日构建中的要素

  归纳一下,日构建中有如下几项要素:

  1.1.1 版本管理

  所有参与构建的开发工件都应该纳入版本管理。有了版本管理,才能为了日构建稳定而可靠的输入。版本管理工具要为日构建提供的支持仅需包括一个命令行客户端工具。

  1.1.2 流程自动化

  日构建的处理复杂性依赖项目的大小以及加入的实际过程数量和内容而不同,但是不管怎样,努力达到流程的全部自动化是日构建的一个要求。流程的自动化有利于提高日构建的运行效率,减少人工干预引入的错误可能。

  1.1.3 为日构建定制的管理制度

  日构建完整的流程不仅只涉及到开发人员,实际还涉及到需求人员、设计人员、测试人、员、项目经理等多个角色,是一天中各方工作成果的集中体现。如此重要的活动,并涉及到多个责任主体,必然也要制定相应的管理制度来规范各个角色的行为,以便保障该项重要活动的有序、有效进行。

  1.2. 日构建的一些策略

  1.2.1代码统一管理

  一般来说,只要软件开发中全部使用了版本管理工具来管理开发输出的工件,就具备了日构建的该项要素。实际情况中,无论采用微软的VSS,Rational的ClearCase,还是开源的CVS,都可以通过特定的客户端工具,以命令行的形式来获得所需项目的最新版本(或者特定版本)的工件来进行构建。(这里之所以说是工件,而不特指代码,是因为实际构建中的元素不仅有代码,还可能包括其他一些参与编译或者运行的工件,比如说元数据。)

  日构建虽然是一个软件企业的日常开发管理行为,但是它一般是以项目作为构建基础的。不同的项目尽管不建议,但是还是允许采用不同的日构建工具、流程。

  一般来说,我们会是先有版本管理工具,再有日构建的相应工具,而且,可能存在多个项目所使用的版本管理工具不一致。比如一个企业可能同时采用VB和Java开发不同的项目。那么采用VB的项目,基于与VirtualStudio的集成,可能更多选择了VSS作为版本管理;而采用Java开发的项目则可能选择CVS作为版本管理。对于一个软件企业来讲,为不同的项目选择不同的配置管理工具可能是个无奈之举,但是在选择配置管理工具的时候,该工具是否能够很好支持日构建应该成为一个考虑项。

  下表给出了可以成功构造日构建系统的常见模式。

  1.2.2流程自动化

  简单的日构建流程包括:下拉源代码->编译代码->运行测试。

  复杂一点的日构建流程可能包括:

  1. 下拉工件

  从版本管理工具获得源代码、参与运行的资源文件(图标和图片)、配置、元数据等。

  2. 工件统计(Statistic)/审计(Audit)

  统计代码的有效行数以衡量生产率,个人工作量。

  审计则可能包括审计工件命名风格,命名规范,多语言处理,异常处理等等。自动审计功能配合合适的管理制度,有助于帮助企业实现开发的规范化。

  3. 编译或加工

  编译很容易理解,这里的加工指对源代码进行某种事先处理,比如根据源代码生成配置文件和部署描述文件。另外,还可能包括特殊目的的代码替换和测试覆盖插入(SourceCodeInstrumentation)。

  4. 部署、配置

  让一个软件运行起来可能需要进行配置和部署。比较典型的是j2ee的程序,需要配置客户端和在应用服务器部署EJB描述符。

  5. 运行

  让软件按照特定的要求运行起来。(比如按照单元测试的要求,或者按照性能测试的要求)

  6. 测试

  日构建中可以引入各种测试。比较常见的是单元测试,实际上能够够自动化验证的集成测试和性能测试也可以加入进来。

  7. 测试统计和审计

  测试过后可能留下许多测试数据,比如单元测试的成功比例,每个单元测试执行的时间,性能测试留下的分析数据等等,这些数据可以在这一步充分利用起来,通过分析得出某种结论。

  8. 发布报告和邮件通知

  日构建过后,除了输出各种工作组件,重要的还要发布日构建报告。日构建报告最好以网页的形式在一个固定的地方公布,内容可以保罗万象,比如模块的责任人、编译成功与否、部署成功与否、单元测试的个数、单元测试的成功率、代码覆盖率、工件统计等等。为了便于大家察看,可以附带简要的邮件通知。

  根据经验,流程自动化会涉及到几个难点:

  第一, 如何解决编译的粒度和循环依赖问题

  对于一个小项目来说,整个项目参与构建的工件可以作为一个整体一起拉下来,然后编译。如果编译未过,则日构建整体不成功。典型的例子是建立一个src目录,不同开发人员共享,所有的原代码都放在该目录中。

  对于大项目而言(尤其是产品),由于有上百人参与开发,可能需要按照项目模块来组织开发,这个时候会存在多个src目录。在日构建中可以处理成把所有的src下拉后重定位到一个src目录进行编译。这种方案称之为大编译。但是这种方案有个问题,就是一旦某个模块的代码编译不能通过,整个大项目的编译也不能通过,除非这个编译问题能够立即解决,否则这将影响那些正常模块的日构建输出和功能验证。尽管大家会认为,编译问题自然要立即解决。但是这也就成为了影响日构建自动化的一个障碍因素。实际上,编译只是影响成功构建并达到可测试状态的其中一个影响因素,比如还可能存在元数据发布不成功,EJB部署不成功等。有些因素一旦发生,可能在某种特殊情形都无法短时间解决,这个时候就凸现了下面一种方案的价值。

  这种方案的基本原则是每个模块单独编译,元数据单独发布。但是这种方案要面临如何解决模块之间编译存在依赖链,并且这个链还可能成为环状的问题。这里与大家分享的一种做法是先执行前面提到的大编译,然后再把大编译的输出作为其它各项目编译的输入。这样可以解决编译次序和循环依赖问题,同时可以真实判断出哪些模块成功,那些模块存在问题,为针对单个模块的报告提供依据。

  实践中,曾经把一个三百号人同时开发的项目分成了60个模块。在项目的初期,一般情况都会存在个别模块在当日日构建无法编译通过,并且可能出现特殊因素无法立即解决。但是采用上述方案,这个有问题的模块并不会在编译期间过大制约其它多数模块的正常编译通过。

  第二, 对于大型项目如何控制个别子模块不成功对全局的影响

  一般来说,模块之间存在依赖关系,比如Module C依赖Module B,Module B又依赖ModuleA,那么是否只要Module A 出现了编译问题,ModuleB和ModuleC在当日日构建就都不输出呢?这是个局部影响全局的问题。作者建议的做法是,ModuleA本次提交如果出现了问题,立即进行修复,特殊情况不能修复,由日构建系统自动根据编译结果判断启用ModuleA历史上最近一次成功版本。

  有人可能会问,这种做法是否存在潜在的问题呢?的确存在,但是这个问题并不会想象的那么可怕。只要不是接口变更,一般来说ModuleA的问题只会影响ModuleA的内部,而不会殃及依赖ModuleA的其它模块。如果ModuleA在今日日构建做了一个接口的变更,而且这个变更也通知了依赖它的ModuleB,并让ModuleB做修改,那么启用ModuleA的最近历史版本的确会存在运行时接口对不上的错误。对于这样的情况,可以不予处理,等待这个问题下一次日构建再解决。最好的办法是管理上要求当日必须解决ModuleA的编译问题。

  上面提到的方法在几百人协同开发, 需求验证和测试并行的场景中经过检验,值得推广。

  第三, 复杂环境的部署

  可能很多人会认为解决了编译问题就解决了日构建的主要问题。其实不然,日构建的目的是产生一个最新的、可供测试的输出。为了达成可供测试的输出,首先日构建就要尽可能进行自测,以期在把工作产品传递到测试服务器、测试人员那里之前发现尽可能多问题。比如整个产品是否可以稳定的在应用服务器中加载?系统的登陆模块是否可以正常工作?菜单项是否可以正常读取?

  基于上述目的,日构建自身要配置出可以运行的实际环境以便运行验证测试程序。比如BVT(BuildVerificationTest)。对于J2EE的应用,大家都知道,视产品部署模型的复杂程度这项任务可以变得非常复杂。

  环境部署问题没有可供借鉴的统一模式。以笔者个人的经验,在日构建系统设计上如果能够做到与开发人员、测试服务器的部署模型和部署位置保持一致,就会大大减少环境的复杂性,这个时候可能需要人为制造一种统一环境。

  1.2.3报告机制

  日构建在某种程度相当于对项目的一次“体检”,体检的结果自然需要公而告之。公告的目的,是以实际数据来说明问题,并让项目中的所有成员对项目的现状达成一致的理解,并且这种理解是充满说服力的。日构建的报告可以做得很简单,也可以做得很复杂。形式可以采用web发布,也可以采用邮件通知。从项目管理的意义上,建议在这方面投入尽可能的精力和资源。

  以本人参与设计的一个日构建系统为例,其日构建报告为web形式,左右结构框架。左边显示日期,点击该日期后在右边显示具体的报告。其内容包括:

  按模块进行报告,报告中显示该模块的责任人(一般是负责该模块的项目经理)

  每个模块的编译情况。通过或者未通过。未通过则显示编译出错信息。

  每个模块的部署情况。成功或者失败。失败则显示失败的信息。

  每个模块的单元测试数目,单元测试的时间,成功率,代码测试覆盖统计。

  每个模块的代码行数,EJB数目,各种元数据的分类统计

  每个模块代码的风格审计,异常处理审计,命名规范审计,多语言处理审计等等

  1.2.4为日构建定制的管理制度

  专门的日构建设备

  必须为项目安排专门的日构建机器,而且要求机器的处理性能较高,内存容量较大。以目前PC机的处理性能,150人以下的项目,实践证明足以胜任。

  日构建的时间管理

  日构建并非每日仅构建一次。从持续构建的意义来看,日构建可以根据需要每日进行很多次。什么时候进行日构建?每日进行几次日构建最佳?没有最佳答案。但是根据经验,在项目的初期,由于功能大批量加入,测试还未全面开展,每日进行一次构建就可以了。随着、项目的推进,系统功能逐渐丰满、稳定,测试和需求验证也逐渐铺开,这时每日可以进行两次或者更多次构建。

  日构建的时机一般放在下午为佳,如果个别模块发生问题,相关人员可以利用晚上的时间留守解决。微软的日构建发生在凌晨,并且自动调度执行。开发人员次日来了关心的头一件事就是自己负责的模块是否在日构建中进行得顺利。

  午餐休息时间也是进行日构建的另一种选择。对于不大的项目,一个小时一般可以产生出日构建报告,这样开发人员中餐回来后可以直接对问题进行处理。而测试人员和需求人员也可以对上午的工作产品进行验证和测试。

  日构建轮值

  尽管完善的日构建是通过调度自动运行,但是对于应付一些突发的事件,比如产品临时检查,开发人员对发现的重大bug的立即修复等,可能需要人为调度日构建运行。原则上建议为日构建设立一位管理员。由于事物处理并非持续,这个管理员兼职即可。

  建议采取管理员在各部门或者项目组轮值的方式。这样有利于加强各方对日构建的重要性和处理过程形成共同的认识,同时也可以避免出现关键人物依赖。

  接口变更管理

  不同模块之间可能存在接口的依赖,这里的接口并非专指程序语言中的Interface,而是包括所有在编译和运行期间依赖的部件。接口的变更管理是开发管理过程中的一个难点,尽管从软件设计角度,我们可以采取一些方法来尽量避免这种依赖,比如接口倒置,接口分离;但是在现实中,这个问题难以回避。持续集成的一个主要目的就是解决这个问题。

  接口的变更原则上要求变更方主动通知接口依赖方,并且要求在日构建之前提前通知,以便接口依赖方有时间在集成编译之前能够调整原来调用老接口的代码。很多时候,这需要借助管理来保证。实际情况中,无法避免接口依赖方没有收到接口变更通知、或者来不及调整接口的情况,这种情况一旦发生,便导致接口依赖方的代码编译无法通过,问题就出来了。问题需要尽量避免,但是其产生并不可怕,这正体现了持续集成的作用——让问题尽早暴露。

  日构建中的行为规范

  日构建是一天中所有工作产品的一次集中验证,并且输出的组件要影响第二天的所有工作,为了保证其正确进行,需要规范参与者的行为。这种行为规范包括开发人员在日构建前的准备工作,日构建后的响应和处理。为了便于大家理解,这里以举例的形式介绍给大家。比如:

  1. 开发人员在日构建前15分钟必须提交代码,以保证处理流程可以下拉正确的代码。

分享到:
评论

相关推荐

    微软软件开发生命周期管理最佳实践系列课程(1):配置管理

    在IT行业中,软件开发是一项复杂的过程,涉及到多个阶段和团队成员的合作。微软的软件开发生命周期管理(Software Development Lifecycle Management, SDLLM)提供了一套全面的方法来确保项目的顺利进行。本课程聚焦...

    持续集成软件质量改进和风险降低之道

    持续集成(Continuous Integration,简称CI)是一种软件开发实践,其目的是让软件开发团队...随着技术的发展和需求的变化,持续集成也会不断演进,但其核心理念——频繁集成和快速反馈,将一直指导软件开发的最佳实践。

    《简单之美——软件开发实践者的思考》

    《简单之美——软件开发实践者的思考》这本书深入探讨了软件开发中的一个重要原则——追求简单。在信息技术日新月异的今天,简洁...阅读这本书,你将对如何在软件开发过程中实现“简单之美”有更深入的理解和实践策略。

    NC总账持续集成实践

    持续集成是现代软件开发中的关键实践,旨在早期发现并修复错误,提高软件质量。在NC(可能是SAP NetWeaver或类似产品)总账的开发过程中,持续集成扮演着至关重要的角色。NC总账持续集成实践涉及多个工具和技术,...

    软件项目开发综合实训——Delphi篇和Delphi篇源代码

    《软件项目开发综合实训——Delphi篇》是针对Delphi编程语言进行软件开发实践的一门课程,旨在帮助学生深入理解Delphi的使用方法,并通过实际项目来提升开发技能。这门课程涵盖了从基础到进阶的多个章节,包括但不...

    大型综合医院改扩建项目中智能化系统的实践——北京大学第三医院智能化建设.pdf

    这包括需求分析、系统设计、软件开发、硬件配置、系统集成、测试、培训以及后期维护等阶段。每个环节都需要精心规划和执行,确保项目的顺利进行。 总之,北京大学第三医院的智能化建设实例展示了如何通过智能系统和...

    持续集成交付实践.docx

    持续集成是一种软件开发实践,通过频繁地将代码更改合并到主分支中,并自动运行构建和测试,以确保代码质量并及时发现潜在问题。持续集成模块支持多种任务类型: - **需求类任务**:如Jira和Ones等工具用于需求管理...

    软件工程——实践者的研究方法

    《软件工程——实践者的研究方法》是一本深入探讨软件开发过程和管理的权威教材,它为软件从业者提供了全面而实用的理论与实践经验。这门课程的课件涵盖了软件工程的多个核心领域,对于学习和复习软件工程知识具有极...

    2013年中国数据库大会-41-数据开发的工程化实践——强化您的数据开发过程

    通过上述的方法和实践,可以显著提高数据库开发过程的工程化水平,使得数据开发与软件开发一样,成为一个规范、可控、高效的过程。这不仅有利于数据库的稳定运行和扩展,也能够提高数据的价值和数据库在企业信息系统...

    软件工程——实践者的研究方法.rar

    《软件工程——实践者的研究方法》是一本深入探讨软件开发过程和实践经验的书籍。它旨在为软件工程师、项目经理以及对软件开发感兴趣的读者提供一套实用的研究方法,帮助他们在实际工作中更高效、更系统地进行软件...

    未雨绸缪——理解软件配置管理(第2版)

    本书《未雨绸缪——理解软件配置管理》第二版深入探讨了SCM的核心概念和技术,帮助读者全面理解SCM的重要性和实践方法。 #### 二、SCM在项目管理中的应用 1. **变更控制**:SCM系统能够记录所有对源代码的修改,并...

    C#软件项目开发全程剖析——全面透视SharpDevelop软件的开发内幕(pdf)

    这涉及到软件开发的最佳实践,如敏捷方法、版本控制、单元测试和持续集成等。这些知识点对于任何软件开发项目都是至关重要的,无论你是否使用SharpDevelop。通过实例,作者会展示如何在SharpDevelop中实现这些最佳...

    硅超大规模集成电路工艺技术——理论、实践与模型(英文版)

    根据提供的标题“硅超大规模集成电路工艺技术——理论、实践与模型(英文版)”及描述,本文将深入探讨硅基超大规模集成电路(Very Large Scale Integration, VLSI)的相关理论、实践技术和模型构建等方面的知识点。...

    构建微服务云原生应用——服务开发框架设计和实践.zip

    本主题围绕“构建微服务云原生应用——服务开发框架设计和实践”展开,旨在深入探讨微服务架构的设计原则和实践经验。 首先,我们需要理解微服务的核心概念。微服务强调单一职责原则,每个服务专注于一个特定业务...

    _软件工程——实践者的研究途径和方法.rar_软件工程

    《软件工程——实践者的研究途径和方法》是关于软件工程领域的深入探讨,旨在提供一种实践导向的研究方法。软件工程作为IT行业的核心组成部分,是确保高效、可靠和可维护的软件开发的关键。本资料集可能包含了丰富的...

    敏捷软件开发原则 模式与实践 c#源码

    《敏捷软件开发原则、模式与实践》是一本深入探讨敏捷开发方法论的著作,它强调在快速变化的需求和不确定性中,如何高效地进行软件开发。C#源码的提供为读者提供了实际操作的可能,帮助理解理论在实际项目中的应用。...

Global site tag (gtag.js) - Google Analytics