敏捷大会 II 敏捷思想在产品周期的延伸

李子骅--石墨文档技术总监。

一个产品有需求的提出、评审、确定,以及实际的开发测试和交付这几个阶段。从2001年敏捷被提出开始到现在已经有越来越多的项目在使用敏捷。现在的敏捷已经变成一种常态,这个时候讨论敏捷实践中被大家的忽略点就变得非常有意义。

今天我们会围绕两个关键的点来讨论:一个是关注非功能需求,另一个是DevOps相关的策略。

关注非功能需求

这是一个网站的截图,上面有两个文本块,第一个是标题,第二个是答案。

看到这个图,首先大家会想它是什么东西,其次是为什么会有人问这个问题。

这是现在最流行的前端开发框架 React 的新一代的核心算法,Fiber的提出有两个背景原因。

第一个原因 是现在越来越多的产品和网站非常复杂,尤其体现在交互和功能方面。就比如石墨文档可以让很多人同时在线编写 Word 文档,这和之前传统的类似博客和新闻的Web 应用不一样,现在我们会有更复杂的交互,所以复杂交互带来什么呢?越来越多的用户发现虽然网站功能越来越多,但是好像网站也随之变得更卡了。滚动的时候会有一些延迟,打开一个网页会越来越慢。Fiber专门是为了解决这个问题,也就是说当你的网站很复杂的时候它可以让你的网站速度响应更快一些。

第二个原因是什么呢? 经过长期的发展,React是现在最流行框架之一,全世界用户都在向它提各种需求:我想加这个功能,要那个功能,但是长期发展过程中也积累了很多技术债,也有很多没有完成的重构的东西,所以他们也希望能够通过Fiber的开发可以把这些技术债还上,把它变成更容易维护一些。

到现在,Fiber开发了满打满算两年时间,它已经推出了。推出之后大家惊喜的发现我的网站好像变快了,我们也可以看到React市场占有率在逐渐升高,迭代频率也在逐渐加快。所以其实Fiber的开发就是一个很明显的非功能需求,大家收到很多需求反馈,但是最终团队还是选择开发这样一个Fiber的工具。

所以,我们当提到非功能性需求的时候,会有几个常见类别,包括响应的速度、负载能力和测试覆盖。每个团队根据不同的情况会有不同的处理方式,把非功能的需求放到Acceptance Criteria里面,也可以放到Definition of Done里面作为这个用户故事是否完成的标准。

不同的方式其实各有利弊,如我们在开发石墨文档过程中支持多个人在一篇文档实时编写内容,同时每一个人看到编辑的东西,这是很明确的功能需求。

怎么去约定它背后的非功能需求呢?大部分情况下应该把它放到我们的验收准则里面,就是说我们可以约定一些通用性能需求。就多个人实时编写这个例子来讲,可能会约定一个人数,比如希望能够十个人都能够去实时编写,然后每个人的保存时间可以控制在一秒钟之内。这样当我们去完成这个用户故事的时候,我们会看验收准则,如果它支持了在一秒钟之内保存,那我们就确定它是完成的,所以这是一个对于事情有没有完成的很清晰的量化标准,不会让人忽略掉非功能的方式。

但其实也有另一种做法。有些团队会把这种非功能需求当成一个独立的项目,然后放在Backlog里面,这会造成什么问题呢,在时间宽松的情况下没有什么问题,但是当开发遇到一些阻碍的时候会发生什么事呢?就是我们常常会倾向于优先解决客户能看到的东西。因为当我去交付这个项目的时候,客户看到有这个功能觉得还挺不错,你们工作很快,然后你们也很卖力,这些功能对我也很有用处。

可实际上隐含的非功能性需求非常重要:能够承载多少人、能不能在公司范围内使用我们的产品以及安全性怎么样等等,还有一个很容易被忽略的点就是项目的可维护性是如何的。

长期迭代中,敏捷强调越来越频繁的跟客户沟通,去了解客户需求,响应用户的需求,所以开发速度会非常快,交互周期非常短。

在这个时候,很容易发现就是我们会忽略掉我们产品的可维护性,就比如我们会引入很多技术债,会有很多投机取巧方法把这个东西快速上线。到下一个迭代的时候,却继续关心客户反馈的其他需求了,没有再去解决之前的技术债。这就会导致一个产品开发的时候,初始阶段速度很快,但是越到末尾越会发现速度越来越慢了,直到不能不得不停下来大家坐在一起讨论解决这个问题。

