阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

微软开发部门 DevOps 经验谈——从经验中学习

  • 2017-08-20
  • 本文字数:4521 字

    阅读完需:约 15 分钟

适度控管分支让开发更快速

在 2008 年,我们开发团队刚开始使用 Agile 时,我们认为可以透过程式码品质控管,以及版本控制系统所提供的分支 (branch) 功能等方式,让程式码维持高品质。刚开始的时候,我们版本控制系统中的分支都是经过精心规划设计的,工程师开发完成后,必须要从主干 (trunk) 取得最新的程式码,将自己所开发的程式码与主干的程式码合并,透过系统建置并且通过所有程式码品质的检查,确保开发的程式码符合我们的规范之后,才能算是开发完成,可以把程式码签入 (check in) 到版本控制系统中。

但我们没有预料到的是,过度的使用分支可能会造成开发流程上无谓的浪费。我们进行新功能的开发时,可能会因为在开发上遇到阻碍开发的事情,所花费的时间超过原本预期,导致开发中程式码与主干 (trunk) 太久没有进行合并 (merge),让程式码落差越来越大。这个现象也产生了相当严重的合并 (merge) 债务,我们在不同分支的工作好不容易完成之后,却发现原本主干中的程式码与建立分支时有相当大的落差,这是由于其他人在我们的工作进行时,也不断的把所开发的程式码加入到主干之中,所以当我们开发完成要合并程式码回主干的时候,就会有大量的合并冲突 (merge conflics) 必须要解决。随着我们的组织越庞大,分支越繁杂,这样的情况也会越来越严重。

因此在 2010 年时,我们开始针对程式码分支的规划进行了改变,我们大量删减了原本过于繁琐的程式码分支架构,只留下了少数几个分支,而这些分支通常也只是暂时存在。我们同时明确的针对程式码开发流程进行了改善,减少程式码从主干切出分支进行开发到合并回主干让其他人可以使用的时间。接 我们尝试转换目前所使用的版本控制系统,虽然我们大部分的客户和合作伙伴都是使用中央化的版本控制系统,但我们仍然决定改为使用分散式的版本控制系统 (例如 Git) ,当然,Visual Studio Online 和 TFS 都有支援这两种版本控制系统。使用 Git 的好处是它相当的轻量,并且由于分散式系统的特性,可以很轻松的在本地端建立暂时性的分支结构,不会影响原本远端的分支,所以我们可以在任何需要的时候开启新的分支,当完成工作并将程式码合并回主干后就把这个分支删除,让分支不会过多,管理起来更容易。

同时再搭配发送 pull-request 的工作流程,让 Code Review 和程式码品质控管可以同时完成,当 pull-request 中的程式码内容被审核人员确认无误之后,就会立即的合并回主要分支 (Master Branch),也就是原本的主干之中,这让我们程式码开发流程是顺畅且严谨的,而且由于每一个分支相当轻量,就比较不容易发生因为在分支上开发过久,开发人员必须花费相当大的精力保持与主干的程式码同步。

搭配这套流程可以把开发人员的工作周期相对的缩短,由原本冗长的开发时程,转变为一个一个短周期的工作项目,也让完成工作项目变得更加容易,并且随时可以合并回主要分支中,达到一个更容易持续整合的循环,分支也不会因为离开主要分支过久,而有许多合并冲突要解决,一旦我们完成工作合并回主要分支后,所建立出来的分支随时都可以删除,让分支的管理工作更容易进行。

保持敏捷

我们虽然决定要使用 DevOps 作为新的流程,但我们一样会继续遵循着 Scrum 的精神,Scrum 有着让我们能够方便进行沟通的优点。举例来说,我们的主要工作团队单位是以开发某项特定功能来视为一个小组,约莫等于 Scrum 的一个 Team,Product Owner 会坐在我们团队的中间,与我们一同工作,Product Owner 和工程师的主管共同代表着我们工作团队的意见。

我们遵循着让团队独立自主,并努力增进团队之间的认同感,这也会让一些化学效应开始发生在团队之中,我们团队的成员都是多才多艺的,我们也不会特别区分开发人员或是测试人员,而是只有一种共同的工程师角色。(这点对于提升士气十分有帮助)

我们尽可能的让团队成员互相熟悉,在每个功能开发团队中约有 8~12 个工程师,我们让团队成员至少一起工作 12~18 个月,甚至更久。当工作量超出团队负荷时,我们也不会对团队成员施压,希望他们能够自己消化满出来部分的工作,而是寻求其他团队的帮助,帮我们分担这些工作内容。

同时,我们让每一个功能开发团队坐在同一个团队工作区 (参考图一),每个团队拥有一个专属的房间,而并不只是开放空间的一部份。团队成员除了坐在一起工作之外,也能够随时进行沟通,不用担心打扰到其他功能开发团队。除此之外,团队工作区附近还有许多小房间提供成员进行需要专注的工作,或是暂时性离开团队进行思考或放松,基本上每个团队成员在工作区中都是非常自在的,甚至当需要进行每日站立会议时,只要在自己的座位上站起来就可以开会了!

