银行中的跨国研发团队如何快速交付

在互联网大潮中,金融企业也越来越多地直面互联网金融的冲击。传统的产品设计和发布周期显然已经跟不上当下快速发展的消费市场。无论中资还是外资各大银行,都已经纷纷上马移动金融产品,并且开始采用敏捷开发的模式,以达到快速发布,灵活调整的目的。
本案例向大家分享某银行的跨国研发团队是如何达到快速交付移动金融产品的。

一、引言

该银行组建了单独的团队来研发新一代的手机银行产品,团队主要分布在中国和新加坡,在马来西亚和印度也有部分人员。手机银行的业务逻辑和关联系统基于原有的网上银行产品,但用户体验及页面设计都要另起炉灶,试图对不同国家的业务提供统一的用户体验。

对于一个全新招聘的跨国团队,采用大家没用过的敏捷方法来研发一款创新的手机银行产品,这个“三新”项目看起来就是一个不可能完成的挑战。

由于各国市场环境、政策法规等原因,不同的国家可能在页面体验、业务逻辑、关联系统有所不同,导致原来的项目代码存在大量分支,由多个跨国团队分别维护,维护成本非常高。这些代码本来是源自相同的代码基线,因此目录结构看起来非常相似,但实际上却具有不同的规范和结构,举个例子,对于一个登录的页面,有的用

实现的,而有些却在外面又包装了一层iFrame。当各个分支有一些公共的升级需要,或者互相合并代码的时候,就会产生大量的手工操作,极易漏掉一些分支,并带来不可避免的人工错误,维护成本极高。

尽管基于分支的开发使得不同团队可以独立工作,但高昂的维护成本,以及从精益角度出发,分支之间存在的代码也是一种浪费。不同的分支就像一对恋人,本是同路人,分手后各奔东西,再也难以相聚,即使某天再次偶遇,也只是最熟悉的陌生人。

在新的项目中,我们的期望是加速交付新项目,统一不同国家市场的产品体验,降低已有国家的维护成本。同时建立标准化的知识基线,使不断加入的新人能够快速融入团队。

本案例主要以前端产品为例来讲述故事。前端产品采用的是Single Page Web App(单页面网页应用),即一次性加载所有页面,实现无刷新页面跳转技术。主要采用了EmberJS框架,结合html5与css3,构建工具采用grunt.js, 其中还用到了node.js、ruby等编程语言。

二、解决之道

在该案例中,项目管理人员和敏捷教练根据现状制定策略,然后设计架构,并由此产生适合团队的协作模式,从这三部分入手来打造团队。

1.1 策略-涌现式设计

敏捷从形式上看是迭代,但是为什么要迭代?这里我们要引入一个词:蜂群思维。一只只柔弱的蜜蜂,组织在一起能够不可思议地构筑出正六边形的蜂巢,角度分毫不差,显然不是单个蜜蜂能够做到的,而蜂王也并没有直接指挥每只蜜蜂。当个体聚集在一起时,显现出了一种整体性,比个体简单叠加的结果显然要多了一些东西。这是自然界生命演化、应对变化的最基本的方式,对于组织和软件系统同样适用。

一个软件研发组织是由许多人组成的复杂自适应网络,在网络中,人和人之间存在连接,而任何一点的变化都会对其他点产生递归因果关系,而且这些影响是同时发生的。每一次变化都会对系统产生深远的扰动,没有一个大脑能够准确地预测和控制网络中的每个节点或细节,必须调动每一个大脑并行地思考,形成蜂群。抛弃掉对可预测性与可控制的执念,用进化的眼光去面对变化。特别是银行这种相对传统和官僚的环境中,先动手做起来,不断地试错,不断地触碰边界,才能更快地找到更合适的方法。

对于软件系统也是一样,许多简单的模块叠加成为完整的可交付的功能,但是整体的业务行为显然不仅仅是那些代码的简单叠加之和,也无法对最终的产出做出完整预测。举个例子,在项目早期架构师曾将后端J2EE系统规划为8层,每层都有各自的职责与含义,并且设计了一个看似灵活性很高的流程引擎用于组装不同的业务逻辑。但现实是,几年以后,这些设计都是用不到或者不现实的,属于过度设计,这在精益中也是浪费。

将大问题分解成小问题,正是敏捷中提倡的短迭代概念。在不断地迭代中,随着有用的信息不断增加,形成滚雪球效应,一定会有更好的设计与方案涌现出来。我们每天早上的站会,随着人数增加,随着跨国沟通的需要增多,逐渐形成了每日的Scrum Of Scrum,而不是预先设计好。我们的构建方案,最初采用Maven,后来改用grunt.js并发展出一套完整的方案,这也是最初没有人想到的。这些变化不胜枚举,但如果从一开始就抱着固定心态不放,那绝对不会演化出那些结果的。

1.2 策略-基于主干开发

引言部分已经提到了基于分支开发的种种弊端。其实基于主干开发或叫单分支开发并非一个新鲜概念,而是从2000年左右就包含在极限编程中的实践,然而真正敢于实践或者做出效果的团队不多,这与团队所处环境有很大关系。

基于主干开发指的是整个项目团队只维护同一主干(如SVN trunk),不允许再存在其他用于开发的长期分支。个人在开发机上的分支要频繁提交,与主干合并,避免过去那种大批量提交的方式,改为小批量合并,降低合并时的风险。

这里碰到一个问题,即传统的SCM政策要求每个项目立项之初就要建立一个单独的SCM分支,以便进行追溯,发布时必须从此分支打包。这与单分支的产品化思维有冲突。我们与SCM部门进行沟通,在满足可追溯性的要求下,尽量延迟决策,降低分支存在的数量和时间,减少浪费。只有当一个版本快要发布之前才拉出一个分支,成为发布分支。这个分支不增加新功能,只用于在发布前稳定质量之用,发布后也不得用于新开发,其上所有的缺陷修复都要即使合并回到主干上。