两个“负责人”

这个负责人是打引号的。为什么打引号呢?

最近很火的一部电影 《绿皮书》 ,看过这部电影的同学应该都知道《绿皮书》有两个男主角。

坐在后排的这个人获得了最佳男配角奖。其实大家很难想象他是配角,因为如果这部电影少了他,我们很难想象这部电影怎么能拍得下去,怎么能把这个故事讲完。所以,虽然我们会有主角,会有配角,但实际上很有可能这两个人缺一不可,我们应该做到不能忽略其中任何一个人。

在一个敏捷团队项目里面,我们很关注PO的决策,很关注PO的倾向,他会去把我们做的事情按照优先级排列。其实,我们还需要另一个负责人,就是说他需要能够很清晰地了解我们现在的状态,我们现在团队的情况,我们的开发的速度,我们对一些非功能需求的深刻理解。

就比如可维护性到底是如何,需不需要停下来做一些重构,还是继续前进。

对石墨来讲这个「负责人」不是一个角色,因为我们不会设置一个职位做这个事情,如果专门设置一个职位这个事情的时候,整个团队其他人很容易说:「好像这个职位的人他只要做这个事情就可以了,我们其他人不需要关心。」这反而会造成对整个非功能性需求理解的一个倒退,会起一些反作用,对于我来讲更重要的是从文化角度把非功能性需求的灌输给整个团队可以使得团队透明的理解和推动NFR,非功能需求。

什么叫透明的? 简单留有一定比例的NFR时间不能帮助透明化。很多团队会有另一种做法,就是我可以有很多功能性需求,可能有很多用户的反馈,但是我也要做一些可维护性的东西,我要做一些重构,我要去还一些技术债,我要去做团队的提升,我要做一些方便部署的事情。为此我需要在每个迭代周期预留固定的10%或20%的时间来做这些事情。

这样会有什么问题呢? 一个敏捷团队,或者正常一个团队,我们最关注它是能不能自我成长,自我提高,自我进步,自我反馈。所以当讨论非功能性需求的时候,其实是一个很好的契机,整个团队,包括我们的PO、包括我们的整个的开发团队,可以坐在一起一起讨论为什么我们要花这些时间去做这个重构;为什么现在去做,而不是下一个迭代去做;这些会对我们的用户、商业产生什么样的价值。我们会发现这些讨论可以让整个团队能够更快地去得到一些反馈,更快地知道我们的产能到底是什么,而不是说我们尽快地去完成客户所有的的事情,直到因为技术债的各种包袱导致我们不得不停下来。

所以透明地和整个团队讨论这件事情,使得团队可以自我提升,这是一个很重要的事情。

DevOps 的左移

提到非功能性需求,我们很自然就会联想到DevOps,这是一个很自然的关联。

DevOps左移,看这个图就知道了:

我们知道大部分的敏捷框架或者敏捷方法都会很关注软件迭代开发的部分,就是左边这个部分,我们要有敏捷团队、我们让开发团队和业务团队坐在一起、我们能够实时去了解客户的需求、尽早根据不同的环境做不同的改变,我们希望能够尽早地频繁地去交付可以工作的软件给客户。

但是,右面是什么? 右面是我们传统的IT实施运维,他们最关心的是稳定,这个东西如果没有问题,就尽量不要搞,上线的次数不要太频繁。我们每次上线可能都会有风险,我们要盯着这个上线的过程,然后运维同学也要去,所以对于运维来说,上线是一个很痛苦的事。

于是,你能发现,这个绿色的和黄色的好像是有一种冲突在里面,左边是希望能够更加频繁一点,尽快交付,右边是冷静一点,不要这么快。所以,大家会发现当采用了敏捷的时候,如果我们在运维层面不做任何改变的话,整个交付给客户的时间有可能并没有缩短。

我要怎么做呢?就是标题所说的,我们要将运维向左移,这个就回到我演讲这个话题,敏捷思想在产品周期的延伸,我们什么时候延伸,当我们敏捷的时候关注的是沟通,就是我们会和环境沟通,我们会和客户沟通。

那其实也一样的,开发团队要做什么?运维团队要做什么?这个其实也需要尽早沟通,就像这个图一样,我们可以在更早的时间,比如说开发的第一天,或者是我们在开发之前,就让大家坐在一起沟通。

DevOps最重要是什么,其实很难有一个确切的定义。

