百度高效研发实战训练营-Step1
百度高效研发实战训练营-Step1
1 设计方法与实践介绍
1.1. 软件设计原则
(1)软件设计的目的
软件设计是为了使软件在长期范围内能够容易的进行变化。
变化:软件不是一成不变的,无论是软件本身的需求、软件依赖的其他软件资源都是一直在发生变化的,唯一不变的就是变化。
容易:任何一个软件的变化都需要成本,要尽可能的降低变化的成本,使得软件可以很容易应对软件的变化。
长期:事实上需要长期进行维护的软件更应该做好软件设计,因为软件长期的变化非常多,难以提前做出预测,需要良好的软件设计来应对。
(2)软件设计的原则
软件设计最基本的原则是高内聚、低耦合,他也是软件设计追求的最高目标。
所谓内聚值得是一个软件内部间元素相关联的程度,高内聚追求的是紧密相关联的元素要放在一起。
低耦合指的是单位之间尽可能少的关联、依赖。
在高内聚低耦合之上有很多其他的原则,如SOLID原则、简单设计、正交设计。在这之上还会有设计模式作为最高层的软件设计原则。
1.2 clean code
顾名思义,clean code,即为整洁代码。
这里从clean code的概念、命名、注释、函数、编码细节等方面进行讲解。
(1) clean code的概念
clean code,中文解释为整洁代码。
整洁代码也就指的是我们写的代码能够在尽可能短的时间内被别人读懂。
且代码看上去排版整洁、逻辑清晰、拓展性好。
(2)命名规则
代码中的命名需要遵循以下几个的规则:
①表达它是什么,不要表达怎么做。
②代码做到自注释。
③使用有意义的循环迭代变量。
④避免使用缩写,尤其是拼音缩写。
⑤不要使用非约定俗成的缩写。
⑥避免使用魔法数。
⑦不要害怕使用长变量名。
(3)注释
注释对于代码来说是必不可少的,通常来说,好的注释包含以下内容:
版权信息、设计意图、警示信息。
不好的注释,则具有以下一个或几个特点:
同义反复、隐晦关联关系、套用模板、提供历史修改记录、注释掉的代码。
希望大家在写注释时,能够标注版权信息、解释设计、标出代码的警示信息,然后尽量避免写出不好的注释。
(4)函数
我们在写函数时,应该注意以下事项:
①每个函数只做一件事。
②每个函数都是单一职责的。
③函数分为骨架函数和步骤函数。
骨架函数,是对于业务逻辑和算法在高层次上的抽象描述(一般是被隐藏起来的)。
步骤函数,是业务逻辑和算法的一些实现细节(也是被隐藏起来的)。
(5)编码细节
在编码细节方面需要,遵循以下几点规则:
①使用自然的比较顺序
②简化逻辑层次,避免多层嵌套。
③在写三元表达式时,不要出现复杂的逻辑和过长的条件。
④需要控制变量的作用域,也就是说需要缩小变量作用域的范围,使其越小越好。
1.3 单元测试
单元测试,在项目开发过程中非常重要。
下面将从三个方面进行讲解:
(1)为什么要进行单元测试
从上图可以看到,测试是分为不同层次的,自底而上来看,其中最底层的是单元测试,中间是基于模块级、组件级的测试,再往上则是系统级别的测试。
越是底层的测试,越能够快速的发现问题。
底层的测试集成性更好,能够安全的进行代码修改。
上层从测试一般情况下获得反馈的速度比较慢,测试过程也比较笨重。
所以单元测试,具有更早发现问题、更容易集成、更安全的代码修改的优点。
(2)写好单元测试的重要性
写好单元测试并不是一件容易的事情,需要花费许多时间。
通过对上面的示意图进行分析,X轴上方表示的是单元测试的成本,在实际开发的过程中,写单元测试的成本甚至不亚于写代码的成本。单元测试带来的好处就是可以降低产品开发的成本。
好的单元测试能够降低产品开发的成本,但如果单元测试写的不好的话,不但会增加产品开发的成本,而且还会增加单元测试成本。
(3)单元测试原则与模式
这里简单介绍一下单元测试的原则与模式。
原则:
-
Tests As Documentation(将单元测试视为文档工作)
-
Fully Automated and Self-Checking (自检性)
-
Do No Harm(不可破坏性)
-
Keep tests as simple as possible (简洁性)
-
Tests As Safety Net (网络安全性)
-
Defect Localization(定位缺陷)
-
Treat Tests As Code(用写代码的方式进行测试)
-
Fast&Repeatable(快速且可重复)
模式:
- forth step (四步测试法)
- state verification Vs. behavior verification(状态验证与行为验证法)
- test doubles(双重测试法)
下面主要重点介绍四个常用的原则:
Tests As Documentation(将单元测试视为文档工作)
将测试视为文档工作,也就是说,我们需要吧测试写的像文档一样简洁,通过一些描述能够清晰地知道这个测试的作用。在之后对项目进行修改时,只需要查看单元测试即可。
Fully Automated and Self-Checking (自检性)
单元测试都是可以进行自检查,自我校验的,通过代码的编写,通过代码的编写,能够知道测试单元是否执行成功,不需要认为判定。
Do No Harm(不可破坏性)
部分开发人员在进行测试时,会基于测试代码创立一些逻辑,这种做法是错误的。在写测试时,需要注意以下问题:
- 不能单独为测试创建特别的逻辑
- 更不能破坏原有代码的逻辑
Keep tests as simple as possible (简洁性)
单元测试,虽然是用来保证代码的正确性,但单元测试本身也是一份代码。
为了避免过多的测试代码相互覆盖,因此需要尽可能将单元测试的代码写得简单,从而保证其不会出错。
1.4 重构
重构不是拆迁,也不是装修。
我们在进行重构时,需要进行一定的规则。
(1)业务导向
重构是一个很大的工作量和任务量,因此执行重构一定是要能够解决实际的业务问题的,而不是为了重构而去重构。
(2)小步快跑(主干、分支)
重构往往是针对相对较大的项目,因此通常重构是需要多人共同参与的。
在重构过程中,开发人员需要随时对比主干和分支的情况。
当某一个开发人员在分支上进行了大量的改动时,并准备将其合并到主干上时,有可能主干和分支的代码有很大的差异,所以进行重构时,要将问题拆分成多个小的单元进行修改,并且每修改一个就进行一次分支合并。
这种小步快跑的模式,可以随时同步主干上的代码从,从而减少出错的可能性。
(3)演进式设计
在进行代码重构之前,我们不可能知道重构的最终结构是什么,为了保证能够得到一个比较好的结果,因此采用演进式的设计方法。
同时在重构过程中,需要遵循包括高内聚低耦合、正交设计原则、SOLID原则等软件设计原则,不断地进行小步快跑的方式去重构,只有这样最终的结果才能尽量令人满意。
(4)正交设计原则
正交设计原则包括以下要点:
分离关注点、消除重复、缩小依赖点、向着稳定的方向依赖。
在代码中,根据功能的不同,可将其分为不同的变化方向,每个变化方向都是一个职责,我们把每一个不同的变化方向称作关注点,根据关注点的变化方向来进行相应的处理。
1.5 配置化架构
(1)配置化架构的定义
配置化架构的定义为,以可配置的方式构建软件的方法,它是在领域建模的基础上,以配置表述业务,以配置组织架构元素(例如对服务、组件、数据等),并对配置进行规范化、自动化的管理。
之所以做这样的定义,有如下的原因:
①通常情况下,配置指的是对数据的抽象,需要架构上的描述;
②架构上描述的配置,指的是对架构元素的抽象,描述配置化不完整;
③配置化包括对业务的抽象,尤其是逻辑;
④配置化还包括对配置的管理以及分支。
(2)如何应用配置化架构
应用配置化架构,主要包括三个方面:
(1)业务配置化改造
-
组件配置化:组件配置化表达是业务层面非常重要的一环,组件是一个独立升级发布的单元,这样的单元关联了很多配置,可将这些配置分为两类,一类是组件内部的配置,另一类是描述组件与组件之间关系的配置。
显然,只有组件配置化是远远不够的,往往还需要构建DSL(Domain Specified Language)来帮助完成。 -
构建DSL:DSL是工程师针对不同的领域创建的语言,具有很强的针对性,在专业领域,有时很长的代码只需要将其改为一行配置就足够了。
(2)提高配置的开发效率
通过下面的持续发布的系统,能够很好的提高配置的开发效率。(它只针对配置,可以独立的发布配置。)
在系统中,需要配置前端编辑逻辑,后端校验逻辑,当存储发生变更时,触发测试流水线,当测试流水线无异常后,才会借用部署的工具,将配置分发到线上去。
(3)降低配置的维护成本
通常来说,代码数量很大的项目,配置也会很多,这样的配置在维护起来时需要花费大量的成本,所以在设计配置的时候,要满足以下这些规则:
-
①四个维度间参数能够共用:
让配置尽可能地在部署、数据版本、业务属性、架构描述这四个不同维度时,参数能够共用,从而把部署的配置和策略的配置分离开来。
-
②配置支持合并
针对配置本身的语法,让配置支持合并。
-
③减少冗余信息
-
④消除信息重复
-
⑤使用配置的默认值
2 高效研发流程脚本
本部分将从以下四个方面来全面解读高效研发流程:
包含产品路线、发布计划、迭代计划、迭代执划等,这也是一套完整流程中的四个步骤。
2.1 从产品目标到产品路线图
我们知道,在项目实施过程中,满足用户诉求是产品的基础职能,但在此之上还有一个更高的期望,即为产品的目标。
通常情况下,产品目标与产品的收益、市场份额、流水有关。
在制定具体产品目标时,需要考虑产品的商业模式以及产品所处的阶段。
好的产品目标是具体的、可衡量的、相对稳定的。
在进行产品目标阶段性的拆解时,需要考虑到拆解的维度和方法,除了根据阶段性的时间维度进行拆分外,还可以根据产品的里程碑进行拆分。
2.2 从产品路线图到发布计划
在了解如何制定产品发布计划之前,我们需要先了解一个工具,也就是所谓的用户故事地图。
2.2.1 用户故事地图
用户故事地图,实际上是一个完整的用户故事,可以帮助我们增强团队协作、洞察真实需求、打磨优良产品。
(1)用户故事地图框架
想要创建用户故事地图,受限要有用户故事地图的框架。
该框架的核心,实际上是一条从左到右的时间线。
然后从上到下,按照归纳结构,分为三个层级:
时间线上方的一级粒度的功能需求,在工作中,我们称之为为Epic,也就是图中的橙色卡片。
时间线下方的第一行为二级粒度的功能需求,在工作应用中,将其称为Feature,也就是图中的黄色卡片。
在二级粒度功能下,蓝色的卡片代表三级粒度的需求,称之为Story。
(2)用户故事地图的创建步骤
此处我们提炼出了用户故事地图创建中的五个重要的步骤:
- 1.一步一步写出你的故事
- 2.组织情节
- 3.探索替代故事
- 4.提取故事地图的主干
- 5.切分出能帮你达成特定目标的任务
这里通过一个训练智能机器人小A从起床到出门的简单例子,来更清楚的了解这五个步骤:
Step1:一步一步写出你的故事
首先,我们使用蓝色卡片,每张卡片只写一个任务,任务以动词开头,如睁眼、关闹钟、穿拖鞋、叠被子等等。
然后,按照任务的发生顺序,从左到右的组织卡片进行摆放。
Step2:组织情节
第二步,对所有的任务进行提取,从而得到概括性的行为,把这些行为放到黄色卡片上,也就是eature。如睁眼、关闹钟这些行为可以归为醒来要做的事情,穿拖鞋、叠被子这些行为可以归为起来后要做的事情。
Step3:探索替代故事
探索替代故事,细节、变化和异常构成故事地图的主题。
比如,时间充裕可以睡个回笼觉,楼上装修被提前操行等等可能发生的变化和异常,我们需要将这些任务补充进地图,然后进入第四步。
Step4:提取故事地图的主干
进入第四步,我们需要将一系列类似的任务提取出来,形成更大的目标,在类似任务的上方,放一张橙色卡片,也就是之前提到的Epic,卡片贴上一个动词短语,使其足以覆盖下方所有任务卡片所要表达的意思,例如起床,可以概况醒来和起来,如厕可以包括如此和刷牙,洗漱可以概况洗脸。
至此,目前已经完成了较为完整的故事地图,下面进入第五步。
Step5:切分出能帮你达成特定目标的任务
切分出能帮你达成特定目标的任务,需要先确定本次迭代需要完成的特性、目标,使用切分来识别和特定相关的所有任务和细节。
在智能机器人小A从起床到出门这个例子中,分为了三个版本,在第一个版本15分钟起床,回笼觉这张卡片明显是不需要放到其中的,在这些story中选出满足15分钟起床的事务,并将其都放入第一个版本中,至此我们也就完成了一个简单的用户故事地图的创建。
下面这张图,是实际工作中对用户故事地图的应用。
可以看到,在实际工作中完整的用户故事地图所包含的内容非常庞杂。
2.2.2 制定发布计划
在创建用户故事地图的第五步中,我们切分出了达成特定功能的任务目标,每一个发布计划都对应着一个版本,具体的步骤如下。
- 1、Big Story进行细化讨论
- 2、按照价值和重要程度进行版本划分
- 3、确定每个版本的期望达成目标
- 4、确定每个版本的内容
- 5、团队达成共识
2.3 从发布计划到迭代计划
这部分主要讲解集成发布式模式这一常用的模式,在集中发布式模式中,一次发布包含多次迭代,在迭代发布模式中,一次发布等于一次迭代。
很多大型项目,都在使用这一模式。通常是每月发布一次,一次发布包含四次迭代,四个迭代之后发布一次版本。
从发布计划到迭代计划,共包括以下四个内容:
- 1、用户故事拆分
- 2、用户故事优先级
- 3、用户故事估算
- 4、迭代计划制定
2.3.1 用户故事拆分
用户故事的拆分,对于迭代速率有一定影响。
对用户故事的拆分,要做到拆分出的故事尽量小,但是要适当,并不是越小越好。避免出现一个迭代内无法完成的故事。
2.3.2 用户故事优先级
在完成用户故事拆分后,需要对用户故事的优先级进行排序,实际上,用户故事的排序其实是对需求的一个排序。优先级排序有许多方法,如高中低、数字排序、衣服尺码L、XL等方式。
优先级决定排入迭代的顺序,以一个两周的迭代时间为例,假设我们有这样一个需求,前面的数字是需求卡片的序号,后面的数字从100到45,这是项目优先级排序的一个方式,每一次得带能做4个卡片时,就会把优先级最高的卡片放入迭代池,而当第二次迭代时,需求发生了变化,出现了x和y两个新的需求,由于x和y有着较高的优先级,那么仍然将优先级最高的四个卡片放入迭代池中,第三次迭代中又插入了新需求z,需求z也有较高的优先级,那么当我们进行迭代时,需求z会顶替另一个需求被放入迭代池中.
通过以上的例子可以看到,在原本的迭代计划中,12张卡片会被按顺序放入迭代池中,而真实的情况是插入更高优先级的需求,替代了低优先级的需求,而把低优先级的需求放入了下一次迭代中,这就是优先级排序对迭代计划的影响。
2.3.3 用户故事估算
在迭代计划前,需要对用户故事进行估算,用户故事估算,实际上是对工作量的估算,这个工作量体现的是团队均值能力。通常在公司内有不同级别的员工,高级别的员工和低级别的员工完成同一任务所需的时间是不同的,所以在进行用户故事估算时,就需要规避掉技能的差异,根据团队的均值能力来进行估算。
用户故事估算,通常参考的是团队的历史数据,我们可以从历史数据中进行合理的估算;而没有这种历史数据的团队,可以参考一下类似团队的数据;当连着都不具备时,就只能采用本能估算的方式了。
2.3.4 迭代计划制定
当前面三步,全部完成后,才能开始制定迭代计划,将已拆分好的用户故事,按照优先级依次放入迭代池中,对每个要进行迭代的用户故事进行估算,确定好迭代的时间期限,这样我们就制定出了迭代计划。
当需求变更时、团队人员进行调整以及预估不准确时,我们需要对迭代计划进行调整,调整方式有以下几种方式:
- 范围调整、需求置换
- 延期
- 加人、加班赶工
这里推荐采用范围调整、需求变换这一方式,也就是前面提到的,插入高优先级用户故事,顺延低优先级故事到下一次迭代的方式。
2.4 从迭代计划到迭代的落地执行
对于一个团队来说,需要通过迭代计划会、站会、需求评审会、迭代回顾会等会议,对计划进行分析和迭代,然后进行开发和测试。
在整个过程中,无论是开发还是测试,都是以story的粒度去进行的,也就是说,分析、开发与测试这三个步骤是并行的,团队可以使用卡片墙标注完成的任务和未完成的任务以及遇到的bug等。
通过这种方式,能够对执行情况有更加清晰的认知,从而对执行过程产生积极的影响。
3 研发工具链介绍
管理实践具有以下三个特点:
①用“精益”指引产品规划
②用“敏捷”加速迭代开发
③用“数据”驱动持续改进
此处需要学习的三个工具,就是对管理实践三个特点的完美覆盖。
3.1 iCafe
下面来学习,iCafe这一项目管理工具是如何支撑管理实践的。
1、需求管理
对于项目管理来说,需求管理是一个项目的基石。
在互联网行业中,因为产品需求迭代快速这一特点,需求管理一直非常令人头疼。因此,如何对于需求进行更好的管理,更好的做出产品规划,对于互联网行业的项目来说,是一个重要的问题。
传统的需求管理方法,有以下几点:
①直接将需求写在文档上面(项目需求文档)
②直接即将需求制作成需求卡片
通过这样的方式,让研发人员与需求人员保持信息的一致。
③使用Excel进行需求管理排序
这三种方法都存在很多的缺点,例如撰写文档耗时长,文档编写需要较多人力,文档的维护成本高,文档在使用过程中沟通不畅等等。
同时,文字因为其阅读特性,不方便对任务进行直观的展现,所以在很多项目开发过程中,经常会出现文档交给研发人员后,开发出的产品与文档设计不一致的问题。
互联网项目的需求管理,需要具有需求完整性、沟通高效性、表达准确性,沟通便捷性等特点。
研究表明,不同的沟通方式产生的沟通效果各有不同。其中,在所有的沟通方式中,文档沟通是最低效的沟通方式。而面对面使用白板沟通是最高效的沟通方式,结合多种高效沟通方式,就产生了用户故事地图,这种新颖的需求管理排序的方式。
用户故事地图,是敏捷项目管理中,一种重要的管理方式。
首先使用卡片,在白板上将所有的需求列出来,这样就有助于展现产品的全貌,而且将需求转化为可视的卡片,能够更好的根据用户反馈对任务需求进行排序,然后使用不同的颜色,对卡片进行分层。
其中,蓝色卡片是第一层,黄色卡片是第二层,白色卡片是第三层,将颗粒度最小的需求,放在白色卡片这一层。低颗粒度的需求更容易被研发人员所接受,最后通过横向的分组,把迭代计划每一期的每一版本的需求进行归类分组,这样就有利于打通产品视图和研发计划视图。
通过以上步骤,可以得到一个较为完整的用户故事地图.
用户故事地图,是一种非常高效的需求管理方式,目前所有的研发团队,都可以在效率云上,不受物理条件限制的,直接使用它进行需求管理和追踪。
2、迭代计划
在完成产品的版本规划后,研发团队需求制定相应的迭代计划。
敏捷、快速、合理的迭代计划,能够更高效的促进项目的迭代,基于用户故事地图,可以在制定迭代计划的过程中,直接对需求进行上下拖拽,修改优先级;左右拖拽更改计划,这样可以更清晰的展现迭代计划,使开发团队更好的定位到里程碑,从而完善整个迭代计划。
3、进度跟踪
关于进度跟踪,有以下三大法宝:
分别是站会、卡片墙、燃尽图。
站会,同卡片墙相结合,在站会过程中,可以直接通过电子看板,共享项目进度和项目问题,提升站会沟通效率。通过燃尽图和统计数据,团队就能直接得知开发进度及遇到的问题。
4、持续改进
针对持续改进,百度提供了卡片状态时长散点图和卡片状态累计流图这两种工具。
卡片状态时长散点图,能够精确展示团队工作速率,从需求提出到需求上线的单个周期时长和平均周期时长,精确的展示团队在每一个状态的工作速率及工作速率的变化。
卡片状态累计流图,能够宏观展示项目各流程效率趋势,颜色的色块宽,表示该流程积压的需求和任务比较多,色条窄则表明团队状态流动速率提高。
基于这两幅工具图,研发团队可以周期性的进行自检,对过去一段时间的工作进行自我审视,然后持续改进。
3.2 iCode
iCode是一个代码管理工具。围绕这个工具,下面主要讲解两个实践集:
1、工作流
运转无序和工作混乱是困扰很多团队的一个问题,它验证影响产品的交付。
典型的问题有:代码处理随意、bug重复发生、测试不完善、发布版本混乱等。
面对种种问题,iCode同时支持两种标准的工作流,用来保障团队有序协作。
(1)基于主干的工作流
在基于主干的工作流中,整个团队维护一条主干分支,为了保证主干分支的质量和稳定,需要配套严格的准入机制,变更点在合入前需要经过机器和人工的双重评审,通过评审后才能合入主干。
当需要进行版本发布的时候,会基于主干拉取发布分支,这个分支其实是主干特定点的快照,单纯用于发布。如果发布问题过程中发现问题,回到主干修复Bug,或进行功能增强。必要时,再将主干提交拣选到相应的发布分支上,分支发布和主干并行不悖,不用担心开发中的功能被带到线上,发布完成后回复到一条主干的简明模式,
基于主干的工作流,有以下优点:
- ①主干质量高,随时可以发布。
- ②模型简单,只有一条主干,节省分支合并的成本。
但该工作流,也有一定的缺点:
- 在开发高质量的工程项目时,团队需要建设完备的测试用例。
- 在提交环节,要求提交人保持原子提交,即功能和提交一一对应。
(2)基于分支的工作流
在基于分支的工作流中,主干用于存储线上代码,需要变更时基于主干最新代码,开分支完成功能的开发,测试和发布。
分支发布前,需要先同步主干的更新,上线之后,需要将分支合并回主干。
基于分支的工作流的优点有:
- ①分支并行,独立开发,分支之间不会相互影响。
- ②对团队而言,使用门槛低,分支贯穿一个独立功能开发,测试、发布的整个过程,给予团队充分的时间完善测试用例及完成人工测试;
- ③容易上手,系统会引导开发人员完成新建分支、同步主干、合回主干等全部操作。
同时,基于分支的工作流,也存在一定的缺点:
- 需要花费分支合并的成本。
- 需要不断地同步主干,来发现分支的冲突风险点并提前解决。
2、评审
评审是保证团队工程质量的一个重要流程。
如果不经过评审直接提交代码,可能会污染代码历史,增加后期维护成本,产生代码质量问题。
在项目开发过程中,可能会出现本地运行正常的代码,在测试环境或线上环境突然崩溃的情况,针对这样的问题,可以使用质量防护网。
质量防护网,包括代码扫描、持续集成、人工评审三个层次。
代码扫描,具有以下特点和作用:
- 能够找出不符合代码规范的地方,在行间距中插入代码评论。
- 同时出具一个风格报告,方便工程师对代码风格问题进行修改。
持续集成,会配置一个云端构建
- 通过云端构建,快速探测出代码初期Bug,帮助开发人员提早修复。
在前两步做好后,就进入了人工评审阶段。
- 团队的资深成员,可以就架构、逻辑、设计等问题进行深度评审。
通过这三步实现了机器、人工双重评审,层层递减,从而确保团队的工程质量。
3.3 iPipe
iPipe是一个交付平台,围绕这个平台,下面主要讲解三个实践集。
1、固化端到端的交付流程
标准的软件交付的过程,包括以下几点:
首先,会有一个明确的发布版本的输入,然后基于这个发布版本,会进行相应的代码提交,在代码提交之后需要进行编译和测试,其中测试环节可能包含模块级的测试和系统级的测试,测试完成后进行版本发布。
发布上线的过程,可能会分为预上线、生产-灰度、生产-全量等几个环节。
为了使得代码变更流程标准化,需要使用交付流水线的方式来落地。
通过标准化交付过程,从而达到可靠、可重复的作用。
交付流水线是串行执行的,上一个阶段成功执行后,就会触发下一个阶段,执行阶段由任务组成,这些任务可以是串行的也可是并行的。
任务的执行状态决定阶段执行状态,iPipe这一工具,目前包含了标准的交付流水线,用户可以在iPipe中看到流水线的构建情况,在使用交付流水线的过程中,如果当前阶段失败,后面的阶段就不会继续进行,这样就可以节省资源并且快速的发现问题,及时修复问题。
2、插件化现有工具和服务
在执行各种任务时,需要依赖很多工具和服务。
比如maven、docker、jenkins、git等工具和服务。
我们通过一套标准的插件化开发规范,将这些工具和服务集成到流水线中,用户在使用流水线的过程中,就可以很方便的使用这些插件和服务,如果流水线中没有想使用的插件、服务或工具,可以根据效率云提供的插件规范,自行扩展以满足项目需求。
3、数据度量驱动过程改进
通过交付流水线,可以快速获取项目所有的数据和信息。
如一个版本从代码提交到交付上线的周期,或者一个项目各个阶段发现的缺陷数量等等,用户可以通过调用API获取数据来进行数据的度量,从而推动交付过程的改进。
在后续的发展中,平台会识别项目中关键的数据指标,并且自动化的形成更加鲜明的数据报表,这样就可以持续的进行数据度量,给个人及团队提供一个维度丰富的平台。
4 持续交付方法与实践
这部分将深入探讨和讲解持续交付相关的理论和实践方法。
下面围绕三个方面进行展开:
4.1 为什么要做持续交付
首先,来看第一部分,为什么要做持续交付。
想要理解为什么要进行持续交付,就要先了解软件交付流程。
4.1.1 软件交付流程
传统的软件交付流程,通常包括四个步骤:
首先。业务人员会诞生一个软件的想法,然后开发人员将这个想法变为一个产品或者功能,经过测试人员的测试之后,提交给用户使用并产生收益,最后运维人员参与产品或功能的后期运维。
4.1.2 传统软件交付的问题和困境
通过分析以上流程,可以发现一些传统软件交付流程存在的问题:
- ①业务人员产生的需求文档沟通效率较低。
有时会产生需求文档描述不明确,需求文档变更频繁等问题, - ②随着开发进度的推进,测试人员的工作量会逐步增加,测试工作的比重会越来越大,而且由于测试方法和测试工具有限,自动化测试程度低,无法很好地把控软件质量。
- ③真实项目中运维的排期经常会被挤占,又因为手工运维繁琐复杂,时间和技术上双重压迫会导致运维质量难以保证。
因为存在以上问题,所以传统的软件交付,经常会出现开发团队花费大量成本,开发出的功能或产品,并不能满足客户需求这一双输的局面,由此可以总结出传统的软件交付存在两个层面的困境。
从表现层来看,传统软件交付存在以下困境:
- 进度不可控
- 流程不可靠
- 环境不稳定
- 协作不顺畅
从本质来说,表现层的问题其实都是底层问题引起的。
从根源上来说,存在以下这些困境:
- 分支冗余导致合并困难
- 缺陷过多导致阻塞测试
- 开发环境、测试环境、部署环境不统一导致的未知错误
- 代码提交版本混乱无法回溯
- 等待上线周期过长
- 项目部署操作复杂经常失败
- 上线之后出现问题需要紧急回滚
- 架构设计不合理导致发生错误之后无法准确定位
经过对传统软件交付问题的分析和总结,持续交付应运而生。
持续交付是一系列开发实践方法,用来确保让代码能够快速、安全的部署到生产环境中。
持续交付是一个完全自动化的过程,当业务开发完成的时候,可以做到一键部署。持续交付提供了一套更为完善的解决传统软件开发流程的方案。
4.1.3 持续交付的流程与优势
持续交付的流程:
①在需求阶段,持续交付抛弃了传统的需求文档的方式,使用便于开发人员理解的用户故事。
②在开发测试阶段,做到持续集成,测试人员尽早进入项目开始测试。
③在运维阶段,打通开发和运维之间的通路,保持开发环境和运维环境的统一。
持续交付的优势:
①持续交付能够有效缩短提交代码到正式部署上线的时间,降低部署风险。
②持续交付能够自动的、快速的提供反馈,及时发现和修复缺陷。
③持续交付让软件在整个生命周期内都处于可部署的状态。
④持续交付能够简化部署步骤,使软件版本更加清晰。
⑤持续交付能够让交付过程成为一种可靠的、可预期的、可视化的过程。
4.1.4 敏捷开发与Devops
持续交付依靠敏捷开发(Agile)和Devops两个组件的职称可以更好地发挥作用。
敏捷开发(Agile),主要作用于需求阶段和研发阶段。
Devops,主要作用于开发测试和运维部署阶段。
下面主要讲解一下Devops的相关知识:
(1)Devops的趋势
根据最近的一项集体研究,Devops的市场在2020年创造了约50亿美元的产值,预计到2022年,这个数字将达到约66亿美元。
随着Devops的影响力不断扩大,目前Devops已经成为软件工程的主流模式。
(2)Devops的效能
Devops的效能跟发布频率、部署时间、平均修复故障的时间点、部署变更的失败率等四个因素紧密相关。
通常在高效的团队内,发布频率会达到每天多次发布,部署时间和平均修复故障时间都小于一小时,部署变更的失败率也能维持在15%以下。
4.1.5 软件交付能力指标
在评价互联网公司的软件交付能力的时候,通常会使用两个指标:
1.仅涉及一行代码的改动需要花费多少时间此案部署上线,这也是核心指标。
2.开发团队是否在以一种可重复、可靠的方式执行软件交付。
目前国外的主流互联网企业部署周期都以分钟为单位,Amazon、Google这些头部互联网企业,单日的部署频率都在20000次以上。
国内以百度、阿里、腾讯三大互联网巨头的数据来看,单日部署的频率也达到了8000次以上,高频率的部署代表这能够更快更好的响应客户的需求。
4.2 如何做到高效的持续交付
如何做到高效的持续交付,对于这个问题,下面提供了一个三层叠加的持续交付方法:
1、持续交付方法
首先来看最上层,持续交付的总目标是价值交付,要为用户交付有价值的内容,然后第二层包含了业务、流程、组织三个维度。
在业务这一维度,主要通过精益、用户故事地图、看板来减少业务部门和开发部门的沟通困难。
在流程这一维度,主要集中于创建一个供开发、测试、运维人员使用的可靠、可重复的流水线,将这种流水线应用于项目的流程中,在组织这一维度,要求加强团队协作,提高项目质量和项目改进能力,并引入了成熟度模型用于评估团队的能力层级。
如果没有技术能力的支撑,仅依靠方法和指导思想,不足以做到高效持续交付。所以第三层也是最重要的底层,即为技术层。
技术层,包括了基础架构和应用架,其中基础架构引入了容器集群管理、研发工具平台、持续交付工具链;应用框架引用了浮现式设计、微服务框架还有能够抽离出来的配置化架构。
2、持续交付、持续集成、持续部署的关系
要进一步构建可靠可重复的流水线,首先就需要理清持续交付、持续集成和持续部署三者之间的关系。
简单来说,持续集成和持续部署是持续交付的基础,持续交付包括但不限于持续集成和持续部署。
持续集成是包含了代码的编译、近代检查、单元测试任务的集成。
虽然持续集成本身也能构成一条流水线,但是这条流水线并不完整,而且集成并没有明确的目标。
近几年,得益于虚拟机技术和容器技术的迅速发展,持续部署也逐渐变得简单高效,能够运用这些工具快速将项目部署到例如准入环境、预生产环境等等各种环境中。
3、如何构建一个可靠可重复的流水线
在理清持续交付的关系后,需要通过持续交付来构建一条可靠可重复的流水线。
构建这条流水线的目的是为了让开发人员、测试人员、运维人员协作完成整个项目并上线到生产环境。
通过对比传统流水线和持续交付流水线,能更加清晰的展现出持续交付流水线的强大。
在传统流水线中,首先代码提交要通过填写表单的形式进行版本申请,然后开发人员在离线环境上,手工进行代码编译和单元测试,单元测试完成后需要撰写对应的测试报告文档,并且向上提测,在系统测试环境需要测试人员,手动构建和部署测试环境,完成测试之后再次撰写测试报告,并且申请测试上线,在通过上线审批之后,在线上生产环境需要再次手动构建环境,以及进行生产环境的测试,最终完成整体的开发。
在持续交付流水线中,代码合入主干之后会直接触发自动编译,自动编译完成之后会进行初步的自动化单元测试,模块测试和系统测试,在测试过程中,持续交付可以自动构建和部署环境。完成系统测试之后会将问题抛出来,解决完成后再次提测,会自动化的再次进行系统测试,当通过系统测试之后可以一键操作进行项目发布,并进行预上线。在完成预上线后,可以再次进行一键操作完成正式生产环境的上线。
通过两种流水线的对比,可以看出,持续交付的流水线有显著的优势,实际生产中的产品级流水线,可以视为多个模块化流水线的组合,多个模块级流水线组合成为复杂的多线并发的产品级流水线,最终可以完成整个项目的持续交付。
4、交付流水线落地工具
交付流水线的落地,需要依靠落地方案和落地工具。
目前常用的落地方案有GoCD(这是thoughtworks的一个产品。),还有目前广泛应用的Jenkins和Spinnakeer。
常用的交付流水线落地工具有,效率云平台中的iPipe工具,在这个工具中可以根据需求创建流水线,并且将相关内容全都关联到流水线中,这样可以让开发人员、测试人员和运维人员在这个工具中,直观地看到产品的状态以及质量情况。
4.3 持续部署
对于持续交付整体来说,持续部署是最后一个环节,也同样至关重要。
1、持续部署方案
容器技术是目前部署中最流行的的技术,常用的持续部署方案有,Kubernetes+Docker和Matrix系统两种。容器技术一经推出就被广泛的接受和应用,主要原因是对比传统的虚拟机技术有以下几个优点:
①容器技术上手简单,轻量级架构,体积很小。
②容器技术的集合性更好,能更容易对环境和软件进行打包复制和发布。
容器技术的引入,为软件的部署带来了前所未有的改进,不但解决了复制和部署麻烦的问题,还能更精准的将环境中的各种依赖进行完整的打包。
2、部署原则
在持续部署管理的时候,需要遵循一定的原则,内容包括以下几点:
-
①部署包全部来自统一的存储库
-
②所有的环境使用相同的部署方式
-
③所有的环境使用相同的部署脚本
-
④部署流程编排阶梯式晋级,即在部署过程中需要设置多个检查点,一
发生问题可以有序的进行回滚操作。
-
⑤整体部署由运维人员执行。
-
⑥仅通过流水线改变生产环境,防止配置漂移。
-
⑦不可变服务器
-
⑧部署方式采用蓝绿部署或金丝雀部署。
3、部署层次
部署层次的设置,对于部署管理来说也是非常重要的。
首先要明确部署的目的,并不是部署一个可工作的软件,而是部署一套可正常运行的环境。
完整的镜像部署包括三个环节,Build、Ship、Run。
Build跟传统的编译类似,将软件编译形成RPM或者Jar包;
Ship则是将所需的第三方依赖和第三方插件安装到环境中。
Run就是在不同的地方启动整套环境。
制作完成部署包之后,每次需要变更软件或者第三方依赖插件升级的时候,不需要重新打包,直接更新部署包即可。
4、不可变服务器
在部署原则中,提到的不可变服务器原则,对于部署管理来说非常重要,不可变服务器是技术逐步演化的结果。在早期阶段,软件的部署是在物理机上进行的,每一台服务器的网络、存储,软件环境都是不同的。
物理机的不稳定让环境重构变得异常困难,后来逐渐发展为虚拟机部署,在虚拟机上借助流程化的部署,能较好的构建软件环境,但是第三方依赖库的重构不稳定,为整体部署带来了困难。
现阶段使用容器部署,不但继承和优化了虚拟机部署的优点,而且很好的解决了第三方依赖库的重构问题。容器部署就像是一个集装箱,直接把所有需要的内容全部打包进行复制和部署。
5、蓝绿部署和金丝雀部署
在部署原则中提到两大部署方式,分别为蓝绿部署和金丝雀部署。
蓝绿部署,是指在部署的时候,准备新旧两个部署版本,通过域名解析切换的方式,将用户使用环境切换到新版本中,当出现问题的时候,可以快速的将用户环境切回旧版本,并对新版本进行修复和调整。
金丝雀部署,是指当有新版本发布的时候,先让少量的用户使用新版本,并且观察新版本是否存在问题,如果出现问题就及时处理并重新发布,如果一切正常,就稳步的将新版本适配给所有的用户。
6、服务描述
服务描述要实现的目标,是当软件部署到不同的环境中时,通过服务描述来规避环境配置的差异。在服务描述中,通常会对不同的环境下所需的配置进行描述,例如所需要的CPU、内存、网络等。
当实际部署的时候,如果出现环境差异,调度工具就可以按照服务描述的配置,发放资源,使环境可以正常运行。
7、流程控制
在部署阶段,为了防止意外问题的发生,会在一些环节加入人工审核,例如在灰度发布工具中,就是会对线上机器进行分组部署,然后由人工去分组检查,如果没有问题,就进行下一组的部署,如果出现问题,人工就可以及时的进行回滚操作,避免问题扩大到更多地线上环境中。
8、数据度量和分析
在完成持续部署或持续交付之后,需要结合多个维度的数据,对项目整体的研发效率和部署效率进行分析,例如通过交付时间周期的长短变化来反映流水线为团队带来的价值;又如通过筛选和展示团队的相关数据,方便团队来进行决策;还有通过环比汇总数据来分析变化的趋势。
系统也会通过数据的自动分析和异常报表监控一些关键指标,一旦关键数据出现问题,系统就能及时联系关键人员关注。