功能开发团队的成员们一起坐在团队专属的房间中

我们通常会根据经验来规划三周的 Sprint,对我们来说,要能够在这么短的周期中,替一个在全球都提供服务的网站,开发出具有足够价值的功能是相当困难的。但是如果开发周期过长,可能会让功能开发充满各种不安因素,也无法确保自己所开发功能的方向是对的。在微软的某些团队甚至使用两周的 Sprint,让他们可以快速根据线上功能使用情况的反馈,不断修正自己所进行开发的项目的方向是否正确,而不是让 Sprint 沦落为计算时间的单位。

透过这种开发模式,要验收功能开发的完成也非常简单,当开发人员完成自己新功能的开发之后,这些新功能会在 Sprint 结束后发布到上百万的使用者面前让他们使用,而当新功能在线上发生的异常时,开发人员也会马上知道,并且很快的找出发生异常的原因,并且修正它。

我们的 Scrum Master 是由团队成员轮流担任的,这也让每个人都有机会学习怎么作为一个好的 Scrum 领导者,我们同时尽可能的让 Sprint 的进行更加轻量化,只保留了 Sprint 透明好沟通的优点。在 Sprint 开始时,每个功能开发小队会从产品的 backlog 中认领想要进行的工作项目,并且撰写一页 Email 说明他们的开发计画,信中会附上 backlog 在 Visual Studio Online 上的连结供大家浏览 backlog 内容,而 Sprint 开发结果的检验也是透过更新这个 mail,如果需要的话还会再额外附上三分钟的简短说明影片,影片中将会以客户的角度来说明如何使用团队开发的新功能,以及这个新功能有什么优点。

我们让团队规划尽可能的精简,通常我们会定下未来十八个月的目标,做为我们开发的主要方向,而这些目标通常是透过一些操作上的需求、想像功能使用的情境、概念影片或是简短的构思文件来决定的。每隔六个月,我们团队与团队间也会根据需求互相交换开发项目或是合作伙伴,每隔三个 Sprints,功能开发团队的队长也会一起进行新功能的跨团队沟通会议,分享交流团队工作内容的优先顺序,确认自己团队进行的方向没有偏离目标,同时交换新资讯和同步不同小队间的讯息。举例来说,我们可能会透过功能会议来重新决定我们开发新功能的顺序以及开放哪些新功能给使用者使用。

根据使用者经验调整方向

在传统的 Agile 开发流程中,Product Owner 会决定产品 Backlog (PBIs) 的优先顺序,PBIs 也通常被视为开发时的需求。PBIs 会使用使用者故事 (User Story) 的方式来撰写,虽然 PBIs 的概念是有弹性的,但决定之后不太会去改变它,我们以前也是使用这种方式进行开发。

但为了转换到 DevOps 的开发流程,我们并没有使用这样的模式太久,我们尝试着把原本的 PBIs 转变为假设性质的项目,假设使用者的使用情境以及需要的功能,再根据这些项目来进行功能开发,完成后就部署到线上环境提供使用者使用,然后收集使用者的反馈以及使用情况的数据,利用这些数据来证明或否定我们的假设方向是否正确,透过这种验证学习循环 (Validated learning ) 的方式来确保假设的方向是正确的。

而要能够执行有效的循环必须要具备有意义的统计样本资料,以及对照组资料来互相比较数据,判断所收集的资料是否合理,当然你也必须要了解影响这些数据的因素是什么,才能够针对这些数据进行评估。你可以参考图 7~11 的范例,我们发现使用者在开始使用 Visual Studio Online 时,通常不会马上建立团队专案 (Team Project),但是如果没有团队专案的话,使用者就没办法实际操作或体验 Visual Studio Online 的好处以及带来的便利性,下图二中呈现了以前进入 Visual Studio Online 页面的样子。

由于使用者必须要输入很多资料,以及进行许多步骤才能开始使用 Visual Studio Online,导致使用者对于试用兴趣缺缺

由于以上的原因,我们修改了 Visual Studio Online 在网页和 IDE 中的操作体验。图三中呈现了我们让使用者能够 Visual Studio 中,透过两个步骤,就能建立 Visual Studio Online 帐号,以及建立团队专案,修改完成后,我们开放这项功能到其中两个 Scale Units 进行实验 (总共六个 Scale Unit)。

我们在两个 Scale Unit 中,开放改善 IDE 建立团队专案流程的功能

我们在 IDE 中改善建立专案流程的实验结果可以在图四中看到。这个改善增加了新使用者建立团队专案的数据,从 3% 提升到 20%,足足有 7 倍的提升。

IDE 建立专案流程的改善,让新使用者建立团队专案的机率从 3% 提升到 20%

同时,我们也改善了 Web 版本的注册流程,从画面上可以看到是完全不同的注册画面,在图五中可以看到我们对 Web 版本登入画面的改变。

可以看到我们简化了 Web 版本的注册流程,并把团队专案的建立移到第二屏

我们计算了在注册同一天也建立团队专案的使用者人数,人数从接近 18% 提升到 30% (1.7 倍),可以看到图表中从深蓝色变为紫色的部分,相对于 IDE 改变后的数据成长,在 Web 版的改善率这么低让我们感到十分讶异。