我们可以说它是一种方式,一种工具,也是一种文化,所以最根本的就是沟通。就是说我们在敏捷时已经证明了沟通的重要,我们可以快速的把软件交付给客户,更快速地去确保我们这个东西满足用户的需求。而不是以前那样埋头苦干一两年,丢给用户,用户却说这不是我想要的。所以项目部署也是一样,像过去如果我们做埋头开发,最后丢给运维团队,运维团队说这可能不是我们想要的,我们可能部署不了。其实之前石墨经常会遇到这样的问题,就是我们其实迭代会非常的频繁,客户需求也会非常多。所以对当时的我们来讲最痛苦的时候就是当一个迭代结束,要部署的时候,发现部署是一件很可怕的事情,我们经常在部署时发现部署脚本有问题、代码好像有点问题、部署上线了但各种错误扑面而来,运维电话响个不停。

实践:石墨服务开发流程

现在去看之前,我觉得石墨开发的最重要的一个基础的产品,就是我们内部使用的交付平台。通过它,我们的迭代周期可以更短,交付频率可以更快,部署上线的整个流程也会更稳定。

因为石墨是面向企业在线协作的软件,所以我们自己也会用石墨写一些文档。这个截图可以看到及我们会用石墨写一些案例、写一些值班计划、写一些工作日志、技术分享和假期安排。

石墨每个员工都是自己产品的重度用户。刚才提到的敏捷,我们最关心的是怎么能够接受反馈。其实内部员工的反馈往往比用户甚至种子用户来得更快,这是因为大家都坐在一个办公室里,天天见,也会更了解产品。

所以,我们就在想两个事情:

第一个事情是我们怎么能够尽早地收到我们内部员工的反馈;
第二个事情就是怎么能够把我们最害怕的问题,部署的问题解决掉。

所以,我们做了一个这样的功能。

“随时测试和部署每个功能” 这个功能是怎么用的呢?石墨在开发每个项目的时候,每个小组开发每个项目的时候都会创建一个特性分支,然后我们所有的功能都会在这个特性分支里去开发。每个石墨的员工,访问石墨的时候都会有一个特殊的页面,如截图所示,通过这个页面,每个人都可以去配置每个微服务使用哪个特性分支来相应自己的请求。

举个具体例子

就是回到刚才这个图,前几个月我们是没有左侧的树型目录的,但是很多内部员工会反馈,如果左侧有树型目录,就能更容易地找到和管理自己的文档。所以我们决定加上这个功能。当开发进入第五天的时候,我们已经可以通过这个平台把正在开发的树形目录可以给内部员工用了,我们会发各种邀请链接,告诉大家可以到这里选择我们特性的分支,然后刷新就可以看到这个树形结构来实际体验了。

在我们开发之前,其实大家都应该知道我们会把设计图会给利益相关者,会给老板看,但这个图给客户看的时候,客户说还不错,,但是我们把软件交给客户的时候,经常发现他们说这个跟当初好像不太一样,不太能满足自己的需求。其实每个人都一样,大家看设计图和在实际工作场景中使用这个东西的时候,感触是完全不一样的。

看图可能会忽略很多东西,但当你每天使用的产品出现这样变化的时候才能切实的感受到这个东西到底好不好用,到底有没有改进的地方,第五天的时候可以把左边有树形目录的产品发给我们的员工看,他们可以把资料放在石墨上,他们会日常体验,因为他们每天用这些文档,所以能很快发现这些东西到底合不合适,到底能不能满足他们的需求,所以也是通过这样我们可以能够非常早地去收集到我们用户的反馈。

相比于之前我们会花很高的成本做AB测试的策略、做各种实验来分析我们的用户使用场景。然后要过两三周的时间才能把这些数据汇总起来。

通过这样的功能,我们就能够非常以一个最低的成本,最快的速度收集到客户最真实的需求。

第二个问题就是刚才说到了,我们每次迭代最怕的就是部署的那一天。因为之前经历到一些部署的问题。现在我们通过这个平台可以做成什么样呢?部署就像切换标签一样方便!刚才讲内部员工可以通过这个平台去选择每个模块所要使用的分支,对于发布来讲是一样的。

我们可以设定一个比例,比如2%或者10%的用户可以访到某个分支,然后剩下百分之几的用户可以放到另一个分支,其他的用户再访问到线上分支。它是一个非常快速、灵活的一种上线的方式。