1.3 策略-持续集成

敏捷实际上是强调快速反馈的过程,收到的反馈越多,学习和改进的机会就越多,系统提高得越快。持续集成正是这样一种实践,每次提交代码之后就会运行各项任务,任何一个环节出错都会立即通知提交者进行修改。频繁地提交是维护主干健康度的有力保证,让主干始终保持一个可用的状态,一旦出错可以迅速回滚。

既然是快速反馈,速度就不能太慢。人对于等待的耐心是有限的,不超过10分钟,甚至更短,对于日常开发,构建的反馈周期最好在5秒钟之内。我们采用的grunt构建任务中,按顺序包括了Lint、UnitTest、Aggregate、TemplateCompiling、FileCopy、Compass、Uglify等,在开发阶段,运行到单元测试即可,可以控制在5秒钟之内完成。在部署到开发环境上时,运行到compass即可,可以在15秒内完成。只有完整部署到准发布环境时,才需要完整运行所有步骤,所需时间也最长。

当然如果团队不能形成良好的纪律性,持续集成也会成为一种负担,被大家所忽视。所以进化不仅仅是接到持续集成给出的反馈后做出调整,还需要进一步对如何反馈、如何调整的过程本身进行进化,这才是敏捷的更高境界。

2.1 架构-以抽象模拟分支

既然业务逻辑在不同项目中存在差异,分支就不可避免。但是我们并不需要物理分支,用逻辑分支即可实现。以抽象为分支就是通过在软件内创建新的抽象层,来避免创建新的分支,新老特性得以共存。类似的方案如Flash等跨平台技术,可以极大地提高可维护性。

这种技术可以简单地依赖于面向对象技术里进行抽象,将公共逻辑至于父类,而差异部分放入子类。关键在于要不断地进行重构,探索更好的组织知识的方式。重构是即时的,而不是大规模的行为。如何权衡子类与父类的内容安排,才是一个持续的进化过程。

这里的目录结构也是经过探索的,究竟是先按模块来划分,还是先按照国家分支来划分?最后发现按照国家分支来划分利于打包发布,这才形成当前的方案。

2.2 架构-提高可测性

良好的测试是持续集成的前提,为了能够让跨国团队并行工作,模块化的划分并且每个模块可以单独测试就成了重要的实践。我们的前端无论是公共逻辑还是国家特定逻辑都能够在几秒中之内完成Jasmine单元测试。同时,后端接口规划为Restful API,也是为了能在开发阶段尽早测试,避免将所有的集成风险留到最后。

2.3 架构-灵活构建

构建系统方案也是架构的一部分,决定了交付的灵活性。我们选用的grunt.js工具是一个插件化工具,各种任务可以分别进行配置,甚至可以方便的进行扩展功能。通过自行编写的插件,我们在发布时可以做到按需打包,只将公共逻辑和待发布国家项目的逻辑打包,便于维护,同时也提高前端产品的线上加载速度,提高用户体验。

3.1 团队-闻名不如见面

团队组建是一个裂变的过程。最初团队是由两个中国人出差,加上两个外国人组成的Scrum团队,笔者担任Scrum Master。两个迭代后团队分裂成两部分,分别在国内与新加坡补充新成员形成更多的Scrum团队,这些团队从同一个细胞分裂而来,具有相同的基因,也就是相同的编码风格,工作约定,架构共识,极大提高后面的协作效率。

对于跨国团队,很重要的一点就是要出差见面,以此来建立人际关系。因为电话沟通是一维的,而当面交流,除了语言,还有眼神、肢体、情感等是多维沟通,建立关系的速度和质量都是电话沟通所不能比拟。组织的协作和活跃度很大程度取决于网络的连接度。

3.2 团队-可视化

我们通过JIRA作为跨国需求协作的工具,通过将迭代发布计划与系统架构图透明给团队每个成员,都是意在增强团队成员和管理者之间的连接,改变协作模型,形成大家对目标的共识,以期望调度每个成员的主动性和参与性。
另外,让沟通不仅仅限于理性部分,也通过图形化等手段开发右脑,让思维效率达到最大化。

3.3 团队-虚拟架构组

自然界告诉我们,异化传粉是有效的传播手段,可以提高进化的速度,并显现出遗传优势。对于跨国多团队组织,也要鼓励通过异化传粉来传播知识和形成约定,而不是强求一致。我们成立了虚拟架构组,每个Scrum团队中的技术带头人会定期碰面,共同约定,并且带回自己的团队。这些虚拟架构师并非指定的职位,而且都要亲自动手写代码。

三、案例启示

经过这些实践,我们获得了以下收益:

  • 所有国家遵从同一设计。
  • 一个改变立即对所有国家有效。
  • ~50% 可重用的代码,减少重复工作,加速上线。
  • 一键签出,快速打包,即可支持一个新的国家项目。
  • 容易理解的代码库结构。
  • 不同团队可互相支援。

无论是团队还是软件系统,都从一个可行走的骨架开始,够用就好,保持灵活性,逐步涌现新的行为。随着分支的出现,形成变体,公共部分与分支都可以继续独立地生长,公共部分逐渐形成平台,而需要新的分支时就可以在平台上直接长出来。这个平台是涌现的结果,是复杂自适应系统不断进化的结果。

视频及讲义链接:

http://www.infoq.com/cn/presentations/fast-delivery
http://weibo.com/1001863751/BxO3RwCKV?type=comment