配置管理最佳实践

978-7-115-32190-9
作者: 【美】Bob Aiello Leslie Sachs
译者: 顾刘学苏建雷魏朝晖
编辑: 汪振

图书目录:

详情

本书细致介绍项目管理的各种知识,通过作者多年管理中积累的宝贵经验,向读者传授源代码管理、环境配置、变更控制、版本控制等方面的项目管理技巧。全书分四部分。第一部分包括源代码管理、构建工程、变更控制、环境配置、发布工程和部署;第二部分包括架构和硬件配置管理;第三部分介绍有效实施配置管理最佳实践中最关键的人的因素。第4部分介绍标准和规范和建立有效IT控制需要的框架。

图书摘要

PEARSON

配置管理最佳实践

[美]Bob Aiello Leslie Sachs 著

顾刘学 苏建雷 魏朝晖 译

Configuration Management Best Practices

Practical Methods that Work in the Real World

人民邮电出版社

北京

图书在版编目(CIP)数据

配置管理最佳实践/(美)艾洛(Aiello,B.),(美)萨克斯(Sachs,L.)著;顾刘学,苏建雷,魏朝晖译.--北京:人民邮电出版社,2013.9

ISBN 978-7-115-32190-9

Ⅰ.①配… Ⅱ.①艾…②萨…③顾…④苏…⑤魏… Ⅲ.①软件工程 Ⅳ.①TP311.5

中国版本图书馆CIP数据核字(2013)第133718号

版权声明

Authorized translation from the English language edition,entitled:Configuration Management Best Practices:Practical Methods that Work in the Real World,978-0-321-68586-5 by Bob Aiello,Leslie Sachs,published by Pearson Education,Inc.,publishing as Addison-Wesley Professional,Copyright©2010Pearson Education,Inc.All rights reserved.No part of this book may be reproduced or transmitted in any form or by any means,electronic or mechanical,including photocopying,recording or by any information storage retrieval system,without permission from Pearson Education,Inc.

CHINESE SIMPLIFIED language edition published by PEARSON EDUCATION ASIA LTD.and POSTS & TELECOM PRESS Copyright©2013.

本书中文简体字版由Pearson Education Asia Ltd.授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

本书封面贴有Pearson Education(培生教育出版集团)激光防伪标签,无标签者不得销售。

版权所有,侵权必究。

◆著 [美]Bob Aiello Leslie Sachs

译 顾刘学 苏建雷 魏朝晖

责任编辑 汪振

责任印制 程彦红 焦志炜

◆人民邮电出版社出版发行  北京市崇文区夕照寺街14号

邮编 100061  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

北京隆昌伟业印刷有限公司印刷

◆开本:700×1000 1/16

印张:14.5

字数:229千字  2013年9月第1版

印数:1-3000册  2013年9月北京第1次印刷

著作权合同登记号 图字:01-2012-9274号

定价:49.00元

读者服务热线:(010)67132692 印装质量热线:(010)67129223

反盗版热线:(010)67171154

内容提要

本书贴近实际,旨在指导配置管理从业者如何处理日常工作中需要面对的各种复杂情况。全书详细介绍了配置管理的6个核心职能:源代码管理、构建工程、环境配置、变更控制、发布工程和部署。作者在书中展示了如何实施配置管理,从而可以支持软件和系统的开发,满足SOX、SAS-70等合规准则的要求,提前考虑新兴的IEEE/ISO 12207等标准,同时还可以和最新的ITIL、COBIT 和CMMI等框架集成到一起。

本书对于任何与配置管理相关的工作人员来说都是一本必不可少的参考书。从CTO到CIO,再到开发人员、质量保证工程师、项目经理、软件工程师、系统分析员、测试人员和合规专业人士,皆是如此。

对本书的赞誉

“管理变更首先要理解变更。Bob Aiello和 Leslie Sachs的这本《配置管理最佳实践》清楚地定义和解释了变更及其潜在的影响。”

—Mary Lou A.Hines Fritts

美国密苏里州堪萨斯城大学首席信息官兼学科课程副校长

“很少有软件配置管理的书在定义和执行高效软件配置管理流程时会强调人和组织的角色。Bob Aiello和 Leslie Sachs的书则提供了这方面的信息。你可以利用这些信息有效地管理好变更和完善软件配置管理流程。”

—Steve Berczuk

敏捷开发软件工程师

《Software Configuration Management Patterns:Effective Teamwork,Practical Integration》作者

“Bob Aiello 和 Leslie Sachs 非常真诚地完成了这本书,并且在细节和实践方面进行了相应的平衡,点明了很多细节,这样可避免大家在实际项目中遇到麻烦。在这本书中,覆盖了很多方面,包括文化、个性、如何处理变革阻力等,他们对这一领域很有热情。软件行业正需要这样的一本书。”

—Jim Brosseau

Clarrus咨询公司

《Software Teamwork:Taking Ownership for Success》作者

“这是一本任何开发、管理软件或硬件项目的人的必读书。Bob Aiello 和 Leslie Sachs 的这本书涵盖了社区中大量成功的配置管理实践。他们描述的是现实世界中可以被开发人员、经理、标准制定者,甚至是专职的配置管理人员实现的实践。”

— Bob Ventimiglia

Bobev咨询公司

“这本书从一个全新的视角审视了软件工程中软件的配置管理、构建管理和相关的主要实践。作为这方面的专家,Bob Aiello 和 Leslie Sachs 对如何做好软件配置管理提供了非常有价值的信息。”

—Pablo Santos Luaces

Codice软件公司首席执行官

“Bob Aiello 和 Leslie Sachs 都有很多激励公司进行必要的组织改革的想法,也擅长这方面的谈话。他们说得非常有趣,也非常重要。”

—Marianne Bays

商务咨询师、职业经理人及教育工作者

推荐序

配置管理是软件工程活动中至关重要的一环,其重要性仅仅比计划管理稍弱,因为没有计划就没有项目。

在我十多年的软件项目经历中,目睹了太多企业荒唐的软件开发活动,很多项目虽然在开发过程中可能没有遇到特别大的风险和问题,但是也都因为没有良好的配置管理而会给项目交付后的软件运行维护周期带来更大的隐患风险。

在本书中,我惊讶地看到:原作者在书中提到,他之所以热爱配置管理,是因为这是一项富有创造性并令人激动的工作——在中国大陆的各个公司中,应该还从没有人公开声称配置管理是一项富有创造性的工作,至少从没有人如此公开推崇配置管理在整个软件工程中的位置,以及配置管理工作本身所能体现的吸引力。书中提到了相当多的实用性操作方法,并且配有原作者在实际工作中进行操作的例子。至于是否一定是最佳实践——我曾经批驳过最佳实践这个词汇,但是,至少这里给出了大量你不曾了解的非常好的实用配置管理方法和操作过程,这些都可以应用于各种不同规模的软件项目开发和维护过程中。希望读者能够更多地着眼于这个角度。

如原作者所推崇的配置管理,曾经有人多次问过我这样的问题,什么样的软件工程过程组成是最精简的,我的回答中始终包含配置管理。曾经在论坛和QQ群中讨论软件工程的关键活动时,我也常常把配置管理放在计划管理之后、需求管理和风险管理之前这样重要的位置上。但是,国内的现状往往是令人沮丧的,2012年中期,完美世界的一个人在提到他们公司的软件工程活动时,配置管理不见踪迹。很多公司甚至完全不知道配置管理为何物,更多的公司可能知道的仅仅是诸如VSS、CVS、代码管理、版本控制之类的名词而已。当然国内也有比较重视配置管理的公司,只是数量很少。记得2001年中期,我所在的公司派遣三个人去参加Rational的那次ClearCase培训中,华为公司派遣了一支一百多人的团队参加这个培训。

本书的翻译中,译者为了保持原文的严谨性,没能将部分幽默的用语表达出来,比如在介绍中提到的:“这实际上是把你的蛋糕放上卡车,准备交付给消费者。(请确保你有我家的正确地址。)”括号内的翻译可以更为风趣一些:“蛋糕一定要写明我家的地址,好尽快准确地送给我品尝。”但这也说明了译文对原文的忠实,有些时候译意很难保持原文中要表达的全部丰富的感情和含义。

书中提到了SQA和SEPG的问题,因此我认为需要强调一下它们之间的可能产生混淆的关系。

国内大约是从2000年底开始引入CMM后用来作为CMMI的过程评估方式,由此带来了一系列软件工程活动的新概念,诸如SEPG、SCM、SQA、PR等。

在整个软件工程活动中,SEPG是作为全过程的标准制定者和审核者的身份出现在一个公司的开发活动中的。SQA检查项目组在软件工程活动进行中的规范符合程度,同时评估项目在整体运行状态上的风险,并将这些风险提前警示给企业的管理层;这里的SQA不是现在大多数国内企业所宣称的QA,国内大多数企业招聘的QA的正确名称实际上应该是QC,也就是质量控制,而不是质量保障QA。QA是不管产品结果如何,监管过程是否符合公司标准过程,是否会出现风险,都会随着软件工程活动的进展,而不断和项目组发生接触,并不是到了产品出现的时候才进行产品的质量检查(这个工作是QC的职责范围),因此对双方的不理解或者误会可能会激发各种冲突,这些都需要SEPG来进行仲裁和协调。

实际上,QA是来帮助项目组规范过程质量,预防突发的风险,同时让公司的上层提早了解项目的进展情况,最起码不至于发生Borland C++ 4发布后的那种几乎让整个企业面临的灭顶之灾。

而SCM则是构建起这一切的基础,从项目的计划到最后运维中的一切代码和文档都应该在配置管理库中存放,同样配置管理库还可以提供一些提升开发效率和公司整体产品一致性的基础支撑。有一句十年前就经常提到的话:一个良好的配置管理体系,可以让我的开发过程随时回滚到任何一段时间之前的状态。很多技术人员都遇到过系统崩溃后找不到稳定代码的情况,很多人也都遇到过风险发生后不得不从一个未知状态开始修改bug的情况。而一个成熟的开发团队和公司应该做到,随时可以在遇到风险的时候,将我的团队状态重置于一个经过验证的安全环境下。比如,将已经崩溃系统的开发过程整体回滚到几天前,1小时前,或者20分钟前,甚至几秒钟以前。

配置管理是远远超越软件系统运行日志的重要性,不仅会标记出软件开发过程的各个阶段和状态记录,还会提供良好的支持给其他软件工程活动,诸如计划管理、需求变更、代码走查、测试、变更、风险等。可以说,配置管理在出现后会成为所有软件工程活动运行的基础载体的核心部分。没有了配置管理的软件开发,就是作坊。比如在最近我发表的一篇文字中就直接指出国内几家大公司开发管理中的问题(全文可在@青润的新浪微盘中下载到最新版本),诸如国内某大型的IM公司都没有建立起完善的配置管理体系,可见国内企业开发过程的不成熟。

要知道,在CMM/CMMI的评估中,配置管理也是2级中要求的核心KPA。

我本人不算是配置管理的专业人员,本来不足以作为本书序的撰写者,但作为软件工程开发方法和过程的研究者和经历者,也就冒昧写下寥寥数语,以示对作者的敬意。

青润

独立软件咨询师

《软件工程之全程建模实现》作者

2013年春节

译者序

其实,我一直想写一本关于软件配置管理实践的书,讲讲怎么才能做好软件配置管理。虽然国内软件配置管理发展很快,但是我发现有些人对软件配置管理依然很陌生。经常会被问到一些问题,例如,配置管理是做什么的?和IT人员有啥区别?到底什么是基线?专职做配置管理工程师还是兼职?……针对配置管理的基础知识,我们特意在配置管理之路论坛列了很多配置管理知识点和大家一起讨论;而对于配置管理中很多经验性的问题,则组织讨论了三十多期配置管理小菜鸟案例分析系列。知识性的东西,一说大家就明白,一点就通,但是很多经验性的理解,只有与有过类似工作经验或者和资深的人员深入地交流才可以理解。但这些零零散散的交流和讨论明显是不够的。需要帮助大家系统性地梳理这些知识,同时从多年配置管理工程师的角度和大家分享工作中遇到什么样的问题该如何去处理。出差时,买到了这本书的英文原版。看完之后,发现作者把配置管理分成6个核心实践的做法和我平时给很多人做培训时的思路十分相似,和现实工作中配置管理的内容十分贴切,于是产生了翻译这本书的最初想法。

这本书没有掉书袋似地往读者的脑袋中塞知识,而是从实际工作出发,把配置管理的知识和经验介绍给大家。首先第一部分把配置管理的工作分成源代码管理、构建工程、环境配置、变更控制、发布管理和部署6个方面。我个人觉得这是和目前大多数配置管理工程师的职责最贴切的一种划分。虽然国内每个公司的研发成熟度有所不同,每个配置管理工程师具体职责可能不同,但是公司级层面上配置管理工作一定会涉及上面的6个方面。这本书第二部分介绍了软件的配置管理架构和硬件配置管理,虽然不是每个人的工作都会涉及硬件的配置管理,但是这部分让我们对配置管理有了更深入的认识。例如把源代码管理、构建管理当做服务提供给研发团队,时刻不要忘记跟踪变化等。第三部分讲述了配置管理中人的因素。很多公司都不缺流程,缺的就是把流程执行下去的人。由此可见,人的因素在流程执行过程中的重要性。第四部分着重介绍了配置管理领域的合规、行业标准和框架。这部分可以让你更深入地了解配置管理。配置管理早已经不是开荒的年代了,我们有很多行业对配置管理都有着明确的要求,同时我们也有很明确的行业标准和框架。我个人感觉这本书虽然不能解决大家工作中遇到的所有问题,但是很多常规的思路和做法值得大家去体会、去借鉴。

感谢青润为这本书做序。同时还要感谢配置管理之路翻译团队的伙伴们:苏建雷、魏朝晖,大家辛苦了。其中我翻译了本书的第Ⅰ部分,即全书的第1章至第6章;苏建雷负责翻译第Ⅱ部分和第Ⅲ部分的前两章,即全书的第7章至第10章;魏朝晖则完成了剩下的4章,从第11章至第14章。最后还要感谢在翻译过程中帮助我们审校的同行朋友,张勇(cody)、石全(SQ)、刘艳菊、张鹰(恐龙)、陈冰洁、段辉娜、谢思思和周赛赛,感谢你们的审校,是你们帮助纠正了本书的某些专业翻译,是你们让这本书的中文译本更专业。