由于另外两个新功能的结果不如预期,导致 Web 版本建立帐号流程改善的效果不好,在我们关闭其中一个结果之后,主要的结果就更清楚了。

根据追查之后发现,这次的新功能发布除了 Web 登入流程改善之外,同时间还有另外一个实验也在进行,导致许多不被预期的使用者也被引导来进行帐号注册,然后没有继续进行更进一步的使用,也因此登入流程改善的数据被影响了,增长的数据就没有那么的明显。这其实也是一个不正确对照组数据的好例子,两个实验的结果互相干扰,当我们停止另外一个实验的干扰之后,团队专案被建立的数据就上升了,可以参考上表中的浅蓝色部分,数据上升到了 50% (2.8 倍的成长,也是 IDE 数据的 2.5 倍)

上面的例子告诉我们,实验的结果可能有好有坏,而对的实验不一定会在一开始就有好的成长,就算这个方向是对的,我们还是必须继续进行反覆的实验,根据实验结果调整并再次验证,才能证明实验的方向是否正确。

参考资料

  • Branch 是分散式版本控制系统中,我们可以除了透过切割不同的 Branch,让不同功能的开发可以同时进行并且不会互相干扰,而在 Branch 开发完成之后,我们可以透过 Merge 将 Branch 的内容合并回主要分支之中,让程式码同步,而当 Branch 由主要分支中切出来的时间过长时,由于其他人同时还是会不断对主要分支签入新的程式码,因为可能会因为改到同一分程式而在 Merge 时遇到 Conflict,工程师必须要解决 Conflict 才能让 Merge 的工作继续进行。
  • Validated Learning - 这个名词出现在 *The Lean Startup.* 一书中,代表有系统将新功能开放给顾客使用,并根据我们所希望收集的资料,针对客户的使用情况与反应收集数据,观察数据来评估我们的方向是否正确,然后再次进行同样的循环,让自己的功能往对的方向前进。
2017-08-20 17:161586

评论

发布
暂无评论
发现更多内容

bzz矿机分币系统开发,BZZ矿机节点APP搭建

认识微前端:一种用于前端 Web 开发的微服务

devpoint

大前端 SPA

基于MySQL Binlog 实现可配置的异构数据同步

王博

springboot+mongo多数据源简单配置

Mars

mongo 多数据源配置

算法设计与分析——递归详解

若尘

算法 递归 6月日更

记录下PVE 装openwrt 后 pve 本身不能上网问题

三爻

Java 中 HashSet 的 removeAll 性能分析

落日楼台H

Java 性能 HashSet removeAll 集合删除

项目又延期了

escray

学习 极客时间 朱赟的技术管理课 6月日更

【Flutter 专题】115 图解自定义 View 之 Canvas (四) drawParagraph

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 6月日更

NQI质量基础设施“一站式”服务平台开发解决方案

源中瑞-龙先生

开发 解决方案 NQI 质量基础设施“一站式”

面试官问我redis的string应用场景,我是这么回答的!

李阿柯

php lua redis 面试

【Vue2.x源码学习】第一篇-源码环境搭建

Brave

源码 vue2 6月日更

[万字总结] 一文吃透 Webpack 核心原理

范文杰

大前端 webpack 6月日更

40 图|硬核解析用 Mac M1 玩转 SpringCloud

悟空聊架构

Spring Cloud Mac SpringCloud Alibaba m1 6月日更

《面试官:谈谈你对索引的认知》系列之B+树

架构精进之路

MySQL 索引结构 6月日更

如何理解梯度下降算法Gradient Descent algorithm John 易筋 ARTS 打卡 Week 49

John(易筋)

ARTS 打卡计划

树莓派上的自动化---自动发送IP地址到邮箱

IT蜗壳-Tango

树莓派 IT蜗壳教学 6月日更

六一限定,致每一个追光者

脑极体

云原生中定时弹性伸缩之CronHPA实战

雪雷

6月日更

Grpc-go源码刨析

王博

Spring Cloud Alibaba 实战

Damon

微服务 SpringCloud Alibaba 6月日更

让你编程能力秃飞猛进的好习惯

程序员鱼皮

Java c++ Python 大前端 自学编程

【译】JavaScript 代码整洁之道-变量篇

KooFE

JavaScript 大前端 变量 6月日更 整洁代码

Rust从0到1-泛型-trait

rust 泛型 Trait generic

GitOps系列一:为什么协作技术对GitOps至关重要?

极狐GitLab

架构抉择之分合矩阵

凌晞

架构

算法训练营 - 学习笔记 - 第八周

心在飞

Dubbo 服务在线测试

青年IT男

dubbo

网络攻防学习笔记 Day32

穿过生命散发芬芳

网络攻防 6月日更

react源码解析3.react源码架构

全栈潇晨

React React Hooks react源码

总结笔记 Datawhale-23期数据挖掘-心跳信号分类预测

万里无云万里天

数据挖掘 6月日更 Datawhale

微软开发部门DevOps 经验谈——从经验中学习_微软_微软中国_InfoQ精选文章