作者介绍:韩伟,1999年大学实习期加入初创期的网易,成为第30号员工,8年间从程序员开始,历任项目经理、产品总监。2007年后创业4年,开发过视频直播社区,及多款页游产品。2011年后就职于腾讯游戏研发部公共技术中心架构规划组,专注于通用游戏技术底层的研发。
在互联网时代,软件工程经历了从瀑布式到敏捷式开发模式,并不断的讨论和实践。而一些软件公司,在面对项目进度压力时,往往都会用上“敏捷”类的开发模式来摆脱压力的侵袭。
一.老板最喜爱的员工是最令人头疼的
有很多公司的老板在进度会议上都会大力提倡“敏捷”。敏捷本身就有“快”的意思。我觉得“敏捷”这个词真的很讨老板喜欢。加上这个开发模式讲究快速修改产品,快速发布产品内容。因此互联网公司的老板们都觉得这个敏捷模式是最合适的软件开发模式,纷纷要求开发团队学习并且执行。
开发团队也希望学习这种敏捷模式,他们看了很多书,开了很多会,然后真正的执行起来,却发现只是额外多了许多工作,而真正的开发进度并没有觉得有很大的进展。从此老板一说敏捷,给大家的感觉就是:要加班了。
因此,我们有必要重新从本源上来了解一下“敏捷”。敏捷一词来源于2001年初美国犹他州雪鸟滑雪圣地的一次“敏捷方法发起者和实践者(他们发起组成了敏捷联盟)”的聚会。然而,这是一个软件开发方法的名字,不表示用了就一定会加快开发进度。敏捷开发方法本身并未规定任何的开发流程,也没有模板文档,他是一个宣言。
1. 人和(人与人的)交互 优先于过程和工具
我们是否习惯通过无数的评审、邮件、工单来沟通工作上的事情?甚至是QQ的留言?我们能否真正的改变自己的沟通习惯,面对面的,或者共同的看一个屏幕的去谈工作。我承认舒服的转椅有极大的粘性,让人的屁股不愿意离开,但是如果你尝试去面对面沟通,你会立刻唾弃QQ和邮件。对于我来说,任何来往回复文字少于100字的邮件和QQ,都是没价值的。用这些打字的十分之一时间,就已经能把事情沟通的很好了。有些公司里面使用冗长的“流程”管理来推进工作,这些工作需要按流程规定逐级批复,这简直就是皇上批折子的工作作风——缓慢、闭塞、脱离实际。
2. “可以工作的软件”优于“求全责备的文档”
有一些概要设计的模板有10来页的框架和目录,就算你把文档写的面面俱到,你还是可能在开发的时候碰到一个能困扰你10来天的逻辑BUG。与其要求文档把所有的事情都预计到,还不如早点让软件跑起来,然后有什么问题立刻解决。更重要的是,客户是看不懂你的概要设计文档,在你满头大汗的做完之后,可能发现完全不是他要的东西。但是如果你有一个很简陋的但可运行的软件,客户马上就能理解你想要做的东西,并且提供有价值的意见。既然如此,你何苦去写那些既没人看,也没人看的懂的长篇大论呢?
3. 客户协作 优先于合同谈判
我们做的每件事都有成本,这个是显而易见的,但是如果我们做的是无用的东西,客户也不会为此买单。就算我们能通过各种手段,把合同谈下来,那也不代表客户会真心实意的成为我们的长期伙伴。他们在付款后可能会觉得被骗了,然后再也不愿意去投资了。因此软件开发要实现真正的价值,除了客户付款外,还要和客户一起来做这个软件。只有客户参与,软件才能真正满足需求。而软件需求是如此的变化多端,在开发者和用户之间的理解又有着深深的鸿沟,只有勇于去填平那些鸿沟,精准的找出需求,才能开发出真正有用的软件。对于一般的企业应用软件,我们往往能和我们的客户面对面的讨价还价,但是在互联网软件领域,更多时候根本没有可供谈判的客户,要找到愿意协作的用户,还要额外付出成本。
4. 随时应对变化 优先于循规蹈矩
变化是唯一不变的东西。这是一个哲学命题,但是在软件开发行业里面,却是一个日常可见的真理。我们害怕变化,诅咒变化,努力抵制、削弱变化,心理想着客户永远别再提新的想法,这其实是很愚蠢的。因为变化才是商机,有变化,就需要开发人员的工作。谁最能适应变化,谁就能在竞争中脱颖而出。适应变化,是软件开发人员技术水平的最高标准。
宣言还包括了以下一些原则:
-
对我们而言,最重要的是通过不断交付有价值的软件来满足客户需要
不断交付软件,不断更新版本,这不仅是最有效的获得准确需求的手段,还是市场竞争中最有力的手段。客户会因为你的努力而对这个软件和团队产生期待,从而愿意继续支付费用。因此不管什么借口,都不应该影响我们尽快放出新版本的程序。有些团队喜欢“做精品”“憋大招”,实际上如果缺乏用户的参与,也不可能做出精品来。
-
我们欢迎需求的变化,即使是在开发后期
需求变化多了,表示我们的软件有更多的市场需求。而我们工作就是有针对性的去适应和控制变化。作为开发人员,应该勇敢的去面对变化。因为只有变化才能提高我们的竞争力,也能让客户变得强大,进而让我们获得更多的利润。
-
经常交付或者发布可以工作的软件,从几星期到几个月,时间尺度越短越好
以前我们习惯于按月安排工作计划,后来我们发现,那些每周都更新的产品,更加容易抓住用户。对于工作进度的把握,则是每天都发布是更有效的。日版本测试,周版本发布,这是我认为互联网软件应该追求,而且也应该能达到的目标。更频繁的发布软件,能够更快速的占领互联网市场,也能让产品更快的接受市场的检验,对于产品设计和市场运营来说,都能争取宝贵的时间。人生苦短,我们应该尽快把所有的工作成果,都尽快的投放到市场上。 -
业务人员和开发者应该在整个项目过程中必须在一起工作
需求的沟通始终贯穿整个工作历程,如果开发人员找不到需求的代表,他们往往就会按照自己的理解去假设需求。而这些假设一旦有偏差,就代表着程序需要修改,甚至重写。然而,如果这个问题在落笔之初,扭过头问相关人员一声,结果可能就完全不同。游戏开发中有一句话叫做:“策划陪技术加班”。意思就是这个原则的自我说明,所有的游戏策划,在工作中都发现,只有“在一起”,才能让产品做的快,做的好。这对已经支付费用的客户来说,似乎是额外的成本,但是软件开发就是这样一个事情:用户必须要参与开发,才能得到真正有用的软件。我们必须承认软件开发的风险性,也必须接受这种必要的成本,否则我们只是在虚掷金钱和光阴。
-
给开发者提供适宜的环境,满足他们的需要,让他们斗志高昂,并相信他们能够完成任务
学习软件开发本身就是一项非常艰苦的活动,而程序员们基本上是靠自学来完成。不知道大家注意到没有,有很多软件开发者都是在黑网吧里工作工作的。对此,有些老板认为他们可能是一群贪图享受,随时准备磨洋工的小混混。不管是在网吧里当小混混也好,还是在坐在明亮办公室里的程序员也罢,程序员本身就代表着一种自律的能力。如果,你了解软件开发这项行业,自然就不会有这样歧视的想法。
宽敞、明亮、安静的空间,其实是和所有脑力工作者一样的需求而已。高昂的情绪,更是能让脑力活动的速度加倍。每个软件开发者,实际上都期望自己的作品能变得有价值,而且他们自己也希望能尽快完成,前提是自己的生理和心理都能承担工作的劳累。因为开发工作是他们的价值所在,如果做的更好更快,是开发者本身就在追求的目标。然而因为我们对软件开发的无知,让我们在管理软件开发的时候,常常提出一些不合理的评价和预估,这会让他们放弃对工作效率的追求,这对于投资者和客户来说,都是一个双输的结果。 -
小组中最有效率的信息传达方式是面对面的交谈
面对面的交谈,能力利用双方交谈期间的100%时间和精力。不管是别的任何方式,都难以达到这个效果。而且面对面,还可以用画图、共同操作等方式来辅助沟通。如果沟通是以QQ、邮箱、电话等沟通方式,那么沟通效果未必就如人意。另一方面,面对面代表了重视和尊重,每个人都会对重视自己的人所提出的意见额外关注,这也提高了沟通内容的准确性。
-
“可以工作的软件”是进度的主要度量标准
你可以号称完成了项目的50%,但是你无法预料在你认为你完成了90%的时候,会碰到一个难缠的BUG,或者接到一个“变态”的新需求,从而让你的项目要多花一倍的时间去做。因此你说的“50%”或者“90%”都是毫无意义的,这些数字既无法代表工作消耗的时间比例,也无法代表软件代码的数量比率。如果软件还没能运行,就是进度还没真正走到那一步,别的预估基本都是瞎扯。为了能更准确的评估进度,就一定要能尽快,尽量小步伐的发布新版本软件。我再次提到每日发版,用这个来代替该死的每日工作报告吧!
-
提倡可持续开发。出资人、开发人员和用户应该总是维持不变的节奏
软件出自我们人类的大脑,他是一种和人们共生的奇特事物,我们应该去持续的“培养”他。不要期望某个想法能放之四海而共通,也不要期望什么手段在任何时候都有用,所以软件也应该“与时俱进”,不断变化,不断开发的软件,才能不断的满足需求。如果软件不是这种事物,微软、IBM、苹果公司十年前就应该关门大吉了。
-
对卓越技术与良好设计的不断追求将有助于提高敏捷性
应对变化是需要成本的,最蠢笨的方法就是不断重新做。大部分的加班实际上都是在重新做一些事情。而卓越的技术让我们能更快速的去开发,因此不管是开发新功能,还是重写旧模块,都能缩短时间,从而降低变化的成本。卓越的技术本身还带来了硬件性能的好处,避免我们为了提高软件的性能而耗费更多的时间。自动化部署发布、自动化测试、优秀的代码编辑器,都能帮助我们更快的完成工作。良好的设计则会帮我们减少需要重做的工作,高聚合低耦合的设计,能让我们在变化时只修改真正变化的部分,而不是被迫重新做很多别的工作。
我们不应该去奢望自己像先知一样,在每个功能设计的时候受到天启,一下子就想到所有可能的变化。但是我们能精心设计我们的系统,让我们在需要变更的时候,减少各种伤筋动骨的大修大改。我们的经验,能帮我们一步步积累更多的关于良好设计的知识。实际上,如果没有技术和设计水平的提高,单靠空口喊“拥抱变化”,是不会真正提高工作效率的。这也是大量公司老板的误解,认为“敏捷”方法本身就是一种“技术”,只要掌握就能增加开发速度,然而“敏捷”更多的是一种软件开发的“世界观”,而比较少是“方法论”,还是需要我们踏实的去提高技术和设计水平,才能让“敏捷”的世界观发挥出真正的价值来。 -
简单——尽可能减少工作量的艺术至关重要
简单就是美,少就是多。这些话对于软件开发来说,确是金玉良言。简单的设计容易理解,方便修改。简单的代码BUG少。程序的功能越少,适用面就越广。模块的功能越单一,能重用他的地方就越多。然而如何让简单而不是简陋,需要的是精炼的思想,需要开发人员去总结和归纳,去把握每个需求的核心和本质。减少工作量本身,也是一项非常重要的脑力工作。去芜存菁,辨伪求真,这种工作确实难以单凭流程和工具就能完成。而这些能力,正是软件设计的精华所在,称之为艺术一点也不为过。我们应该去追求这种创造性能力,而不是去追求机械性的流水线、自动化工厂方式的开发能力。
-
最好的架构、需求和设计都源自自我组织的团队
自我组织的团队,指那些对项目充满热情,愿意主动承担责任,互相信任的团队。这种团队的气氛是积极热情的,他们视项目为体现价值的途径,而不是换取工资的手段。只有这种团队,才会努力去想办法提高工作效率,而不是总是计算投入产出,时刻希望多从订单、合同里面多掏出来点钱。培养和打造这样的团队,是管理者最重要的工作,也是管理者最有价值的投资。软件无法自动从机器上流淌出来,投资在人身上,就如同投资购买先进的生产线一样重要。
-
每隔一定时间,团队都要总结如何提高效率,然后相应地调整自己的行为
敏捷的价值观,是不断自我提高效率,不断进化自己的方法,这本质上就是所谓学习型团队的价值观。其实,重视工作效率和重视产品质量一样,这样才能让团队拥有不断应对变化的能力。
孤芳自赏抱残守缺在技术人员中并不少见,愿意学习新技术,愿意总结问题,不断改变自己,才能适应不断的需求变更。这条是“敏捷”当中少有的“方法论”,虽然没有说每隔多久就要总结,也没有要总结什么,但是很明确的就是,要通过开发实践来总结经验,以提升工作效率。这和某些公司的“大牛”迷信论是相反的。有些老板认为程序员本身就分大牛和菜鸟,一定要大牛才能做出好东西。实际上每个团队,每个程序员,都能通过实践积累经验,只要他们愿意总结,愿意去改变,就算是菜鸟也能做的很好。而某些大牛只做自己拿手的,反而能提供的价值比较少,因为他的那些拿手菜,不一定是时时都有需要的。
敏捷方法有时候被误认为是无计划性和纪律性的方法,实际上更确切的说法是敏捷方法强调适应性而非预见性。适应性的方法集中在快速适应现实的变化。当项目的需求起了变化,团队应该迅速适应。
很多老板,嘴里说着:你们敏捷一点嘛。意思只是“你们快一点做嘛”。潜意识里面还有让大家抛弃那些保证质量或者管理的工作,也不要做什么设计,只求快点交付软件就行了。而真正的敏捷,是一种贯穿始终的软件开发方法,是一种价值观和软件开发文化。这需要我们从很多地方去修正原有的开发思路,从而使软件开发效率得到长期提高,降低失败风险,而非一种短期可以用来冲刺的手段。
二.敏捷是一种沟通方式
关于“敏捷开发”的书籍也是汗牛充栋,经典论文也很多。敏捷提倡的工作方式有很多是关于“观点”和“风格”的。其最核心的目标是把开发方式从经典的瀑布式改变成以“迭代”为核心的方式。其实并没有说多次迭代的开发进度就一定比瀑布方式要快,这里是很多人望文生义的误解。
以迭代为核心的开发方式,最大的好处是能尽快的把功能体现在可用的产品上,而不断更新的产品,能让非技术人员——用户更多的参与到开发过程中来,而不只是在需求阶段,对着一堆需求或者调查文档来填文字。因为人的认识规律都是需要通过实践,如果有可用的产品,不管是多简陋,能让用户的理解的,都远比开发人员的任何描述都要准确。通过这种方式,开发方向可以不断根据用户的意见来修正,避免做那些不能满足客户需求的开发。
敏捷,提倡的就是额昂开发者和用户用产品来沟通。下面列出一些敏捷方法的具体方法论:
1.水晶方法 Crystal
水晶方法认为不同类型的项目需要不同的方法。决定用什么软件开发方法,与两个因素有关:项目参与人数和出错后果。实际上,大部分互联网项目都适用于Crystal Clear方法。水晶方法针对不同类型的项目,提倡不同的方法论,是一种很求实的态度。
2.特性驱动开发 FDD/Feature Driven Development
FDD是一个模型驱动( model-driven)、短期迭代(short-iteration)的过程。 FDD的起点是创建一个全局的模型轮廓,不要求很精确,得出大概模样就可以,然后使用小于两周的时间在哦为一个开发迭代,通过一系列的迭代, 逐渐丰富模型功能内容。FDD能让团队很清楚现在的完成度是多少,而不是让开发人员感觉没有一个整体目标。
3.Scrum
Scrum是一种迭代式增量软件开发过程,通常用于敏捷软件开发。Scrum在英语的意思是橄榄球里的争球。Scrum很务实的定义了团队中能的主要角色:
敏捷教练或项目经理:确保团队合理运作Scrum,并帮助团队移除实施中的障碍;
产品负责人:在游戏项目中就是主策划,确定产品的方向和愿景,定义产品发布的内容、优先级及交付时间;
开发团队:一个跨职能的小团队,应该包括美术、运维、测试等所有需要的专业人员。
实施过程是把项目分为一次次的“冲刺”阶段,每次“冲刺”从一周到一个月。工作目标就是产品订单(product backlog)。每张backlog在全体讨论并承诺接受之后,将严格执行不得更改。Scrum最大的好处之一是它非常容易学习,而且启动Scrum应用并不需要太多的投入。
4.极限编程 XP Extreme Programming
XP方法是所有敏捷方法中,规则最清晰和最完整的。包括:
- 团队协作(Whole Team)
- 规划策略(The Planning Game);
- 结对编程(Pair programming)
- 测试驱动开发(Testing-Driven Development)
- 重构(Refractoring)
- 简单设计(Simple Design)
- 代码集体所有权(Collective Code Ownership)
- 持续集成(Continuous Integration)
- 客户测试(Customer Tests)
- 小型发布(Small Release)
- 每周40小时工作制(40-hour Week)
- 编码规范(Code Standards)
- 系统隐喻(System Metaphor)
这里面有很多规则,一般的团队似乎比较难以达到,比如结对编程和测试驱动。除了结对编程和测试驱动外,其他的一些规则则是比较容易做到。XP方法是能提供给我们清晰的行动指南。
有人把XP方法中的“测试驱动”看成是核心规则,这个确实是非常正确的。因为如果你要造一辆未经严格设计的车子,最好的保证他质量的方法就是多跑跑。幸好软件是可以无限自动重复测试的产品,因此利用计算机的能力去模拟现实,从而代替人类不完整的思维,是一种方法上的进步。事实上就算你不用XP方法,你也应该尽量的去靠近“测试驱动”的方法去开发系统。
三.敏捷是瓷器活,你得有金刚钻
既然敏捷的方式有很多好处,为什么很多团队都觉得实际上用处不大呢?因为敏捷本身不是万能的。敏捷方法适用于需求萌动并且快速改变的情况,如系统有比较高的关键性、可靠性、安全性等方面的要求,则可能不完全适合敏捷的开发模式;从组织结构的角度看,组织结构的文化、人员、沟通则决定了敏捷方法是否适用。
最重要的因素恐怕是项目的规模。规模增长,面对面的沟通就愈加困难,因此敏捷方法更适用于较小的队伍,40、30、20、10人或者更少。大规模的敏捷软件开发尚处于积极研究的领域。
敏捷适合于很多人对产品提出需求修正的模式,特别是开发人员和需求人员有较大的知识背景差距。而有一些“纯技术类需求”的项目,开发人员本身就是需求人员,再去求敏捷的各种确认活动,就显得多此一举。
敏捷讲究开放的团队气氛,是主动负起责任的做法。而我们很多的团队本身分工泾渭分明:服务端、客户端、DBA、运维等等,而这种分工还不仅仅是因为传统或者文化,而是团队成员本身就不具备那么多种不同的技能。
同样组织文化必须支持谈判,因为敏捷意味着大家都承认,项目的开发是在不断的对所有人的思维的整理。所以项目中没有谁是绝对正确或者权威,必须要互相妥协,还有对妥协结果真心实意的接受。
在团队中人员的彼此信任也相当重要。敏捷的各项方法并未受到严格的检查,而是强调发动自己的热情去做事。如果成员不信任彼此,那么就会出现大量的沟通问题,反而会影响效率的提高。所以人员越少,越精干。
敏捷方法也要求老板和投资人接受开发团队的决定。因为需求是在开发团队中产生,如果缺乏了团队的密切沟通,而是接受老板下达的指令,那么强加在系统中的功能可能就没人做得好。这类指令越多,就等于越缩减敏捷方法在需求方面能提供的好处。只有团队有权决定自己做什么,以及如何做,才能激发团队的热情。
敏捷对于环境设施的要求是能满足成员间快速沟通。一些方便办公沟通的地方,并不是我们现在常见的地方。高耸的格子间隔开每个人,而稀少的会议室又让大家难以找到地方沟通。虽然每个人都有个格子,但是噪音和别人的干扰却可以轻易穿透,想到某人的格子里开会也是不太受欢迎的事情。
笔者曾参加过无数次 的“每日例会”,这个例会的作用除了让早上大家能准时上班外,真正起到“沟通”的作用非常小。而且时间往往也没控制好,特别是有领导参与的时候。大家轮流汇报的方式,让当时不用发言的人都在走神,分工已经分好,也无需去讨论别人的进度如何。反而当实行了每日版本发布后,大家会在早上的时候,一起碰一下昨天发现的问题,如何分工去解决。所以每每日例会的议题应该是每日版本的需求问题,而不是所谓的进度。
但是,要做到每日都有版本发布,也不是一个简单的事情。首先团队要能熟练的使用版本管理软件的分支功能,比如SVN。其次团队还要搭建完整的自动构建和自动部署的测试环境。最后还需要有类似JIRA的问题跟踪系统。
总结来说,一个团队要真正能启动“敏捷”,在团队气氛上必须是开放和主动的,而不能让团队成员得过且过。在技能上团队成员不能只固守自己的一摊子技术,必须要愿意多接触跨界技术。在开发流程和开发工具上要比较成熟,能做到比较高效的构建、部署、测试。“持续集成”就是专门讲这一个环节的。而最重要的,是团队成员必须明白敏捷的目标——不是提高开发速度,而是避免无效的开发。
我认为最有效提升工作效率的敏捷方法包括:
- 和需求人员一起办公,最好能有一间独立的办公室,让开发人员和需求人员坐到一起。
- 测试驱动开发,写代码前写单元测试。
- 重构,安排专门的版本周期进行重构,通常应该在每个重要版本发布后,经过总结和讨论,安排重构的恩物。
- 代码审查,在代码提交前。对比结对编程,这点容易实现的多。
- 持续集成,一定要有自动化编译、构建、发布、部署的工具。
- 每日发布,项目经理以此作为进度依据。
- 实施编码规范,用培训作为铺垫,以代码审查作为实施措施。
- 每周工作40小时,长期来看,加班本身是降低工作效率的事情,敏捷是一个针对长期目标的方法,只要加班,就非敏捷。
小TIPS:从自动构建和自动发布开始,做好每日版本能测试,比较容易开始“敏捷”。