如果大家在阅读本书的过程中有任何疑问,或者在实际工作中遇到问题,欢迎访问我们的网站——配置管理之路(http://www.scmroad.com),或者关注我们的新浪微博(@scmroad配置管理专业网站),期待能与大家一起交流互动。

虽然我们都竭尽全力想翻译好这本书,但是说实话,有些内容读英文很容易理解,但是要想翻译成让大家也很容易理解的中文,真不是一件简单的事儿。所以翻译错误在所难免,敬请读者赐教。

顾刘学

2013年1月

译者简介

顾刘学

配置管理之路(ScmRoad)创始人(ID:laofo),资深配置管理专家。有多年软件行业从业经验和丰富的配置管理实战经验。2008年创办配置管理之路(Sc-mRoad),致力于在中国推广配置管理。曾在 Siemens,Websense,IGT等知名外企任职。期间一直从事软件配置管理工作,负责版本管理、构建管理、过程自动化和过程改进等。多年以来坚持组织配置管理技术沙龙,并推出了三十多期配置管理小菜鸟系列案例分析,深受大家喜爱。

苏建雷

配置管理之路核心成员,资深配置管理专家。2005年毕业于多伦多大学,获得计算机科学学士学位。现任职于橡树湾咨询公司(Oak Bay Consulting Inc.),长期从事软件配置管理咨询服务和软件研发工作,对Perforce版本控制系统的服务器配置、系统调优及过程自动化有丰富的经验和深刻的理解;同时精通 Subver-sion、Git 等版本管理工具的配置和使用。

魏朝晖

配置管理之路核心成员,资深IT项目和配置管理专家。1995年到美国留学。毕业于美国康涅狄格大学(University of Connecticut),先后获得机械工程硕士和计算机科学硕士双学位。于2000年开始从事IT项目及配置管理工作至今。于2010年5月至2012年7月曾回国两年并在IBM中国公司从事Rational开发和应用工作。现定居美国纽约。

献给本杰明·K·萨克斯

见过本杰明的人都不会轻易忘记这个有着深蓝色眼睛、和蔼的、说话轻柔但清晰的工程师。

他被家人、朋友和商业伙伴所尊敬,他以非凡的智慧、诚信、追求卓越的激情被人称道。被他的温暖、善良与慷慨感动的人,都将他深情地回忆。

他成功的职业生涯充分证明了“做正确的事”必将带来更好的质量、更高的生产效率、更高的股东价值、更加满意与忠诚的客户的坚定信念。

作为集体意识的坚定推动者,即使是在最复杂的情况下,本杰明仍能结合他的道德伦理标准与天生的乐观情绪,创造出双赢的解决方案。

在他的智慧和慈爱的指导下,我们的个人职业发展得到了极大的提升。

爸爸,谢谢您从未放弃机会去表达您对我们能力的信心和对我们取得成就的自豪,感谢您如此热切地分享生活中动人的喜悦!

Bob Aiello and Leslie Sachs

前言

配置管理(CM,Configuration Management)在任何开发工作中都起着非常关键的作用。我从事配置管理的实施和支持工作已经超过25年,本书中将讨论的大部分内容都直接来自于我个人的经验。我实施并支持过各种配置管理的实践方法并达到这样一种状态——如果建立的过程或自动化没有按照预期般运作的话,我经常会在半夜里被惊醒。作为一名教师,我向超过九百多的专业技术人员传授过工业级的配置管理工具(同样,他们在成功地完成课程后都得到了我家的电话号码,这样如果我没有教授好知识和技能,即使半夜被他们的电话叫醒,也毫无怨言)。同事和学生们总是说我对这门学科充满着激情和热爱。在我眼里,配置管理包括六大职能:

1.源代码管理

2.构建工程

3.环境配置

4.变更控制

5.发布工程

6.部署

我曾经四处寻找一本可以涵盖配置管理所有领域的书(或者是一个系列的图书),却从来没有找到过。大多数配置管理书籍要么是面过于狭窄,只集中于一个关键的区域(比如使用Ant构建代码);要么是太过“象牙塔”化,并不能提供足够的信息教我在现实世界的实际环境中如何真正实现这些功能。指出需要“让所有配置项受控”是很好的,但如果不能告诉我究竟如何用实际和现实的方法做到这一点,那么这样的建议是无法真正被应用到实践的。在本书中我试图广泛地覆盖人们需要理解的配置管理实践,并提供足够的细节以便大家不仅知道每个配置管理职能伴随而来的是什么,而且同样重要的是知道如何实施每一个配置管理功能。我会信守这个承诺。本书支持网站的URL是http://cmbestpractices.com。

配置管理的传统定义

配置管理——或在本书中的软件配置管理(SCM,Software Configuration Management)——拥有包括4个特定功能的传统定义:

1.配置识别

2.变更控制

3.状态统计

4.配置审计

这些功能早已在行业标准和框架里得到了描述,并且被很多人看做是任何有效配置管理工作的本质内容。虽然我完全同意这些功能是正确和必要的,但也发现它们使用的术语连许多技术专业人士都很难理解和领会。在这本书中我讨论了传统配置管理的功能,提出了一个我认为反映了当前行业惯例的框架来理解和执行配置管理。具体来说,本书揭示了更能反映实际日常工作中配置管理执行方式的四大传统功能与源代码管理、构建工程、环境配置、变更控制、版本发布工程和部署六大功能之间的关系。这项工作的重要部分是使配置管理最佳实践作为专业技术人员自身过程改进努力的一部分,对他们来说变得更简单容易和更实际。而我的工作正是关注于此,这样就可以让专业技术人员体验到这种过程改进带来的好处。

术语和配置管理

与其他许多学科一样,配置管理中有很多令人混淆的术语。在这本书里我解决不了这个问题,但至少我会努力不使情况变得更糟。首字母缩写SCM曾被用来代表源代码管理 (Source Code Management) 和最近的软件配置管理 (Software Configuration Management) 。一个博学的同事提醒我不要使情况变得更糟,所以当使用缩写SCM时,我仅指更广泛的软件配置管理,这是配置管理的一个专业领域(和第8章“硬件配置管理”中讨论的硬件配置管理相反)。同样,缩写CI代表的可以是配置项(Configuration Item)或者是持续集成(Continuous Integration)。 配置管理术语可能会相当令人混淆。我不能改变这种双重用途的首字母缩写词造成的混乱,因为它很普遍,但会尽可能地做到清楚明晰。配置控制和发布管理等术语也存在类似的问题,我将尽我所能地对这些术语提出明确的解释。而更重要的是解释如何在现实世界中实施这些方法。其次我希望能在网上和大家一起讨论如何使用这些术语以及它们的演变。现在对配置管理来说是一个激动人心的时刻,因为许多技术人员都开始意识到配置管理对所有一切的影响——从IT服务管理(ITSM)到整个敏捷ALM。只要有可能,尽量使用IEEE的SEVOCAB(软件和系统工程词汇)中的定义。在写本书时,该词汇表可以在www.computer.org/sevocab上找到。

为什么我热爱配置管理

我热爱配置管理,因为它是一项富有创造性并令人激动的工作,通过提高产品质量和工作效率可以显著地为技术项目增添价值。在本书中我不仅讨论了所学到的知识,而且我所阐述的经验包含了成千上万的配置管理专家诚挚地与我分享的专业知识和最佳实践,以及这些年来我对所从事的这项工作的投入。对于这些与我分享一切美好的同事,我欠他们一份感激之情。我已经撰写并发表了许多配置管理方面的文章,同时非常享受收到的反馈,尤其是那些有不同意见并提出其他实用的方法,来解决棘手的配置管理相关问题的反馈。我预计这本书将在我和同事之间产生更多的互动,尤其是通过设立的支持网站http://cmbestpractices.com。要获取有关这本书中我们所讨论的话题的最新信息,以及如果想把你自己实施配置管理的经历反馈给我,请访问这个网站。

为什么我写这本书

写这本书是想与大家分享在实际商业、工程和政府环境中实施配置管理各个方面的知识和经验。我希望你觉得这些信息是切实可行的、全面的并有助于在各种现实情况下实施配置管理。

一些配置管理专题的发展如此之快,以至于为它们写一本书成了一项十分艰巨的任务。例如就在我写本书前言的这一刻,我的“日常工作”是实施IBM的最新应用程序生命周期管理(ALM)解决方案,其中包含了一个全新的源代码管理和自动化工作流程解决方案。因此本书中只讨论如何选择配置管理工具的通用术语,而把有关特定工具的话题都放在本书的支持网站上(http://cmbestpractices.com/tools),这样可以保证信息是最新的、准确的。我也将为所写的每个字的准确性负责,因为我个人认为配置管理在道德、伦理和理论基础上都是必不可少的。虽然配置管理不是我的“宗教”,但做诚实、高品质的工作是我宗教信仰体系的一部分。我也把传播配置管理最佳实践看做良好的企业公民的典范。我在发展和支持配置管理,以及应用开发其他方面的虚拟社区中一直非常活跃。在任何给定的时刻,你都可以看到技术专家们相互提供大量的帮助,而从不考虑他们是否在为竞争对手工作。这个虚拟社区在尊重和接受他人方面是真正多元文化、多语言和普遍的。我为能够成为这项工作的一部分而感到自豪,同时希望能够通过促进配置管理最佳实践的努力使其更快地发展,以促进有效的IT控制、有责任的商业领袖力和良好的企业公民义务,从而在我们所居住的越来越小的世界里创造并分享更优质的服务和价值。换一种说法就是,应该要求每一个政府机构、金融服务公司(包括银行、对冲基金和保险公司)以及医疗、制药、国防(和所有其他的)行业的公司实施适当的IT控制,这样才能保护依靠它们服务的公众以及股东的利益。在某种程度上,写这本书是为了把这方面的努力从一种负担变为一个提高生产力和质量的旅程。以务实的方式实施IT控制——包括配置管理最佳实践——应该能够为公司的成员、股东和依靠它们服务的公众获得较高的盈利能力,这是我的信念。

课堂教材

欢迎学生和学院教授们与我们联系以获取课堂教学需要的辅助材料(如讲座幻灯片、课程内容等)。只要可行,我们愿意访问采用这本书作为课堂教学的教育机构并讲学。请联系莱斯利·萨克斯,她将协调这方面的事宜。

谁应该阅读本书

专业技术人员,包括开发经理、系统架构师、开发人员、系统工程师、硬件工程师、质量保证、质量工程、运营工程师、技术人员和项目经理都将受益于本书中的信息。首席技术官、IT审计师和公司经理们会特别喜欢建立IT控制及规范的部分。无论是敏捷爱好者还是采用经典的瀑布式生命周期,本书都将帮助你把工作做得更好。配置管理完全是关于如何成为一个好的企业员工的。企业有责任为公众利益提供和维护技术报告,而新闻媒体则是喜欢报道其中一些企业的贪婪和无能。配置管理最佳实践帮助确保全球经济运行平稳,自动取款机工作正常,空中交通管制系统保持在线状态等。如果你希望自己的技术开发工作更加高效并产生更高质量的产品,这本书就是给你的。

如何阅读本书

你至少应该浏览介绍部分,因为它提供了有关配置管理功能和整体联系的概述。然后你可以随意跳到需要得到帮助的部分。我努力把每一章都作为一个可以单独阅读和使用的单元。在实践中我通常也是这样实现配置管理的。例如,我经常直接跳到解决最迫切(由用户指出)的问题上,而不是严格地按照顺序实现配置管理的各项功能。尽管这么说,各章之间也还是存在一些相互依赖的关系,我将尽我所能地阐述它们。

本书是如何组织的

这本书共有14章,分为4个部分。第I部分包括6章,涵盖源代码管理、构建工程、环境配置、变更控制、发布管理和部署。第Ⅱ部分包括架构和硬件配置管理。第Ⅲ部分涉及你需要知道的有效实施配置管理最佳实践中最关键的人的因素。第Ⅳ部分介绍标准和规范(如IEEE、ISO、EIA)和建立有效IT控制需要的框架(如ITIL、COBIT、CMMI)。下面是每章的简介。

第Ⅰ部分:配置管理核心实践

这6个章节构成了配置管理核心实践。

第1章:源代码管理

源代码管理是所有配置管理职能中一个最根本、最基础的出发点。在这一章我们讨论了一个有效源代码管理工作的要求和一些核心概念。在源代码管理中需要知道应用程序需要的所有工件(artifact)的位置,确保它们都得到正确的识别并能够获得有效的管理。打个比方,如果我们在烤一个蛋糕,那么源代码管理可以帮助我们确保获得正确和适当分量的配料。

第2章:构建工程

构建工程包括编译进入发布的所有配置项。构建工程实践应该是高效、可靠和可重复的。构建工程也包括嵌入配置识别所需的、必不可少的版本ID到程序中。构建工程涉及混合面糊和烘烤蛋糕本身。

第3章:环境配置

环境配置涉及编译和运行时变化的处理,此变化对于代码从开发阶段提交到测试以及生产环境有其必要性。环境配置也包括对需求的配置和管理。环境配置确保准备好了用来炫耀这个烤好的大蛋糕的架子。

第4章:变更控制

变更控制有七大功能:评估变化请求、把关(比如提升发布)、配置控制、紧急变更控制、流程改动、建议变更可能对下游的影响以及变更控制的高级管理层结构。变更控制决定什么时候烤蛋糕,什么时候可以从炉中取出来并送给喜欢蛋糕的人们享用。

第5章:发布管理

发布管理涉及按照需要包装配置项,使之成为能够可靠提测和部署的组件。发布管理就像是把蛋糕放在开了窗口的精美盒子里,让其他人可以看到和欣赏你做工精细的杰作。

第6章:部署

部署应该是一个狭义定义的功能,可以按照需要发布预先包装的版本到QA或生产环境。这实际上是把你的蛋糕放上卡车准备交付给消费者(请确定你有我家的正确地址)。

这就构成了本书的第1部分,它涵盖了所有配置管理功能所需的、必要的核心配置管理竞争力。我真的开始肚子饿了,所以我必须停止把配置管理比喻为蛋糕。后面的章节组成了实施一个有效配置管理工作的8个重要辅助功能。

第Ⅱ部分:架构和硬件配置管理

架构和硬件也是配置管理需要了解的知识。

第7章:为配置管理设计应用程序架构

这是配置管理中经常被忽视的一面,涉及识别应用程序架构和配置管理之间的相互关系。不管是在一台主机或你最喜爱的手持设备上实现,配置管理的本质都是相同的。但基于应用程序的架构,实际过程可能会有显著的不同。所以在Wintel平台上实施配置管理和在UNIX/Linux平台上使用Java SOA或C++实现,可能会有很大的不同。本章让大家理解它们之间的关系。本章还介绍配置管理如何帮助实现出色的架构。配置管理最佳实践可帮助团队开发优秀的应用和系统架构。

第8章:硬件配置管理

我需要为硬件配置管理单独写一整本书,它在配置管理领域的价值和重要性还没有得到足够的认识。很多人经常要求我写写硬件配置管理。本章开始了一个肯定会很漫长的旅程。

第Ⅲ部分:配置管理中人的因素

绝不能忽视任何企业或组织工作中人的因素。这对配置管理也不例外。我曾参与并观察过实施配置管理最佳实践的许多成功案例。在结果是不可接受的甚至是真正失败了的时候,往往都是因为人的问题。本章提供了非常实用的建议,这是从现实世界中得来的如何处理配置管理人的因素的经验。这是本书中对成功实施配置管理非常重要的一个部分。

第9章:合理精简过程

我在整个职业生涯中一直专注于实施过程的改进,从中学到了过多的过程与没有足够的过程是同样糟糕的。本章讨论如何找到适当的平衡并实现足够把工作做好的过程。

第10章:克服变革的阻力

如果不能让团队接受过程的概念和实施,并在实际工作中开始使用新的、更好的工作方式,再好的过程对任何人而言都没有用。这一章是关于克服变革的阻力以及让团队接受并享受新的工作方式。

第11章:个性与配置管理:一位心理学家眼中的工作场所

莱斯利·萨克斯率先在本章中介绍有效实施配置管理最佳实践需要具备的基本人际交往能力。当我读莱斯利的文章时总感到害怕,因为她似乎总是在偷听我的谈话。如果与他人一起工作对你很重要的话,请阅读本章。

第12章:从错误中吸取教训

我在职业生涯里犯过很多错误。我取得了很多成果,但并没有像希望的那么多。我从自己的错误中学到了很多东西,本章中将分享我从错误和缺点中学到的一些个人改进经验。本章所涉及的内容很广泛,可以独立成书或者至少应该像小百科一般大小。

第Ⅳ部分:合规、行业标准和框架

本书结尾讨论建立IT控制、遵守法规、使用行业标准和框架所涉及的问题。仅次于配置管理中人的因素,需要了解和掌握行业标准和框架,同时也有助于成功实施配置管理最佳实践。这些信息将帮助你克服变革的阻力,因为你将理所当然地可以解释成千上万其他技术专家曾经审阅过或辩论过并确定为正式的、行业公认的最佳实践。

第13章:建立IT控制及合规性

建立IT控制和规范性是我自己最喜欢的话题之一。把重点放在利用这些控制及使用这些规范来提高产品质量和生产力,同时也准备好通过审核。 IT控制和规范对于许多组织来说是一个非常重要的话题,如果企业需要满足某些行业法规的话,这章提供了很多极其宝贵的信息。

第14章:行业标准和框架

我极力提倡使用行业标准和框架,但是发现许多以前写下的东西难以理解,甚至更加难以实施。这些参与建立行业标准和框架的人,需要写更多关于如何以求真务实的方式真正实现标准和框架的实用材料。这一章的重点是描述我自己应用标准和框架的个人经验,包括利用其指导以及对其剪裁、统一,使出版的指南更具可操作性等。这可能是本书中最重要的一章,希望你能把自己接受和实现行业标准与框架的经验反馈给我。

总体而言,我认为你应该把重点放在本书的第一部分,了解配置管理最佳实践的核心,然后再以任何顺序选择阅读与你所在公司迫切需要实施的主题相关的章节。

致谢

我写这本书时得到了很多人的帮助。首先,Aiello家族的编辑团队一直是让人惊叹的。我们非常像一个妈妈和棒棒糖糖果店,只是我们是写技术期刊的。我的助理编辑包括我的儿子Shmuel和Dovid(他也是我们的网站管理员);Massimo能够从不同角度看事情的能力让我用新的、不同的方式观察概念(更不用说他提供了新鲜出炉的比萨饼);我女儿Esther的创意在很多方面帮过我;我的小公主Devora的拥抱和依偎(更不用提在我后背上的轻擦)总是让我专注于工作的完成。最后,Leslie——我的终身合作伙伴——证明我们可以在多个层次上共事。

我还要感谢那些愿意与我分享他们专业知识和经验的同事。名单开头是我在IEEE配置管理规划工作组的同事,从我们的主席Chuck Walrad到该工作组的成员,他们在配置管理上曾教过我如此之多的东西(以及容忍我关于我们需要写得更清楚的尖刻言论),包括Diego Pamio、Alastair Walker、Darrel Strom、Ronata Johnson和Mike · Smith。我也从所有S2ESC委员会的同事和导师那里学到了很多关于标准的知识,包括James Moore、Carl Singer和David Schulz。给予我同样帮助的还有很多CM Crossroads的同事,包括Steve Berczuk、Mario Moreira、Ben Weatherall,当然还有Patrick Egan,我与他们一起在 CM Journal和CM Crossroads工作了这么多年。 Addison-Wesley出版社的伙伴们也是很棒的,不论是我的开发编辑Chris Zahn,还是Chris Guizikowski和Raina Chrobak。在我职业生涯的早期,我很荣幸能与Marianne Bays博士一起工作,他和我一样觉得软件工程和工业心理学家是一个很好的组合。还有更多令我感激的同事,我希望你能访问我的网站(http://cmbestpractices.com)阅读他们的文章和了解他们的贡献。

——Bob·Aiello

Bob.Aiello@ieee.org

www.linkedin.com/in/BobAiello

作者简介

Bob · Aiello是CM Crossroads的主编和软件过程改进,包括软件配置和发布管理的专业顾问。Aiello先生有25年在纽约前几名金融服务公司担任技术经理的经验,负责整个公司的配置管理,通常在企业级源代码管理工具、SOX/COBIT的合规性、构建工程、持续集成和自动化应用程序的部署等方面提供技术支持。他是IEEE 828标准工作组(配置管理规划)的副主席和IEEE软件及系统工程标准委员会(S2ESC)管理委员会的成员。他还是纽约市软件过程改进网络(CitySPIN)指导委员会的长期会员之一,担任配置管理SIG的主席。Aiello持有纽约大学工业心理学的硕士学位以及Hofstra大学的计算机科学和数学学士学位。你可以通过Bob.Aiello@ieee.org联系他或是在www.linkedin.com/in/bobaiello上与他建立联系。

Leslie · Sachs是Yellow Spider公司(http://yellowspiderinc.com)的首席运营官(COO),专门提供与本书中所描述的做法一致的配置管理相关咨询服务。Les-lie在她的专栏“个性很重要”中描绘了把个性应用于技术工作中的重要性。作为纽约州认证的学校心理学家拥有超过20年的经验,她曾在各种临床和商业环境中工作。在改善个人和团体的社会和教育功能方面,她在她所从事的环境里提供了有效的干预措施。Sachs拥有佩斯大学(Pace University)学校及社区心理学硕士学位,并在纽约Bellevue医院著名的精神病学中心实习。作为每一个人都是独特的这一思想的坚定信徒,她最近于Mel · Levine的各种思维研究所进行了高级培训。你可以通过LeslieASachs@gmail.com和她联系,或者在www.linkedin.com/in/leslieSachs上与她建立联系。

序言

在此我简要介绍一下配置管理(CM)以及如何开始实施配置管理最佳实践的一些基本信息。公司把重点放在只实行很狭窄的功能区来解决特定目标或问题是很常见的。在实践中这么做可能没有任何问题,但是了解配置管理的各个职能如何相互影响非常重要。在我的个人经验中配置管理一直都有6大职能,这一点我将在下面以及本书的各部分中说明。实现好的配置管理非常不容易,需要十分辛勤的工作。下面让我们开始这段旅程。

配置管理包括6个职能

配置管理的6个核心职能如下:

1.源代码管理

2.构建工程

3.环境配置

4.变更控制

5.发布工程

6.部署

源代码管理涉及控制每一段计算机代码,包括源代码、配置文件、二进制文件和所有编译及运行时依赖关系。我们通常称所有这些工件为配置项(CI,Configuration Item)。

源代码管理的主要目标是有效地保护所有的项目资源。我一直称之为锁定代码。源代码管理也涉及在开发过程中创建一个特定里程碑永久记录——常被称为确定代码基线——这是一个关键的配置管理功能。源代码管理也包括创建代码变体来管理并行开发、错误修正和分布在全球各地的开发。我们将讨论如何评估源代码管理的需求和计划,提高源代码管理实践的干预措施。我们也将看看在源代码管理中是怎么被过度工程化的,造成不必要的复杂性和不可靠。

构建工程涉及选择一个特定的代码变体(例如基线)来可靠地编译、链接和打包代码组件。构建工程提供了一个可重复的过程来管理(往往是复杂的)编译依赖关系,从而为项目增加价值。我们将讨论如何实施有效的构建工程来帮助改善团队的开发过程。我们还将讨论持续集成(CI,Continuous Integration)和相对不是那么严格的每日构建的价值。

在通常情况下,环境配置涉及管理那些可能随着代码从开发到测试,再到生产的推进而改变的编译和运行时的依赖关系。环境配置还涉及管理开发环境、测试环境、集成环境和生产环境本身。

变更控制有不同的类型。最普遍采用的变更控制做法本质上是一个“把关控制”功能,防止未经授权的版本被推进到生产环境(或者是QA环境)。还有一种优先变更控制(priori change control),拟对代码做出的任何变动先要经过审查(在实际改动发生前)然后再授权(或拒绝)实施建议的修改。我们讨论了优先变更控制常用的情形及什么时候它应该是项目经理或开发经理的默认任务。还讨论了组织中很常见的其他类型的变更控制。最后定义了7种不同类型的变更控制,同时还介绍了实践中通常是如何运用这些变更控制的。

发布工程涉及在构建工程功能中构建的所有组件的打包和标识。对于企业IT部门与软件供应商这可能有所不同。我们首先关注在企业IT环境中的企业发布管理,然后讨论它与软件供应商的不同点(例如部署打包的版本到客户处)。部署涉及打包版本的暂存区和上线。在IT组织中这通常是由运维团队来执行的。部署还涉及生产(和QA)环境的监测,这样可以确认有没有未经授权的更改。针对软件供应商的部署,通常是指提供打包版本发布给客户并根据客户的需要来管理更新和修补程序。

所有这些职能都是配置管理(CM)的一部分。软件配置管理是一个专业化的配置管理。同样重要却经常被忽视的是硬件配置管理,这点我们将在第8章“硬件配置管理”中讨论。

了解配置管理职能之间的关联

配置管理的6大职能在很多方面相互影响。如果没有有效的源代码管理实践,良好的构建工程几乎是不可能的。如果版本不能够正确地构建,发布管理是不会发生的,特别是对识别所有配置项来说,就像我们将在第2章“构建工程”中描述的。环境配置影响构建工程、发布管理和部署。当然如果版本不能正确打包的话,部署几乎是不可能的。所有这些功能都受到变更控制最佳实践的影响。例如一个有效的变更控制委员会(CCB,Change Control Board)将在允许批准发布之前审查配置管理计划和发布管理自动化。我们将在第4章“变更控制”中讨论变更控制的最佳实践,包括行动后审查,以确定错误是否可以通过改进任何配置管理最佳实践来避免。

配置管理的传统观点

同事们提醒我,配置管理的定义如下:

配置识别

变更控制

状态统计

配置审计

他们是绝对正确的,我并没有改变配置管理的本质。但我认为在传统的配置管理中所使用的术语不够清晰。在这本书中,我希望能够做到使描述配置管理的术语令人信服。一般情况下,我通过挑战他们给我一个状态统计得明确、合理的定义来回击。在我看来,配置标识和配置审计同样不是很直观。另外,大多数开发人员对源代码管理、构建工程和发布管理会涉及什么都有一个基本概念。让我们用传统的术语架起一座桥梁,然后更深入地了解配置管理。

配置识别是指以跟踪配置项(例如源代码、二进制文件、文档、配置文件)为目的向每个工件提供特定的唯一标识。本书将用一整章内容讨论变更控制的七大功能。状态统计(我最不喜欢的术语)是指在整个生命周期内跟踪配置项的状态。配置审计是指能够检查和识别任何配置项的确切版本。在我看来配置管理专家需要使这个术语在日常工作中更容易理解和使用。

例如,配置标识实际上是通过在源代码管理工具中用逻辑和直观的方式命名组件、流和子目录(文件夹)。构建工程最佳实践要求在二进制配置项中嵌入版本ID,这样也有利于配置审计。同时许多构建工具(如Maven)能够帮助你以逻辑和理智的方式组织代码。发布管理也同样涉及配置识别,因为必须用一贯及明确的方式命名发行软件包。

状态统计涉及在整个生命周期里跟踪配置项的状态。在实践中许多源代码管理解决方案都内置或者集成了需求和缺陷跟踪系统,这使你可以轻松地跟踪一个组件从需求(或者缺陷记录)一直到部署的演变。通过配置审计可以确切地知道在生产(或QA)环境中究竟是哪一个版本的代码正在运行。遗憾的是许多技术人员在代码离开源代码管理工具以后,无法确定一个二进制配置项的确切版本。以我的经验,配置管理要能够清楚知道运行在生产(或QA)中代码的确切版本,能够检索到用来构建它的源代码的确切版本,这样的话就可以在源代码管理工具中建立一个沙箱并对代码做一些小的修改,而不会因为错误版本的头文件或其他依赖的代码导致回滚整个发布。如果你今天还不能做到这一点,你来对地方了!本书将会讨论这些内容。

本书的前6章构成了第一部分“配置管理核心实践”,它描述了配置管理的核心职能。描述了六大核心职能与传统配置管理观点的相互关系。还覆盖了包括在作为第二至第四部分的第7章至第14章中的其他一些重要议题。下面是这些部分的简介。

本书的第Ⅱ部分是“架构和硬件配置管理”,阐述了架构对配置管理最佳实践的影响,以及配置管理对架构自身的影响。在第8章中我们将讨论本应该可以独立成书的硬件配置管理。

第Ⅲ部分“配置管理中人的因素”讨论了在有效实施配置管理最佳实践中需要理解的最基本的因素——人。许多过程的改进工作之所以失败就是因为常常忽视了这些问题。本部分有如下几章:

第9章 “合理精简过程”

第10章“克服变革的阻力”

第11章“个性与配置管理:一位心理学家眼中的工作场所”

第12章“从错误中吸取教训”

第Ⅳ部分“合规、行业标准和框架”是这本书的最后部分,涵盖了建立IT控制和遵守有关规范的问题。第14章解释了应该知道的建立配置管理最佳实践必不可少的标准和框架。

第13章“建立IT控制及合规性”

第14章“行业标准和框架”

配置管理的目标

任何配置管理的努力必须完成3个基本目标。第一个是能够轻松识别已部署到生产(或QA)环境中的代码。在配置管理术语中称为配置审计。这意味着可以轻松地确定生产中所有配置项的确切版本。第二个目标是可以检索用于创建一个发布版本的全部源代码(以及其他配置项)的确切版本(而无需诉诸“英雄”一般的努力)。第三个目标是必须能够创建一个工作区(通常被称为沙箱)来完成一个小的“漏洞补丁”而不会因为错误版本的头文件(或其他依赖关系)而造成回滚整个发布。如果不能做到这三件事,你的配置管理实践需要一定的改进。好消息是我们明确地描述了如何实事求是地实现这些目标。

第I部分 配置管理核心实践

第1章 源代码管理

本章概述

1.1 为什么源代码管理如此重要

1.2 从哪里开始

1.3 源代码管理核心概念

1.4 权限和需求跟踪

1.5 管理全球分布式开发团队

1.6 工具的选择

1.7 认识质量成本和总拥有成本

1.8 培训

1.9 建立使用模型

1.10 实施时间和风险

1.11 建立支持过程

1.12 高级特性和授权高级用户

源代码管理是保护构建成系统的所有工件(artifact)的学科。源代码管理是配置管理的核心职能(function),直接影响着团队的生产力和产品质量。不幸的是,很多公司并没有意识到建立高效源代码管理机制的重要性,缺乏实施源代码管理的能力,缺少源代码管理工具和流程。这一章将讨论如何正确地进行源代码管理。我曾经负责过多家分布全球的大公司的源代码管理工作。源代码管理必须确保产品发布的源代码永远都不能丢失。源代码需要通过一种灵活和创新的方式进行管理。每个公司的情况都是不同的,所以常常需要针对不同的开发团队采用不同的源代码管理方法。但是不同的开发团队之间也是有共性的,我们更要关注那些共性,关注那些满足团队最本质需求的方面。源代码管理通常为配置管理的其他方面提供了基础支持,尤其是在构建工程、发布管理和部署方面。

这一章总体介绍了源代码管理的很多方面,包括目标、原则和基本概念。大部分配置管理的相关职能都是以源代码库为基础的,包括构建工程、发布管理和部署,这些知识可以帮助你从整体结构上理解本章内容。本章首先列举了我和同事的几个实例,然后讲述了如何实行源代码管理,包括赢得管理层的支持。接下来,从基线以及创建配置管理时间机器 [1](CM time machine)来讲一些源代码管理的核心概念。和源代码密切相关的是缺陷和需求跟踪,这通常会与源代码管理工具和流程集成到一起。接着讨论了通过对源代码管理进行分布式开发。无论是一个大团队还是小团队,都应该考虑采用合适的工具来支持开发团队的工作。在这里我列出了几个常规的指导原则,主要涉及如何选择正确的源代码管理工具、如何通过API来扩展它,以及一些不要过度工程化源代码管理方案的提示。即便质量是“免费的”,但是想做好配置管理的工作仍然需要资金的支持,尤其是考虑到一些培训的需求。与其紧密相关的是定义一个满足团队需求的配置管理工具使用模型。我们也会讨论在实施源代码管理和建立源代码管理过程中可能遇到的风险。最后,我分享了如何对待一些配置管理工具的高级用户。

术语和源代码管理

在这本书早期的草稿当中,我用SCM 表示源代码管理,它也可以作为软件配置管理(SCM,Software Configuration Management)的缩写。[2]

源代码管理和软件配置管理显然是不同的,后者所包含的内容远不止源代码管理。

我想连贯地把源代码管理讲述清楚又不至于太过枯燥无味。我会讲一些涉及经济领域关键系统和生命支撑系统(life support systems)发布管理的例子,这样读者就不会感到太枯燥。但是考虑到这本书的可读性,这里源代码管理仅仅涉及管理源代码,甚至仅仅是代码的管理。我不愿意用版本管理(version control)这个词,是因为版本管理在传统上意义更狭窄,通常被用来描述源代码库。在讨论版本管理的时候,我通常会想到比较老的CVS、RCS和SCCS等工具。如今很多强大的源代码管理解决方案都具有过程自动化,可扩展元数据,通过复杂的分支或者流(stream)管理变体开发(variant)的功能。而我在这里把源代码管理称为对于源代码的管理或者简单的代码管理就是为了使这本基础读物尽可能地易读。

源代码管理的目标

好的源代码管理实践应该确保所有源代码安全地受控和没有重要的源代码(或者其他任何配置项)会丢失。这听上去很简单,但是回想一下千年虫问题花费巨大资源的事件,就会发现关键系统在生产环境下运行了很多年,人们却不知道它的源代码在哪里。某种情况下,我们可以去搜索一下COBOL[3]语言模板的正确版本;而其他时候,不得不从零开始重写整个系统(通常这也是正确的选择)。我们的目标是实施好的源代码管理,百分百地确保源代码永远不会丢失。

有效源代码管理的另外一个重要目标是提高整个团队的工作效率。有效的源代码管理可以同时管理多个代码线,也可以帮助在多方面提高代码质量,包括帮助实现自动化单元测试和系统级的测试,还可以建立多条代码线来支持测试工具,实现性能测试的代码,代码分析(包括静态、动态等) 或者自动化回归测试。代码管理很重要的一个目的就是提供完全的可跟踪能力。这样就可以确切地知道谁改变了哪些代码,如果有必要还可以回滚所作的更改。

源代码管理的原则

源代码管理的原则总结如下:

代码受控,不能丢失

在特定的里程碑或者时间点及时地建立基线

通过合适的分支管理代码变体

分支(变体)上的代码变化可以合并回主线(或者其他变体)

源代码管理的过程须可重复、轻量化和精益

源代码管理具备回溯的能力,可跟踪所有的变化

源代码管理最佳实践帮助提高工作效率和产品质量

1.1 为什么源代码管理如此重要

源代码管理之所以如此重要是因为既要保证资产是安全的,又要允许通过受控、可靠的配置库对其进行访问。源代码管理提供了管理源代码和把工件组装成系统的工具和方法。在配置管理术语中,我们称其为配置项(CI,Configuration Item)。所有开发团队都需要识别和控制配置项。源代码管理是公司开始实施软件配置管理的开端。良好的源代码管理可以让你一边处理长期的开发任务,一边快速发布紧急补丁。敏捷和精益的源代码管理非常重要,它为很多其他依赖有效源代码管理的工作奠定了基础。另外一个需要考虑的问题是,如果没有实行有效的(可重复的)源代码管理过程,很多糟糕的事情就会发生,包括开发中的重大中断、不必要的缺陷和大量的重复工作所浪费的时间。

当糟糕的事情发生的时候

当糟糕的事情发生的时候,我的手机铃声就会响起。于是我总结了一条,当一切进展顺利的时候,是没有人会打给我的;经常是当人们遇到问题需要帮助的时候,就会打给我;而通常是在重大问题造成源代码丢失或者其他问题的时候,就会立刻打给我。这本身可能就是我工作最好的一部分,因为它可以让我看到自己的工作在软件开发中有着显著的积极影响。这里首先需要了解的是为什么糟糕的事情会发生。源代码经常会因为下面的原因而丢失:

源代码管理工具和流程缺失

采用了不可靠的工具

用户没有经过培训,所以即便是最好的工具也不能帮助他们

聊胜于无的发布和部署过程

复杂的分支导致用户犯错

沟通不畅和团队合作很差

灵活部分太多导致复杂性增加

源代码管理工具缺少有效的行政管理过程的支持

我曾经在大公司中处理过上边说到的每一个问题。也曾经在源代码管理问题可能会导致损失数百万美元,甚至是灾难性事件(比如飞机相撞)发生这样的公司工作过。虽然很多同事都肯定规范的源代码管理带来的价值,但事实是很多人并不这么认为。经常遇到很多经验丰富的技术专家却对源代码管理最佳实践一无所知。我曾经在一些大型金融服务公司工作,在那里负责公司级源代码管理实施。虽然作为配置管理的狂热分子推广最佳实践是我的工作,但是想得到高级管理人员的认可并支持我的工作却是一项挑战。

1.2 从哪里开始

实施源代码管理最好的切入点是确定源代码管理的目标和需求。我曾经工作过的一些公司,有的是集中全公司的资源来做好配置管理;而有的则是源代码管理几乎处于自我管理的状态。大多数公司开始做都是先评估其现有的做法,如确保代码安全、控制变更、建立基线和发布,包括修复补丁。当我们进行评估时,一定要确保现有的实践和进行改进的领域是依然可以工作的。采用一种平稳渐进的改进方式可以帮助避免来自团队的抵制,并且使他们在别人审视自己团队长处和短处时感觉比较舒适。我推荐敏捷和精益的做法。例如,只进行可以让任务完成而又没有多余步骤的过程,且具备可以改变过程从而提高质量和生产力的能力(也许需要得到在第4章变更管理中讨论的SEPG[4]的批准)。烦琐死板的源代码管理过程也许在理论上听上去很美好,但是在现实世界中基本上无法工作,或者所有人都想方设法绕开。用必不可少的步骤把工作完成就可以了。如果需要,通常可以增加另外的限制(也许是一个过程中的一个步骤)来达到我们的目的。任何改进的机会,在没确定得到高层管理人员的支持之前,请不要贸然开始。无论是从下往上,还是从上往下改进,在最后一分钟情况都有可能发生改变。源代码管理中首先需要理解的是如何创建和管理代码基线。

获得高级管理层的支持

我还记得曾经和公司的CIO[5]开过一次会议,寻求他支持源代码管理的实施。实际上,他的很多直属下属已经非常支持我的工作了,但我还是希望得到他明确和公开的支持来改进公司的源代码管理过程。这位CIO[6]找来他的一位直属下属(一位高级副总裁),让他总结下部门目前的源代码管理情况。这位高级副总裁承认他的团队仅仅把代码放在网络存储上(其中的一些并没有周期性的备份)。这位高级副总裁在公司里是最了解配置管理的经理(后来,我才意识到为什么CIO把他叫进来)。这位高级副总裁被任命为我的新经理并且得到指示“公司所有的资产都必须得到保障”。看着新老板慢慢变成一个配置管理最佳实践的倡导者是件非常有意思的事情。他时常在办公室里说:“千万不要告诉我你还没有签入代码哦。”他常常和其他高级技术经理交流,确保他们能全力和我合作。

没有高级管理层的支持,你的工作将会很困难,甚至还没有启程,就已经掉进了沟里。

1.3 源代码管理核心概念

就像其他学科一样,源代码管理也有它自己的术语。可能你以前从其他一些配置管理人员那里听到一些技术行话却百思不得其解,读过这一章你就不会再对这些术语感到陌生了。这一章将会帮助你理解这些核心概念。理解了这些概念对理解源代码管理最佳实践也是非常有帮助的。

1.3.1 建立基线和时间机器

许多开发者认为源代码管理就是简单地从源代码管理工具中(一个代码库)签入和签出代码。就像大多数人认为的那样,多年前一些比较老的版本管理系统的确是这个样子。如今,虽然大多数配置管理代码库具备的可靠性和功能性不同,但都能支持变更,确保所有变更的安全。简单地签入代码到源代码管理工具中确实是必需的,但是在配置管理过程中这显然是不够的。实施有效的源代码管理,要点是提供一个虚拟的时间机器,可以随时把你带到一个特定的时间点,通常是一个稳定版本发布时代码的某个状态。对于某个特定发布,识别出其源代码的确切版本,常常称作建立代码基线。一些权威的资料中称此为代码的配置。对于用这个特定的术语,我认为它有误导性。在第3章“环境配置”中,我们将会讨论配置这个词更好的用法。

很多配置管理工具把建立基线的操作叫作给代码做标记(tagging)或标签(label-ing)。也有的工具在涉及相互依赖的多个组件时用代码快照(Snapshotting) 这个术语。基线是不可改变的。这就意味着你必须具备可以锁住标记或者标签使其无法修改的能力。这一点是非常重要的,因为我们必须有一个代码版本不变的记录,从而构建出部署到生产环境(或QA环境)中的发布。除了标记(或标签)用于创建基线,很多人用额外的标记(通常称作“生产”)来指出生产环境中的当前版本,或者指那些最后完好的构建。标记是可以随着生产环境中代码的当前基线浮动的。生产环境下的代码发生变化了,对应的标记也要变化。这是一种常见而且方便的做法。但是这种做法是不能用来替代创建基线的,因为它不能用来识别那些已经被发布到生产环境(或QA环境)下的代码。区别就在于基线是不能改变的,而标记是可以改变的。大多数优秀的源代码管理工具对标记或标签用元数据来实现。元数据是关于数据的数据。这意味着源代码管理存储库中保留着一个单独数据库,用来记录签入代码库中代码的信息。元数据包括签入的注释,相应缺陷(触发对代码的变更)的链接,以及记录了代码合并的链接。事实上,所有针对代码的变更都应该用变更请求(CR,Change Request)来跟踪,这样你就可以确切地知道为什么会进行某个变更。很多源代码管理工具利用元数据提供了一系列丰富的特性,如在很多年后依然可以为用户提供从代码库创建后的所有变更历史。在处理跟踪变更时,通常的做法是在开发前期采用一个轻量级(非正式化)的过程,然后随着软件即将发布变得越来越严格,并且要一直保持这种趋势。这是一个很好的把敏捷和精益原则应用到配置管理的例子。在第9章“合理精简过程”中我们将会讨论这些。一些源代码管理工具用分支创建基线,这也许不是最优的办法,因为分支上的代码常常是可以修改的,除非利用一些机制来锁住分支。利用分支来创建代码基线的工具之所以这样做是因为工具性能上的局限。在这类工具中创建分支要比创建标记或标签快。虽然一些配置管理工具的确尝试用分支来创建基线,但是这并不是分支的常见用法。我们将会在这章的后面部分对此进行讨论。首先,我们需要了解源代码管理中的签入和签出。

1.3.2 保留与非保留签出

保留与非保留签出,也就是我们经常说的代码是否可以锁住的问题。一些源代码管理解决方案是建立在保留签出模型 [7]基础上的。默认情况下,当一个开发人员想做修改而签出一个文件时,存储库就会在这个文件的版本上放置一个锁。其他源代码管理工具是基于非保留签出模型工作的(有时也被称为“乐观签出模型”)。这就意味着不管有多少个开发人员同时签出并且修改代码,存储库都不会在该文件上放置锁。我比较倾向于使用保留签出模型,因为这可以主动地让我知道我是否正在尝试和别人修改同一个文件。乐观签出模型可能会造成额外的合并代码的工作,如果开发人员知道他们在试图同时修改相同的文件,这种形式的合并本来是可以避免的。当其他人试图和你修改同一段代码时,一些现代的源代码管理工具会通过提高可视化的方法来避免这种问题。另外一个非保留签出的用途是简单地得到一份可写的(可能永远不会签回到存储库的)文件副本。

1.3.3 沙箱和工作空间

大多数源代码管理工具都有私有沙箱和工作空间的概念。在私有沙箱里,你可以隔离你的工作,然后签入你的变更,如果有必要,还可以合并更改到另外一个分支(通常被称作代码集成)。普遍的做法是开发人员有多个工作空间(或沙箱)来协调和安排自己的工作。分支提供了一个安排工作的有效方法,并且提高了开发人员的生产率。

我的第一个沙箱

当我介绍配置管理和如何使用源代码管理工具的时候,我常常提到小时候在沙箱里玩的经历。像很多其他男孩一样,我喜欢牛仔、军队士兵和其他玩具娃娃。我家隔壁是一个小女孩,她时常到访,在我的沙箱里玩她的玩具娃娃。不可避免地,我在玩牛仔的时候扔得到处是沙子,然后苏西就跑回家抱怨我把沙子弄到她的娃娃上了。结果你也知道了,给我带来了很大的麻烦。之所以提到这件事情,就是想说明不应该让别人进入你的私人沙箱,否则你就会遇到麻烦。在隔离并且受控的环境中工作是软件开发中提高生产率的首选方法。良好定义的处理代码变体的方法是提高生产率的另外一个方面。

1.3.4 变体管理

变体(variant)是指同一产品不同版本之间具有很多相同功能,但是又有区别的情况。优秀的源代码管理工具最重要的特性之一就是很容易地支持相同代码库的多个变体。这样就可以很容易地支持在相同代码库下仅为了某些特殊需求而对代码子集的修改。创建变体常常是创建多条并行的开发线来实现,通常被称作分支。创建分支的原因有很多。例如,想写某个软件显示一个国际时钟。这个时钟最基本的功能都是一样的,无论此时钟是运行在Windows、Mac、Linux或者是Unix的机器上。但是,为了使这个时钟可以工作,需要一个函数去读底层的操作系统时钟。因此,编码了一个特定模块来处理那些为每个操作系统定制化的系统调用。

在实践中,我们假设Linux 上通用的共同代码将放在主分支(main branch)[通常被称为主干(trunk),主(main)]。然后我们创建了一个变体(例如,Windows,Mac,和 Unix分支),这些变体都包含了主干上的所有代码和另外一些必需的修改(例如,针对特定系统时钟的操作系统调用)。在这个例子中(如图1.1所示),所有分支唯一不同的代码是系统时钟查找函数。通过这种方法,可以有效地管理代码的不同变体。

1.3.5 复制分支与增量分支

一些源代码管理工具要求所有的分支是主干上所有代码的一个复本。如图1.2所示,这种做法通常叫作拷贝分支。其他工具则是仅仅包含发生改变的代码(通常叫作增量分支)。

主干是分支的基础。有时分支会很复杂,尤其是当人们开始用分支管理所有的开发活动时。一个常见的做法是每修复一个缺陷就建立一个分支。这种做法常被称作建立功能分支。

1.3.6 如何处理缺陷修复

支持缺陷修复通常是一个最常见的创建分支的需求。例如,你正在写“Hello world”程序时,想在屏幕上也显示一个漂亮的时钟。这是一个现在版本不需要的额外功能。在将程序发给客户几天后,你发现每个月第三个星期二的时间都是错误的。图1.3 展示了这种情况。虽然时钟不是这个发布版本的内容,但是我们不能容忍屏幕上的时钟是错误的。

程序的其他部分工作得都很好,所以只要把时钟隐藏起来,让客户看不到错误的时间就可以了。在产品的下一个版本中,我们会发布一个带有全新时钟的控制台,这个问题就不会存在了;而目前我们需要为客户提供一个快速的修复,把这个错误的时钟给隐藏起来。现在的问题是我们已经在版本3上做了很多只有在下个版本中才会发布的更改,可那已经是2个月后的事情了。而与此同时,我们需要发布一个临时解决代码问题的缺陷修复,如图1.4所示。

1.3.7 流

流是另外一种强大的管理代码变体的方法。虽然和分支十分类似,但是流常常具有强大的管理代码变体的特性。如下是其中的一些特性:

清楚的使用范例

清楚直观的层次组织结构

流之间管理和操作变更集的能力(有时须借助工作空间)

通过快照建立代码基线的能力

找到并获取组件的某一个特定基线的能力

找到并获得特定快照的能力(例如一个或者多个组件的基线)

强大的安全授权和认证机制

有助于流设计和使用的可视化流拓扑结构图

可提供追溯能力的完整历史信息

例如,一些源代码管理工具可以层次化地组织流。也就是说,有一个父级流(常被用作集成)和子级开发流。一些源代码管理工具可以允许你动态地变更子流的源。这个特性很有用,可以让你在接口还未完成的组件上十分方便地工作。例如,创建一个代码桩(Code stubs or mocks),把其放在一个临时流中供使用,一旦那些代码被真正实现后再变更流的源。变更从子流到其父流的提升,也被称为交付(deliver)。通常的做法是在交付特定变更集(Changesets)到上一级父流的时候,子流首先要从父流更新 (有时也称作变基,rebasing) 中得到最新的更改。最佳实践的做法是变基代码到私有的工作空间,进行测试确保成功构建,然后交付变更到父级流。流通常有流向这个概念,以便变更集可以从一个流复制(或者说提升)到另外一个流。当有开发流和集成流的时候,通常会选择这么做。发布管理团队(RM,Release Management)通常有一个自己控制的单独分支来确保可以独立地构建、打包、发布代码和部署(常常由运维团队来做)。没有流,就需要额外的工作来将源代码管理工具和缺陷或变更跟踪系统集成到一起来组织分支,特别是如果想让每个分支仅实现一个功能。在实际中,流比分支提供了更多的功能。流有点复杂,但是更强大,因此值得去学习和理解它们的用法。

1.3.8 合并

分支是一个很强大的特性,许多开发员发现分支可以帮助他们更有效地工作。问题是我发现很多开发人员忘记拉出分支的代码需要经常合并(Merging) 回主干。例如,在一个分支上修复了一个bug,通常在主干上也需要修复(假设这两者之间是相关的)。从分支合并回主干通常被称作内合并(Inner merge),如图1.5所示。

有些时候,需要从主干合并代码到缺陷修复分支,通常被称作外合并,如图1.6所示。

1.3.9 变更集

变更集(Changesets) 是一种可以方便地将一个或多个对代码库的修改组织到一起的方法。大多数支持变更集的源代码管理工具都可以提供应用或者回退变更集的功能。提交变更集(又被称作签入)通常是一个原子事务,这意味着整个变更都可以成功地签入(或出现错误,完全地回退)。我非常感激变更集带来的好处。还记得某个漫长的夜晚,当我试图去提交几千个文件的时候,在签入的中途却停止了的困窘。跟踪哪些文件已经被成功签入和哪些文件在签入中途失败需要再次提交是非常痛苦且容易出错的事。考虑到变更集,一些源代码管理工具提供了管理整个代码库的能力,这样如果不小心失误了,就可以容易地回退。通常可以把一个变更和一个缺陷或者一个需求关联到一起,我们将会在下一节详细讨论具体方法。

1.4 权限和需求跟踪

跟踪缺陷和需求变更是一项非常重要的功能,这可以告诉你为什么做了一个特定的变更或查明是否不经意地错过了一个必须做的变更。在第13章“建立IT控制及合规”中,我们会讨论可跟踪性的重要性。一些配置管理工具已经集成了缺陷或者需求跟踪的功能;另外一些工具需要一点编程的工作,通过应用程序接口(API)和外部工具集成到一起。通过API去集成是最后的手段,因为这种集成方式将需要大量的工作,并且可能会很复杂。在实践中,经常发现通过API写的脚本和扩展有很多意想不到的问题。这些让人很痛苦的问题包括时序问题和原因不明的副作用等。总体而言,千万不要过度设计代码管理解决方案或者流程。

培训至关重要

培训对于配置管理工作非常重要,但不幸的是常常被人们所遗忘或者故意缩短。这是非常错误的。在培训时,配置管理工程师不但需要解释工具是如何工作的,还需要介绍流程和使用模型。这意味着,不仅仅需要工具供应商的培训,本公司配置管理团队中某个人也有责任记录和设计使用工具的流程(通常被称作使用模型)。不管最终选择的工具是不是目前最好的,都应该对员工进行培训。培训往往决定着工具使用的成败。

1.5 管理全球分布式开发团队

源代码管理可以帮助协调分布式开发团队之间的工作。如图1.7所示,在伦敦、纽约和孟买有三个开发团队,源代码最佳实践可以有条理有逻辑地帮助协调每个人的工作。

在地理分布式的工作环境中,全球性软件开发的挑战是能否协调好工作和使变更受控。对于同一房间里坐在对面的两个人,协调好工作和使变更受控都不是件很容易的事情,而对于那些身处不同国家,工作在不同时区,有着不同语言、文化、追求的团队来说,这就更难了。

源代码管理可以在各自的分支上帮助组织这些工作,使其可以在一个地方被完成,进行审查,然后通过受控和可追溯到方式合并到主干。还可以通过建立一个海外分支(Offshore branch),上面所有的变更经由国内的团队审查,最后合并到主干(最后的结果要复制回海外分支)。另外一个方法是允许国外团队具有相同的源代码库访问权,就好像他们工作在国内一样。常见的最佳实践是通过使用变更请求(CR,Change Request) 来沟通和跟踪这些变更。变更请求也就是我们通常看到的工作项(work item)、任务、产品改进(enhancements)或者缺陷(defect)。每一个变更请求的类别都有不同的生命周期,从而可以建立和实施不同的流程,这样就可以有效地进行代码控制。好的源代码管理实践可以为团队建立有效的控制和适合的流程,可靠地控制离岸开发(offshore development)。我推荐建立一些试点项目,然后尝试一个或多个方法,通过实际效果看看哪个更适用于团队。随着时间的推移,源代码管理逐渐细化,团队也在慢慢改变和成熟,适用于团队、促进工作的有效流程也会逐渐地建立起来。

正确的策略包括良好的协调机制,进度可跟踪性和高的可见性。

1.6 工具的选择

在实施任何一个源代码管理解决方案中,工具的选择都是一项非常重要的任务。选择一个源代码管理工具需要考虑众多的因素。针对这一主题,我会在这章只讨论最基本的方面,而在我们的网站上(www.cmbestpractices.com/tools)专门讲了一个工具的选择部分作为对本章的补充。这样一来,就可以保证内容的时效性,同时可以允许我的同事说出他们的观点,尽管很多时候这个题目都会变成激烈的宗教般的争论。

首先可以观察到的一个事实是,目前市场上有众多优秀的源代码管理工具。感谢厂商们开发了如此众多商业的和开源的优秀源代码解决方案。我的经验是,所有的工具供应商都值得赞誉,因为他们不仅仅关注短期的销售产品的目标,还关注开发和传承高效的最佳实践。即便是一些“不好”的工具在某些特定的情况下都有它们的地位。最重要的事情是开始评估自己的源代码管理解决方案的需求,然后以开放和务实的态度去评估哪些解决方案最符合团队正在做的工作。所有的源代码管理工具都是不一样的,也就造成了某些工具在某个特定项目中可能会表现得好些或者坏些。一些工具的功能不是很丰富,可集成到一起的其他工具也不是很多;而另外一些可能学习曲线很陡峭,可一旦用户接受了全面培训和得到支持,工具就会体现出巨大价值。

许多常用的源代码管理工具最大的问题是缺乏测试和控制代码库自身内部完整性的能力。例如,我就看到过在一些非常著名的源代码管理工具中,代码没有任何迹象就直接丢失了。在工作过的某大型金融服务机构中就发生过这类问题,代码丢失导致公司蒙受了重大损失。

在开源软件和一些大型知名厂商的商业软件中,都出现过类似的问题。因此,把金融交易系统的源代码放在这样的工具中也许不是一个万无一失的方法。最好的方法是,保留额外一份代码的备份,以便用来构建和发布产品。

下面是在选择源代码管理解决方案时应该考虑的方面:

容易使用(相对于学习曲线来说)

具有分支的能力

代码合并(图形界面和命令行都支持)

变更历史

建立基线(例如标记和标签)

变更集

管理工具(例如可检查代码库的完整性)

成本(包括总拥有成本)

有效的培训和支持

与常见IDE 的集成

完整的 ALM解决方案(相对于与第三方工具的集成)

良好定义的使用模式

开源软件与商业软件

产品成熟度

供应商承诺

可扩展性和开放的API

实施的时间和成功的风险

一开始最重要的是定义选择有效配置管理解决方案的目标。然后,通过上面提到的和其他未提到的方面来选择合适的源代码管理解决方案。有时候基于仅仅一项或者多项标准就可以排除某个工具。例如,很多公司的开发团队非常大(数百名到千名)分布在全球各地,包括美国、欧洲和亚洲各地。在这种情况下,源代码管理工具真正显示出了其价值所在,因为它可以帮助保护代码、组织开发工作,并且可以知道团队每天都在做什么。有时,当团队真正需要更强大的工具提供某些高级功能的时候,就需要提前规划好必要的培训和支持。在某些公司,需要在同一代码库中支持多个变体,这就要求工具必须支持复杂分支和代码合并。

随着更改的增多,查看所有更改的历史记录很快就会变得很复杂。大多数公司都需要能够很容易地查看这些历史记录的功能。所有的开发团队都要有建立基线的能力。在某些有IT控制和法律合规监管的公司,这是一项基本的要求;相反,在我读研究生做课后作业时,建立可靠基线就不是那么重要了(虽然那时我也使用源代码管理工具)。例如,如果期望一组确定的变更可以很容易地应用到(此分支)或者回滚时,那么变更集是非常有用的,哪怕这仅仅影响到你是否可以按时交付作业。许多组织也非常看重是否有一个可靠的供应商或者开源社区支持这个工具。

1.6.1 开源软件与商业软件

在选择工具的时候,我们还应该考虑公司在开源和商业配置管理工具上是否有强烈的偏好。哪一种类型的工具都有优点和缺点。一些开发人员认为开源软件好,因为源代码是可见的,而且有活跃的用户社区在开发更多的功能;而商业软件的拥护者则认为商业软件的支持和功能更好些,因为有一个很大的专职研发团队在开发这个软件,通常这意味着可以从一个技术一流的公司得到支持。还有一种结合了上面两种方法的情况,即商业软件供应商愿意对所有人公开自己的源代码,并且允许他人可以通过定义好的API写代码来拓展功能。另外一种很流行的做法是提供一个免费的(或者不受任何限制的评估用)版本,其中某些功能或者许可证的数量是有限的。选择商业或者开源代码管理解决方案是一个非常有趣且很热门的讨论,双方的很多看法都很有道理。针对这一点,在这本书的支持网站上有很多更深入的探讨(www.cmbestpractices.com/tools)。尽管如此,我们还是要考虑公司对开源或者商业工具是否有某些强烈的偏好,公司里的采购部门是否把它当作选择工具的标准之一。

1.6.2 产品成熟度和供应商承诺

我曾经使用过很多在短期内几乎很少有大改进的十分成熟的产品,既包括开源的也包括商业的。我也使用过很多采用了尖端技术的工具。工具太新了,以至于都没有一个明确的安装说明文档。成熟的产品中,很少会遇到难题和使用问题,但是这些工具往往具备的高级功能也少,无法极大地提高程序员的工作效率。有时我们想提高工作效率但又不想在源代码管理中太冒险,这时就需要在软件成熟度与使用产品风险间取得平衡。在采用最新最好的源代码管理工具集之前,一定要确认供应商已经做好准备,能够且愿意给你提供支持去维护这套先进的源代码解决方案。

1.6.3 可扩展性和开放的API

当有同事想通过开放的API或者 shell 脚本去扩展或者修改源代码管理工具时,我一般都劝他们不要着急,想好了再做。虽然使用脚本(例如触发器)可以有助于强化流程,但是支持定制工具花费的时间和精力也是必须要考虑的。我看到很多写脚本或者封装工具的工作最后都惨败了。通常最好是与供应商合作,制定出一个好的解决方案,然后和整个用户社区共享。起初虽然没发现自己写的脚本有什么问题,但是当开源社区使用并且给你提出很多意见和建议后,这些脚本就会变得更加可靠。如果你是唯一一个知道这些脚本如何工作的人,这对于你和你的公司都不是一件好事。

1.6.4 不要过度工程化源代码管理

在配置管理中,我看到的最大的错误就是开发人员用心良苦过度地工程化源代码管理工具。源代码管理工具有许多很酷的特性,很多技术人员一看见就感到兴奋,于是一旦开始工作就尝试去自动化一切。有的时候,这会导致源代码管理方案加进去很多花里胡哨的东西,导致整个系统常常无法正常工作。如果整个系统因为那些花里胡哨的东西而无法工作恰巧发生在负责的技术人员度假时,就会给公司造成很大的麻烦。把过程自动化,集成到源代码管理工具中是不错的想法,但这应该仅限于在自动化完成这项任务的情况下,不要添加更多其他的东西。源代码管理解决方案应该体现敏捷和精益的原则,从而达到更好的效果。

例如,创建一个分支来支持一个缺陷修复是一个很不错的想法,但是如果针对每个缺陷都要创建一个单独的分支就会太复杂。实际上没有什么不可以违背的原则,但还是建议尽量保持你的流程精益,仅仅自动化那些十分必要的部分。

另外一个常见的错误是很多人写脚本会在源代码管理工具命令行外再封装一层。这种做法的错误就在于用户通常都不知道这个工具正在做什么。因为脚本隐藏了工具的功能,常常替代了实际的培训和清晰的流程。如果真的要写脚本自动化源代码管理工具,我建议脚本要清晰地显示出每个执行的命令和命令的输出情况,这样就不会隐藏源代码管理工具的实际操作。这样的做法可以让你清楚地知道脚本做了什么,也有利于工具的培训。对于成功地实施任何源代码管理工具和能自动重复地执行任务的脚本,培训都是最关键的因素。一定要确保能够为团队提供足够的培训,使他们了解如何充分利用配置管理工具。脚本不应该替代培训,更不应该隐藏工具的功能。当脚本隐藏了工具的功能,开发人员就无法了解如何使用源代码管理工具最基本的功能,而这常常会导致错误和降低工作效率;同时,还要有人维护和升级脚本,这通常是件耗时且易出错的活儿,无论对于个人还是开发团队都不是件好事。选择合适的工具,使用模型和过程很重要,培训则更重要。同样重要的还有考虑影响交付优质产品的各个方面,包括质量成本。

1.7 认识质量成本和总拥有成本

我的职业是管理源代码管理工具,工作中时常会发现高级管理人员没有意识到每天维护这些工具的成本。这些成本包括人员和要管理的资源(例如备份)、实施、培训和支持用户。

曾经在一家公司任职,管理层要求我让所有人员都用上一个业界最强大的源代码管理工具。公司已经为这个工具付了一大笔钱,但是使用率却在下降。随着时间的推移,我成功地支持了分布在世界各地的700个开发人员使用的1500个代码库。那时,在我的团队里只有两个人提供全职的支持(我和另外一个人)。要做好支持整个公司的工作真的不是一件容易的事。其他经理甚至告诉我,我应该罢工,让他们知道什么是不可能完成的事。今天这家华尔街的金融服务公司已经不存在了。我认为它关门的原因之一就是关注短期利润而不是长期目标。我认为提供源代码管理工具和流程是一项长期的战略资产,需要考虑总拥有成本(质量成本),包括成本管理和工具支持。没有资金支持的源代码管理工作就像是开车行驶在从纽约到洛杉矶的路上,却声称无暇在中途加油。迟早,你会意识到短视是一个巨大的、显而易见的、费时的、让人尴尬的错误。

建立源代码管理预算

一定要把运营源代码管理职能的所有费用都考虑进去,包括服务器,硬盘,存储源代码管理工具的外围设备,所有必需产品的许可证,维护配置管理工具和其他产品的费用,支持,备份,灾难恢复产品和服务等。此外,培训经常被忽视和投入资金不足。

1.8 培训

在选择源代码管理工具时,还要考虑供应商或者第三方机构是否有系统性的培训。有时我更倾向于那些非供应商提供的培训,因为我希望从一个没有偏见的角度去了解如何有效地使用工具,尤其是涉及工具缺陷和限制等。供应商有时认为培训只是销售过程的延伸,所以他们的培训总有种推销的味道,不能让人从公正的角度去看工具。我曾经参加过一个培训,这位讲师以前就是在供应商处工作,并且自己确实写了一些代码。他直率地讲了以前代码的一些错误,这些错误很多时候都是由于公司没有给他足够时间导致的,因为那时的首要任务是向外声称工具能够具备某个功能。他还说,一旦产品销售出去并且被使用,供应商也没有让他返回去花时间提高产品质量。供应商提供的培训也许很不错,但是有时第三方提供的培训会更客观、更实际、更有用。

鲍勃的培训方式

我自己首选的方法是在公司内部选择一个人去参加供应商提供的培训,然后制订一个针对本公司的培训计划,包括所需的过程和推荐的使用模型。因为公司内已经有人受过培训,对这方面很精通,可以在公司内始终对工具进行支持。这种做法显著地降低了支持用户的成本。我会把电话告诉那些成功接受过我培训并完成训练的人。我总是这样和同事约定:“如果我不能教你做好工作,每当你无法从源代码管理工具中签出代码的时候,你都可以半夜打电话把我叫醒。”考虑到工具的重要性和影响,培训可以使工具更容易被使用,更容易被接受。好消息是,现在很多工具的功能都很易学且易使用,并且都有强大直观的用户界面。

在软件开发的很多情况下,大家普遍都使用集成开发环境(IDE)。现在大多数配置管理工具都提供了强大的与流行集成开发环境集成的能力,这样就可以在集成开发环境中直接签入、签出代码了。但是我注意到在某些科技领域,这种集成的方法根本不可行,集成之后系统充满了问题,根本就无法使用。所以在购买任何源代码管理工具前,都一定要尝试使用下,确保你的集成开发环境可以和它集成起来,工作效率不会受影响。另外一个很重要的功能需求是通过源代码管理工具可以查看到在任何特定时间发生的变化。作为一个支持和促进配置管理最佳实践的人,这是我个人认为始终需要的功能。除了培训和易用性,源代码管理工具需要具有丰富的提供可追溯性的功能,从而方便地进行需求和缺陷跟踪。

1.9 建立使用模型

在公司内,设置专人定义整个团队如何使用源代码管理工具是非常重要的。在理想的情况下,这个人从整个团队那里得到信息,明确地定义出使用模型是决定选择使用哪个工具非常重要的部分。可以预料的是这是一个反复迭代的过程,并且肯定会有很多不同的意见。有的时候,你可能喜欢某个特定的工具,但它的使用模型也许过于复杂(或者不够复杂,但是缺少所需的功能)。一个常见的例子是,把源代码管理工具和缺陷或者需求跟踪工具集成到一起提供可追溯性的能力。

需求和缺陷跟踪实现的可追溯性

曾经遇到过一个国际银行系统偶尔会错误地四舍五入1日元。钱不是很多,只是非常令人讨厌。如果这不是违反了行业规定,日本财政部要关闭这家银行,估计谁也不会认真对待这个问题。所以,每次遇到四舍五入1日元这个问题,就要有人立刻去修正它。每次都是这样去修复,但是从来没人记录最后一次是如何修复的。如果有一个和源代码管理工具集成的需求或者缺陷跟踪系统,所有这些变更都会通过特定的需求或者缺陷ID(或者变更请求,Change Request)关联到一起。而且可以通过在缺陷系统中搜索“1日元四舍五入”,找到六个月前为修复这个问题到底做了什么变更。一些源代码管理解决方案是一套应用生命周期管理(ALM)解决方案的一部分;而其他一些方案则仅仅是具体的源代码管理工具,通过与市场上其他工具集成一起提供服务。需要考虑的是,我们是需要一套完整的ALM解决方案去支持整个软件开发生命周期,还是仅需要一个垂直的解决方案来满足特定的需求。选择正确的工具很重要,但更重要的是定义明确的使用方式。

1.10 实施时间和风险

在采用任何一个源代码管理工具之前,都要考虑部署、培训和支持团队将要花费的时间和精力,还要考虑任何可能阻碍进展的风险。例如,拒绝参加培训的开发人员是一个严重的风险因素。在尝试部署任何配置管理工具之前都要重视这种现象。有的时候选择一个稍差的工具并不是一件坏事,通常更好的方法意味着更高的风险,使得公司不愿意接受和支持新工具。

1.11 建立支持过程

实施配置管理最佳实践,很重要的一条就是建立一个团队来帮助实施、支持和管理源代码管理职能和其他将要讨论的五个方面。把配置管理团队的服务作为一种共享资源非常重要,这会给整个开发团队带来更多的价值。这个小组通常被称为发布管理服务(RMS,Release Management Services),最初仅仅是做发布代码的工作。当一些开发者意识到他们总介入一些配置管理工作时,建立发布管理服务团队就很有必要了。实际上,配置管理涉及整个应用程序和产品的生命周期。我的经验是把发布管理团队作为一个服务和一个支持部门,参与到应用生命周期的每个阶段。其中可能遇到的小问题是,实施配置管理最佳实践时,开发人员不遵守发布管理服务团队的指导方针,这个时候我通常会把这一问题反馈给高级管理人员。源代码管理无疑是整个配置管理生命周期中最重要的一环。

1.12 高级特性和授权高级用户

很多专业技术人员是源代码管理工具和规范的高级用户,而另外一些人仅仅期望以最少的精力把工作做完就可以了。团队中的每个人并非都要成为一个源代码管理工具专家,但应该认可和授权那些在源代码管理方面想提高的用户。我从同事那里学到很多经验,所以鼓励你授权给那些认真对待配置管理最佳实践且愿意分享所学的专业技术人员。良好的配置管理经验是会传播的,配置管理员应该努力宣扬和弘扬这种传播。

结论

源代码管理是配置管理最佳实践的核心。在保护源代码的同时,利用配置管理工具和规范可提高工作效率和产品质量。在选择源代码管理工具和购买某些源代码管理功能时,一定要小心行事。培训和定义良好的使用模型有助于确保配置管理职能有效地执行且容易被接受。认真对待特殊的需求和满足这种需求时可能发生的风险。支持愿意深入了解源代码管理的人,鼓励他们分享自己的经验。源代码管理是一项团队活动。如果开发人员愿意去学习和分享配置管理最佳实践,源代码管理流程就会更加高效。

第2章 构建工程

本章概述

2.1 为什么构建工程如此重要

2.2 从哪里开始

2.3 构建工程的核心概念

2.4 建立构建职能的注意事项

2.5 构建工具评估和选择

2.6 质量和培训成本

2.7 把构建做得更好

2.8 构建工程师的角色

2.9 架构是构建的基础

2.10 建立构建过程

2.11 持续集成与每日构建

2.12 构建工程的前景

构建工程是高效地把源代码生成二进制文件的学科。构建工程可以很简单,例如仅仅执行一下 Makefile 或者 Ant 脚本;也可以很复杂,比如写一个完整的支持底层技术架构的构建框架。在本章中,我们将会讨论构建工程中遇到的挑战、构建工程的核心技术,以及一些选择合适构建工具的方法。我们也会讨论如何挑选和培养构建工程师。如果公司里现在没有一个合格的构建工程师,建议利用已有的资源去完成现在的工作。配置管理中构建工程是最具挑战性和最有意义的角色。

本章全面介绍了构建工程的方方面面,包括目标、原则、基本概念等;介绍了构建工程最佳实践中如何理解和运用这些核心概念,包括版本ID、依赖关系、生成构建。还讨论了当前流行的很多工具,以及质量成本和相应的培训。这里介绍了构建工程师这个角色,同时讨论了建立一个可靠可重复的构建过程和应用框架中构建工程师的重要性。本章也涵盖了持续集成最基础的内容以及构建工程的前景。构建工程是配置管理的核心职能,本章将在这些方面进行深入的介绍,希望能给大家一个正确的方向。

构建工程的目标

构建工程的目标是能够可靠地编译和链接源代码,在最短的时间内生成一个可执行的二进制文件。构建工程包括识别确切的编译和运行时依赖,以及其他任何特定的技术需求,例如编译器(链接器和受控环境)开关和依赖。构建工程提高了整个团队的开发质量和生产效率。我认为构建团队应该把自己看作一个服务部门,把研发团队当作自己的主要客户。但是,构建工程师要有权力去强制执行公司的规章制度。作为构建工程师,我们会提供服务去支持研发团队的活动,但是我们的主要目标是保护公司的资产。

构建工程的原则

构建工程的原则包括以下内容:

构建易理解,可重现

构建速度快,过程可靠

每个配置项都可识别

代码和编译依赖易确定

代码仅需构建一次,就可部署到任何地方

构建异常易识别和管理

可快速定位构建失败的原因(并解决)

2.1 为什么构建工程如此重要

构建工程可以重复为研发团队准确地编译和链接代码。构建工程可以快速地重新构建一个版本,不但能提高研发团队的工作效率,还能促进软件的开发。快速构建对于任何软件开发都是很重要的,尤其是敏捷和迭代开发很早就强调了这一点。正确的构建可以避免很多将对开发团队和整个公司产生重大影响的问题。我看到过一个发布和部署中的严重问题,甚至影响到了世界经济(第6章会详细介绍这个例子)。构建工程中的问题也会产生同样的影响。构建工程在提高应用程序质量的同时,还可以提高整个公司的生产效率。

为什么优秀的开发人员其构建却有问题

构建工程有时候是项很令人头疼的工作。比如,有的公司开发团队甚至经常长时间无法获得一个可靠的可执行文件。原因可能有以下几个:第一个原因是没有实行可靠的源代码管理实践。这导致了我们不知道怎么能得到一份版本相同的源代码。第二个原因是构建过程太复杂且不可靠。第三个原因是不支持新的构建需求。比如,需要对现有自动化构建过程大做修改后才能支持新的构建需求。我觉得最好的方法是重新开始,而不要在自主研发的解决方案里挣扎。这些自主开发的解决方案只有那些顾问可以理解,可惜他们早已离开去支持下一个合同了。我在很多大型企业都看到过这些情况,包括银行和对冲基金公司。

2.2 从哪里开始

首先就是要研究现有项目的构建过程。有时你会发现研发团队已经写好了构建脚本,可能采用的是Ant,Maven 或者Make。通常情况下,现有的构建过程只能部署产品到研发的测试环境中。构建工程师就要在此基础上进行修改,从而支持QA环境和产品环境。现有的构建脚本可能会频繁失败,这个时候就需要研发的支持来予以解决。构建工程师的工作就是确保这些脚本可靠,易维护。有时需要深入理解一个应用程序,才能理解它是怎么构建的。有时候,产品的架构太复杂了,这时候构建工程师就需要和开发工程师合作,一起完成构建系统。请记住首先要做的就是评估现有的构建工具和过程,然后再改进,实施构建工程最佳实践。

2.3 构建工程的核心概念

成功的构建工程都包含如下职责:首先构建的依赖关系易被理解且受控,基线是可识别的,在此基础上可重复地生成构建。每次构建都是针对配置项的活动。构建包含配置项,并且可产生新的配置项。几乎构建中的任何东西都可以被认为是配置项。构建工程师的首要任务,是核实所有的可执行文件、重要的脚本、文档和文本文件已被正确地识别和标识。

2.3.1 版本ID和标记可执行文件

构建工程师既能轻而易举地识别出源代码基线,也能轻松地确定构建产物的版本。这包括所有的二进制文件(中间代码和运行时模块)以及所有的配置文件。正如第1章配置管理术语中提到的,我们称这些产物为配置项,无论它们是源代码、二进制文件还是配置文件。在理想的情况下,一切事物都有一个不变的版本ID作为标识。实际上我们已经习惯了通过查看应用程序的“关于”框看产品的版本。所有的文档,包括发布说明、教程和技术说明等,都应该包含版本信息。这样,我们就能很容易地知道它们对应的是源代码的哪一个版本。

2.3.2 不可变的版本ID

对可执行文件最基本的要求就是给它们一个不可变的版本ID,然后提供简单的程序来检索版本ID。对于C++程序,通常可以把版本ID设置成一个静态的char 类型变量,然后把它打在可执行文件上。对于JAVA程序,可以写一个JAVA类去定义版本ID,然后把版本ID写到构建过程生成的JAR,WAR,或EAR的manifest文件中去。关键在于确保通过可执行程序的版本ID可以很容易地追溯到生成它的源代码版本。

2.3.3 打上版本标记或者标签

在某些情况下,发布构建的时候,我们会把源代码管理工具的版本标签或者标记打在可执行文件上。因为在源代码原理工具中,当用于发布的构建标签或者标记被锁定时,基于标签或者标记的构建也就确定了。那么当需要重新构建时,我们就可以基于这些信息重新构建出基线版本。某些时候,标签或者标记不容易被锁定,很容易被认为是开发人员删除了标签或者标记,然后把另外一个版本的代码附加到先前的标签或者标记上。此时,如果构建已经准备发布给QA了,那么我们就要记录下当前版本库的修订版本。

更改两行修复缺陷

好的构建工程实践可以让你很容易地识别出发布的构建是由哪个版本的代码生成的。也就是说,看一眼生产环境下正在运行的可执行文件,就可以确定是哪个版本的代码生成的这个发布。如果坚持遵循这一最佳实践,修复缺陷时就可以随时创建一个沙箱(sandbox),然后从代码基线获取正确的版本,更改两行就可以解决了。

在遇到头文件版本错误或一些编译依赖问题时就可以确定根本不需要代码回滚,改两行代码就可以修复。这种做法十分方便和高效。

2.3.4 管理编译依赖

很多构建失败都是由于环境问题造成的。比如某个环境变量是用某开发人员的账号设置的,而两个月过后准备发布代码时,在正式环境下用其他账户构建时就会失败。不仅仅是源代码,所有的编译和运行时依赖都必须被了解且受控。这就意味着每次构建时,构建脚本必须设置所有的环境变量,以确保所有的构建依赖都是正确的。

2.3.5 独立构建

避免出现严重错误的办法之一就是独立构建每个发布版本,并且每次构建都是从顶级到下级,所有配置项都重新构建。这通常由一个独立的版本发布管理团队完成,或者由持续集成中的自动构建过程完成。许多规章制度不但明确要求职责分离,而且要求有独立的构建、打包和发布控制过程。看起来好像有很多工作,但是从合规的角度来说,这是一个最基本的要求,大多数金融服务公司、国防部门、医疗部门和政府机构都有这样的要求。曾经有一个研发经理实施了我的最佳实践后,很快地就建立沙箱,获取基线,快速修复问题并部署到生产环境中。他对这种做法非常高兴和兴奋,以前需要很多时间才能解决的问题,通过实施适当的IT控制就可以迅速做出反应。我们将会在第13章详细讨论限制访问生产环境。本书后面还会提到一些其他提高生产效率和质量的实践。

2.4 建立构建职能的注意事项

根据我的经验,在开发团队中实施构建工程最佳实践之前,必须要打消大家的疑虑。有时,对现有构建过程复杂度认识不足,可能会导致人为错误、代码缺陷、不断返工、生产效率低等问题。造成这种现象的大部分原因都是技术上的,另外可能是过程上的。而一旦有问题,就会有人把责任推到构建过程上来,建议简化构建过程。曾经遇到过在某产品中使用的技术特别复杂,而专业技术人员深陷于复杂的技术泥潭之中,并把它弄得更复杂了。显然,我们都希望尽可能地把事情变简单,做到万无一失。但是现实情况是,很多专业技术人员都想通过能处理复杂问题来显示他们的实力,结果把问题弄得更复杂了。

2.4.1 推广独立构建

独立构建可以验证代码库中基线的配置项。通常监管部门都要求有独立构建,以降低任何可能带来问题的风险。也就是说,构建工程师要说服开发团队改变一些构建过程,来避免可能出现的错误。开发人员认为构建工程师从头开始重新构建一遍应用太浪费时间。也许开发团队知道在产品被提交到QA或者生产环境之前要通过独立的环境进行构建是监管的要求,但是很多工程师还是会窃笑,觉得这项任务就是浪费时间。如果构建工程师是开发团队中的一员,这将有助于理解构建当中涉及的技术问题,但是这样常常会把自己放到一个尴尬的位置。很多时候,构建工程师都要和开发团队进行妥协。总之,管理层应该在公司规章制度允许的情况下,让构建工程师可以尽快地得到他们想要的信息。构建过程要尽可能地快并且自动化,这样其他人不需要等很长时间就能得到想要的东西。为了做到这一点,构建工程师应该负责第一时间查看和解决构建中的问题。

在构建的工作中经常会遇到的问题是构建过程过度工程化,导致构建过程太复杂。通常情况下,公司有一些工作已经自动化了,但是其中仍有很多让人头疼的部分,以致没有一个人懂得这个构建到底是怎么工作的。这就导致公司里的其他人不敢修改,更无法提供支持。通常来说,这就是构建过程过度工程化的直接结果。下一节,我会分享我是如何解决这个问题的。

2.4.2 过度工程化构建

我发现很多公司不可靠、太复杂的构建工程已经严重阻碍了其开发工作。接连不断构建失败警示我们这个团队可能无法成功地发布一个版本,这成了项目和公司最大的风险。有时候这都是由于软件配置管理做得差或者几乎没起到配置管理的作用导致的。但是更多时候是因为构建脚本本身太复杂,几乎无法维护造成的。通常的问题是一个很聪明的人创造了一套非常复杂的构建过程,团队里其他任何人几乎都无法理解这套过程和自动化程序,更无法进行支持。常见的情况是,构建工程师尝试使用构建功能时,他希望可以传进去一个变量作为参数(例如,开发、QA或者生产三个值),这时就可以根据参数生成需要的配置文件。在第3章中,我们将会详细介绍一些关于创建配置文件的最佳实践。而开发者设计构建工具的时候,他希望相同的代码可以运行在各个环境当中(例如,开发环境、QA环境和生产环境)。但是他基本上不了解软件测试的过程,也不了解生产环境下部署和配置的情况。因此,软件测试时用的是一个版本构建,而当我们把产品部署到生产环境下时,却用了另外一个版本。这是一个很大的问题。我们一定要确保软件测试和生产环境下使用的是同一版本的源代码,例如都是从基线发布出去的。但为每个环境都重新构建,这显然是不现实的做法,因为这种情况下可能绕过IT的控制,而且没有进行一致性评估。还有一个常见的问题就是,在构建过程中同样的文件被放到不同地方,名字一样,但是大小却不一样。这会让看到的人相当费解。之所以那些聪明勤劳的工程师开发出来的系统这么复杂、这么难理解,是因为他们根本没有从软件测试的角度考虑需求或者不理解这个工具的本质需求。

2.4.3 保持正直和诚实

有些时候,公司管理层要求做的事,并不都是完全正确的。一次,某大银行要求我保证所有的开发团队都是符合2002版萨班斯法案404节IT监管要求的。在这种情况下,我的责任是审查所有团队,要求所有开发团队都要依据ISACA[8] COBIT[9]模型的要求,建立合适的变更和配置管理流程。这项工作对于我这种配置管理狂热分子来说是再兴奋不过的事了,我帮助他们满足了合规要求的同时,还提高了产品的质量和工作效率。我在项目最后阶段也加入到了这个项目。项目要在一段很紧张的时间内完成SOX法案 [10]的合规要求。这时我的老板,SOX法案的合规专员和我一起开会,当我提出要为每个团队做配置管理评估的时候,他们都非常吃惊。他们认为审查是否符合SOX法案才是第一位的。这一次虽然他们有些不了解我的做法,但是我成功地说服他们同意我去做配置管理评估。评估结果是四分之三的团队都使用了正确的软件配置管理流程。然后我请求给予更多的时间进行审查,最终的结果是他们都是合规的。六个月后再次做审查时,我发现一些团队已经倒退,重新拾起了先前的做法。我觉得这已经不是技术能解决的问题了,而是一个办公室的政治问题,所以我最终离开了这个公司。不久,这个大型金融服务公司就倒闭了。我觉得倒闭的原因在很大程度上是公司短视,太关注短期目标,偷工减料,最终酿成了灾难。就如同当年的安然事件一样,但是我会尽力让公司做正确的事情,并符合所有行业法规。

2.4.4 隶属研发部门引起的利益冲突

另外一个实例是,研发团队的头儿是我的直接领导,而我帮助团队构建和部署一个大型的国际贸易系统。这个系统用的技术十分复杂,因为我和研发团队一起工作,理解这个系统的速度快了很多。我们一遍又一遍地构建、发布和部署交易系统,从未发布和部署过失败的构建。然而,项目截止日期日益临近,甚至都已经发展到按时发布产品和研发部门经理奖金挂勾的情况。研发团队不断地修复缺陷,然后构建,最后部署上去,一遍又一遍地进行着。上线的截止日期到了,我却被要求去部署一个因含有缺陷而未经过QA团队核实的系统。也就是说,我们测试了系统的某个版本A,并得到QA团队的批准,可以进行部署;但是实际上我们部署的却是另外一个版本B。我找到研发部门的头儿,也就是我的直接领导,解释说我们不能构建和部署一个未经QA团队批准的版本。他当然不希望因为错过最后期限而丢了丰厚的奖金,所以他坚持发布这个版本。无可奈何,只好找到他的直接老板并解释了事情的原委。他的老板当即表示,最新的版本应该走正常的测试流程,必须要经过QA团队的确认才可以上线。因此,项目延期两个星期,但是我们遵守了正确的流程,避免了上线后可能出现的问题。可是从此以后,这个研发团队的头儿觉得我是在和他对着干,而不再配合我,我的工作也就变得很难进行下去了。

2.4.5 组织结构的选择

在理想的情况下,构建工程团队应该向足够高级别的管理层汇报,避免自己受到办公室政治和那些只关注自己利益经理的影响。经常看到构建团队是QA团队的一部分,但是远离开发团队会阻碍交流合作,以致无法快速有效地理解要构建的系统。因为在部署应用程序的时候我的职责和系统管理员(SA,system ad-ministration)的职责有些重叠,所以我需要同时向系统管理部门和数据安全部门的经理汇报。还有很多其他的组织结构,但是无论哪种组织结构,都要确保构建工程师可以得到他们所需要的信息,经授权后可以去操作,以便有效地保护公司的资产。同样重要的是,构建工程团队负责人应该是一个遇到问题愿意去沟通的人,如果有必要,也是敢于说不的人。比如版本中还有严重的问题没有修复,在这种情况下就不能发布版本给客户。我个人的经验是,构建工程师是一个十分具有挑战性的职位,需要高级管理层提供必要的支持,以便构建工程团队可以做好自己的本职工作,保护好公司的重要资产。

2.5 构建工具评估和选择

目前有很多好的构建工具,也有很多相关的最佳实践教程。这些教程可以指导你建立一个可靠、可扩展的构建流程。这里将会讨论一些工具和最佳实践,你可以有选择性地实施其中一些来支持公司的开发工作。我把针对工具优劣的争论内容放到了支持这本书的网站上,大家可以查阅(http://cmbestpractices.com/tools)。目前软件开发中主要有几类比较流行的构建工具。不久以前,有段时间构建自动化仅仅意味着使用Make(也许还有一些shell脚本)自动执行构建过程的每一个步骤。这种方法可以很好地支持C和C++ 的构建。但是在实现的时候,要注意底层不同平台带来的差异性。我在HP-UX、Solaris、AIX和Linux上都用过 Make。Make是1977年由斯图尔特·费尔德曼在贝尔实验室创造的。 GNU Make 相对于Make进步了一些,解决了一些跨平台的构建问题。值得注意的是,Make不仅仅可以用在 C 和 C++的项目上,某些情况下也可以用来构建 Java 的项目。

2.5.1 Apache Ant进入构建舞台

作为Apache Tomcat 项目的一部分,Ant 最初是由詹姆斯·邓肯·戴维森(James Duncan Davidson)创造的。一开始Ant是和Apache Tomcat被捆绑在一起使用。到2000年7月的时候,Ant 1.1 才作为一个单独产品被发布。Ant 与Make截然不同,它是基于 Java 实现的,而 Make 仅仅是通过一些Shell脚本来构建的。

2.5.2 Maven

Maven 一开始是作为Jakarta Alexandria 项目的一部分在2001开发的,在后来却作为一个单独产品被发布了。 Maven 目标是成为集中整个项目信息源的标准化的构建框架,并自夸:“需要写很多行Ant XML 代码的活,Maven 可以轻松搞定。”Maven 是基于约定优于配置的理念,也就是说 Maven 希望使用者遵守它定义好的声明和约定来使用Maven。Maven 通过生成框架的机制可帮助你初始化一个符合约定的项目。Maven 生成的框架代码可帮助你使用不同的Java 框架。Ma-ven 的生命周期是非常重要的概念,理解好每一个生命周期,有助于使用 Maven的更多功能。在这本书的支持网站上( http://cmbestpractices.com),我提供了更多的资料,大家可以参考。

Apache的网站上说 Maven 是依地语的词,意为“知识大成者”,但是我更愿意把它翻译成“专家”。至于Ant 和 Maven 哪个更好这样的争论,我已把它放在我的网站上( http://cmbestpractices.com)。但是我想说,即便像我这种深入使用过Ant、Maven 和 Make的人,也很难回答它们中哪一个更好一些。

2.5.3 Maven与Ant

Ant 需要大量的 XML 代码来描述到底要做什么。从这个意义上说,Ant 比Maven更注重过程。 而Maven 在项目描述上采取了截然不同的做法。Maven规定应用程序应一直遵守一个特定的结构。这也就是前面所说的 Maven 倡导的约定优于配置的概念。 Maven爱好者认为开发人员必须以 Maven 的标准来组织应用程序结构。这样Maven 就知道资源都存储在哪里,哪些是需要构建的,剩下的 Maven就可以自己完成了。Maven 1.1使用的是 Jelly 脚本,而Maven 2 使用的是纯 Java的 XML。Maven 有一个定义好的生命周期,理解了Maven的生命周期就可以更大地提高构建效率。在实践中,许多构建工程师使用Ant 插件来拓展 Maven 的功能。Maven 预先为你定义了项目框架,尽管对于复杂的构建,这个框架可能不是特别顺手。当在两个都备受推崇的工具中选择时,开发者一般都有各自的偏好,有些甚至是固执己见。在曾经工作过的几个公司里,我用 Maven 1.0.2和 Maven 2.0构建过规模相当大的产品,当然也用过Ant 6 和Ant 7。我认为每个备受推崇的工具都有自己的优点和固有缺点。

2.5.4 使用Ant生成复杂构建

Ant 被用于生成复杂构建时,很快就会陷于一堆笨重且杂乱的XML中。 Ant脚本要好好地组织结构,尽量减少每一步之间的依赖,以便其都可以单独地执行。例如,调用源代码管理工具的代码内嵌到 Ant 构建项目的目标(target)当中。 这就导致每次调用Ant 编译Java类的时候都会调用源代码管理工具。其实这是没必要的,因为有可能我在本地做一个构建,而源代码早已经在本地工作空间中,这时根本就不需要重新获取一遍代码。此外当团队从一个源代码管理工具转到另一个时,就必须检查整个项目的 Ant XML文件,修改每一个涉及源代码管理操作的部分。实践中应该避免这样的Ant 组织结构,尽量使每一步都相对独立。还有一点要谈的是当源代码管理系统关机维护或者备份的时候,构建团队就不能构建项目的情况。好的构建工程脚本应该采取结构化的方法,创建开发沙箱后,可以单独地进行编译。构建不应该依赖于源代码管理工具是否正常运行。

2.5.5 持续集成

持续集成是现在十分流行的最佳实践之一,它要求在开发人员每次提交变更到代码库后,都立刻进行构建和部署代码。虽然一开始持续集成流行于敏捷开发领域,但是现在在很多非敏捷开发环境下,持续集成也是一个广受推崇的最佳实践。持续集成系统一直监控源代码管理系统中的变化,一旦有变更就会立刻触发构建。构建的结果会发布在显示面板(dashboard) 上,包括导致最近系统故障的变更、构建失败的变更等。每个持续集成系统都是不一样的,在公司中使用之前,应该根据其功能来评估是否适用。由于这些工具升级很快,我想把更多的讨论放到这本书的网站上,以供大家讨论和分享(http://cmbestpractices.com/tools)。

2.5.6 持续集成系统

目前有很多非常受欢迎的持续集成系统可供选择。关于“哪个工具是最好的”的讨论永远都是无尽头的,大家可以到这本书的网站上发表看法(http://cmbestpractices.com/tools)。持续集成是配置管理中最令人激动的领域,有很多很强大的开源解决方案,当然也包含很多扩展功能的商业产品。在有新代码提交到代码库时,先进的持续集成系统都支持自动发起构建的功能。另外,也可以安排一个特定的时间,例如每天晚上自动触发一个构建。持续集成系统通常都可以识别出最新的变更,尤其是最后造成构建失败的变更。大多数持续集成系统都使用 XML文件进行配置。有些系统已经具有强大的图形化界面,这使管理变得更容易。

2.5.7 集成开发环境

集成开发环境(IDE)可以让开发人员以迭代的方式快速开发应用程序,帮助他们提高工作效率和产品质量。集成开发环境通常会安装一些插件,就可以在里边使用编译器(例如C++ 或 Java的编译器)来构建项目。构建工程师面临的挑战之一就是开发人员只知道在集成开发环境中构建产品,这就会导致其很难写出一个可以在命令行下执行的构建脚本。一些集成开发环境可以生成在命令行下运行的脚本。在集成开发环境中构建出的应用程序是绝对不可以部署到生产环境(或者QA环境)中的。因为通过集成开发环境生成构建的方式在本质上是不可重复的。最大的问题就是开发人员常常不了解那些由集成开发环境隐藏了的构建过程。

2.5.8 静态代码分析

构建工程通常被认为是进行静态代码分析的最好时间点。因为构建工程师控制所有源代码的构建和发布,所以可以插入一些打桩代码(instrument code)生成一个用来进行静态代码分析的构建。自霍尔斯特德复杂性度量(Halstead complexity metrics)成立之初,我就做过静态代码分析的工作。使用静态代码分析工具可找出可能存在的安全漏洞,并且在代码发布之前修复。构建工程师往往是唯一的可以把所有代码都放到一起构建出发布版本的人。构建工程师还可以通过脚本和适当的修改构建出整个系统,这对于静态代码分析来说都是必要的。显然,用来做静态代码分析的构建通常包含打桩代码,所以这样的版本通常也不能部署到生产系统中去。

2.5.9 构建框架

我曾经使用过很多不错的构建框架,它们都可以提供广受好评的结构化方法来开发一个完整的构建解决方案。大多数产品都可以让用户制订构建计划,分配构建代理(build agent),并把所有的结果反馈到统一的构建显示面板上。这些产品也许是整个应用程序生命周期(ALM)解决方案的一部分,也许是扩展了某些特定功能的扩展插件。这个时候就需要花费一段时间评估可用的构建解决方案,然后再为公司选择合适的构建工具。

2.5.10 构建工具的选择

选择合适的工具是一件非常重要的事情,通常包含估计实际需求、进行工具评估和协调团队达成共识。在实践中,许多专业技术人员发现很难选择一个适合自己的工具。这首先就要找到支持项目中所采用技术的工具。下面是一些例子:

GNU make 支持C/C++

Ant,Maven 或 GNU make 支持Java

MS Build 或 GNU make 支持 .NET (e.g.C#)

关于构建工具更多的讨论,大家可以参考本书的网站http://cmbestpractices.com/tools。

2.5.11 对比优缺点达成一致

在选择工具的时候,应该尽可能地让所有利益相关者都加入到这个过程中。在一些公司当中,是开发部门做决定说我要选择哪个工具;而另外一些公司,则是以更民主的方式来选择。很久以前,一夜之间大家都开始谈敏捷开发。心理学家发现自我管理的团队更有效,尤其是获得高生产效率和高产品质量方面。自我管理团队,顾名思义,有权力来评估和选择自己团队使用的工具。达成共识是任何一个成功的自我管理团队的核心竞争力之一。每种方法都有优点和缺点。我的建议是哪种方法适合自己公司的文化,就以哪种方法去选择工具。总体而言,在软件开发工作中,调研工具,对比工具优缺点,分享评估结果,最后达成一致往往是选择工具或者流程最好的方式。

2.6 质量和培训成本

快速可靠地构建平台需要资金的支持,包括购买相应的硬件和软件系统。许多公司发现采用虚拟化技术提供构建和测试环境效率高且非常划算。除此之外,一定要为将来的培训和必要的资源留下预算。构建工程非常需要充足的资金支持。

2.7 把构建做得更好

在很多公司,已经建立了良好的构建流程,我的角色就是帮助改善现有流程,以支持更多的环境(比如QA环境和生产环境)。有段时间,我发现有的构建过程只有技术背景很强的专业技术人员才能理解和使用好,且在使用中极易出错,结果也不可靠。构建工程的目的是提供一个可靠、快速、清晰的构建过程来支持产品的构建和部署。

2.7.1 鲍勃的构建秘方

这一小节将介绍建立可靠的、可重复的构建过程的秘诀。在很多环境中,我的方法都可以帮助开发团队成功地完成构建,并且部署到QA环境(生产环境)中去。通常情况下,我都是在项目或者公司濒临失败时才加入其中。如果采用我的方法,通常可以在3个构建之内解决他们的构建问题。我的很多技术都是基于在纽约大学工业组织心理学研究生课程中学到的方法。在其他学科学到的知识帮助我建立了一套独特的方法。团队失败的原因有很多,只要是构建工程的问题都可以通过改进构建来解决。

2.7.2 测试驱动的构建

构建工程师不仅要随时关注构建的过程,还要关注开发人员调试构建、解决构建问题的方法,甚至是每一步的操作。有这样一个实例,我观察到每当构建失败,开发人员就会查看某个特定的 JAR 文件是否被创建,是否包含在了 WAR 文件当中。我并不完全了解为什么有的时候这个 JAR 文件没有被创建成功。之后在构建脚本中,我也加入了这一步骤,在以后的每次构建中,构建脚本都会检查这个JAR文件是否存在。如果某步检查到这个 JAR 文件没有成功生成,那么构建脚本就会提前通知我们,JAR文件缺失将会导致构建失败。虽然这样做可能有点小题大做,但是主动测试构建将会帮助你生成可靠的构建,并且一旦出现错误你也会很早就得到提示。开发人员一般都坚信自己的构建是完全没问题的,因此并不会主动地去测试自己的构建。

2.7.3 信任但仍要核查

作为构建工程师,我的做法是“信任,但仍要核查”。也就是说我们信任生成的每个构建,但仍然需要对它们进行测试。当你的构建结果事关他人的健康和安全时,这就尤其重要。也许一个构建的错误可能就会导致飞机相撞或者其他更严重的事件。他人的健康和安全都是至关重要的事情。例如,航空工程师花费了大量时间制造准确、易理解的控制器,以避免出现问题。

2.7.4 飞机的驾驶舱

在某些领域,经常需要付出大量的工作去避免可能出现的错误。之所以这样关注整体质量,是因为任何一个错误都可能导致有人丧生。就像本节前面讨论的一样,采用这样的思路设计驾驶员座舱就是为了减少错误的发生。上面的控制器都容易理解,接口也很清晰。我觉得软件工程师需要向飞机驾驶舱设计师学习,把它应用到应用程序构建、部署过程和自动化的设计上。曾经尝试创建可以避免错误,且可以主动检测构建问题的构建系统。构建和部署的自动化需要想办法避免可能的错误发生。我做过多次构建工程改进的项目,每次都是把团队从不稳定、不可靠的构建状态中解救出来,成功地实现一个完全可重复的可靠的流程。下面列出来一些重要的关注点,供设计或改进构建系统时参考:

构建过程的每一步都要易读且易执行

自动检查构建过程中可能的出错点,核实构建是否成功

结构化组织自动构建过程,避免一个错误破坏整个构建

通过状态公告板和构建报告展示构建状态

2.8 构建工程师的角色

构建工程师通常需要有软件开发的背景,扎实的技术知识,一定程度的编程能力(包括 Perl、Python、Shell 和 XML),可以建立可靠、可重复的构建过程。工作中很难找到一个合适的构建工程师,因为具有很强开发背景的专业技术人员通常都更愿意做项目而不愿意写构建系统。构建工程师是一个非常有意思也很有挑战的职位。其他的开发人员很容易使用到新的技术、新的框架,而构建工程师却并不总能把前沿的技术应用到工作中去。但建立一个高质量且高效率的构建工程的确是一项十分需要创造力的工作。

在软件开发过程中,构建工程师发挥着举足轻重的作用。但是这个职位的角色随着团队的不同也会发生变化。我曾经不断地构建和发布构建来满足开发的需要。有时,开发人员会被分派一些构建工程的短期任务,例如写构建的基础架构。这就要求开发人员既了解应用程序的架构,也熟悉构建工具本身。关于一些常用构建工具的选择,大家可以参考这本书的网站(http://cmbestpractices.com/)。

2.8.1 了解构建的项目

资深的构建工程师需要在精通相应构建工具的同时,深刻理解应用程序的架构。例如,我曾经用特定的 JMX 资源处理J2EE服务器接口的配置。在其他的技术中,相同的功能是由不同配置文件处理的。开发人员具备专业的知识去配置这些,但是构建工程师往往缺少这些技能,所以就需要在构建过程中明确定义出这些需求,参考构建过程文档来完成这项工作。构建工程师的工作常常要涉及很多技术。也许第一天,我深入研究C#,.NET和SQL Server 等与平台紧密相关的工具和技术。第二天,我就转向J2EE SOA、部署特定的网页和应用服务器。下一个任务也许是使用Make 构建C/C++开发的嵌入式软件,以及相关的硬件和固件。构建工程师需要有很强的技术知识,还要能和开发人员合作完成某项任务。这就要求构建工程师能快速掌握很多具有挑战性的新技术。

2.8.2 与开发人员合作

曾经遇到一个涉及 Java 对象持久层框架的项目,以前从来没有接触过。我的任务是为这个将被发布的项目写构建脚本。于是开始学习它,想快速地掌握这门技术,可还是对很多东西没有概念。在这种情况下,与开发人员合作去完成构建框架就显得很有必要了。期间也遇到了一些挑战,比如习惯了集成开发环境的开发人员,不知道如何在命令行下构建他们的应用。在这种情况下,我会设定好构建的入口和出口标准。比如,构建脚本的入口就是在开发环境中通过命令行来生成构建。这样,这个脚本就可以修改为支持QA 环境和生产环境。修改过程中最重要的事情是保证构建可靠并且可重复。

2.8.3 招募新人

招募新人最好的办法是将一个新的开发人员培养成为构建工程师。新的开发人员也许对创建可重复性构建的知识一无所知,但是这没有关系,我可以教他。只要他有相应的专业技术,哪怕没有技术,有强烈的学习意愿也是可以的。事实上,在我看来所有的开发人员,都应该在入职培训的时候了解一些构建工程的内容。这将有助于开发人员处理架构中的问题,也有助于我们发现那些真正理解构建工程和发布流程的团队。

2.9 架构是构建的基础

构建工程师常常忙于建立可重复的构建流程。成功完成一个项目后就会更忙,因为有更多的项目需要协助。开发技术不是永恒不变的,其他专业技术人员可以很快地学习和使用新技术架构。而构建工程师接触新技术并能立刻应用到构建方面的情况却不是很多。我就有过这种现学现卖的经历。第一次是用 Hibernate处理数据持久化。我注意到构建过程中有一些异常,例如源代码管理工具状态和往常不一样。于是在项目会议上对这种情况进行了说明,告诉研发技术经理我应该在技术架构组的通知名单里,如果有架构方面的变更,我应该得到通知。由此可知,了解应用程序的体系架构是正确构建的基础。

2.10 建立构建过程

实施构建工程最佳实践是一项非常具有挑战性的工作。构建工程师可以选择有益于公司的实践;也可以选择最好的工具去建立可重复的构建,实施持续集成。但是实际工作远不止此,构建工程部门还需要为开发团队提供培训和技术支持。我的经验是和研发团队合作,解决构建和部署过程中的问题,然后转到幕后做支持,把日常的工作还交给开发团队来负责。这里有个前提就是公司的合规部门允许这样做。曾经一家实施 SAS-70的公司认为可以接受这样的做法;但是另外一家公司认为这不合规,不能接受。在一些公司里因为合规的要求,需要单独建立一套独立的构建和部署环境,这是可以理解的。但此时切不可忘记,构建团队还有另外一个职责就是帮助开发人员建立起可重复的构建和部署过程。而有的公司虽然没有合规的限制,但实施配置管理最佳实践时还要实施适当的访问控制,这有助于提高工作质量和团队的工作效率。

建立公司级的标准

最佳实践也包括建立一套公司的标准,比如正确地使用构建工具,包括Ant,Maven和 Make;也包括正式的命名规范、记录构建脚本的文档。例如,一些公司要求每个团队所用的 Ant build.xml 须和顶级的保持一致。公司级的标准应该以合作的方式去起草和推广,这样才能最大程度地提高质量和工作效率。

2.11 持续集成与每日构建

持续集成是一个相当流行的软件开发实践。现在,人们时常把持续集成和敏捷开发联系到一起。实际上,即使开发团队使用的不是敏捷开发的过程,持续集成在他们之间也已经非常流行。另外一个很明显的现象是很多研发团队并不需要签入构建(commit build,check-in build),也就是说并不需要每次有代码签入代码库都要立刻触发一个构建。很多时候,每日构建已经足够用了,而且也容易实现。持续集成经常会发起很多没必要的失败构建,导致显示面板上出现很多没必要的失败记录。某些构建可能需要几个小时才能完成,这时持续的构建就会导致一个很长的构建队列,最终使有些构建无法完成。在我工作过的公司,我认为选择每日构建可能会更好。我的观点是尽可能采取更轻量级的流程。恰好够用的过程改进是我最推崇的,这也是建立有效开发过程最实际最直接的方法。

2.12 构建工程的前景

构建工程是公司的关键职能部门,应该得到公司的重视和支持。大量制定的标准和架构都强调了它的重要性,业界也开发了很多工具来支持构建工程。在第14章,我们将详细介绍标准和框架。在配置管理的大背景下,构建工程逐渐被人们所了解。最近几年构建工程的日益成熟和受到的关注更加速了它的发展。也许当初公司是为了合规的要求才实现的构建工程,比如想实施IT访问控制。但是除了通过认证或者审计,应该看得更远一点。为了过程改进,我们需要弄清构建工程以及所有和它相关的核心能力,这样才能真正地提高工作效率和质量。

结论

构建工程最佳实践可以提高整个开发团队的效率,产出更高质量的代码。构建过程应该自动化,可回溯,快速,并且尽可能地简单。当遇到项目使用的技术十分复杂时,应该把构建分成几个可控制的部分。如果构建过程中可以自我检测错误,开发活动就会更有效。在选择工具时,要谨慎并且考虑构建职能如何更好地融入公司的文化。如果你在构建工程中发现哪些实践是有效的,日常构建中还需要改进什么,希望可以联系我。

相关图书

云原生测试实战
云原生测试实战
Kubernetes快速入门(第2版)
Kubernetes快速入门(第2版)
Kubernetes零基础实战
Kubernetes零基础实战
深入浅出Windows API程序设计:核心编程篇
深入浅出Windows API程序设计:核心编程篇
深入浅出Windows API程序设计:编程基础篇
深入浅出Windows API程序设计:编程基础篇
云原生技术中台:从分布式到云平台设计
云原生技术中台:从分布式到云平台设计

相关文章

相关课程