导图社区 高效研发:硅谷研发效能方法与实践
这是一篇关于个人研发效能提升、流程研发效能提升、团队研发效能提升,管理和文化的思维导图,希望对大家有所帮助。
编辑于2022-06-07 16:46:20高效研发:硅谷研发效能方法与实践 高俊
困扰
团队角度
1.加班也不少,但是产品发布还是常常延期,上线后产品问题频发。
2.从需求分析、产品设计、开发、测试到部署一个环节都不少,但最终发布的产品却与用户需求偏差很大。
3.产品发布上线时出现大量提交、合并,导致最后时刻出现很多问题,团队成员集体熬夜加班,却将大把的时间花在了等待环境、等待验证上。
4. 产品发布上线时出现大量提交、合并,导致最后时刻出现很多问题,团队成员集体熬夜加班,却将大把的时间花在了等待环境、等待验证上。
个人角度
1.疲于应付业务,没有精力去精进技术。
2.工作过程中有大量的电话、即时聊天消息干扰,工作思路常常被打断。
3.对众多的工具(比如Git、命令行)的使用仅限于表层,工作效率较低,想提高却因为工具太多不知道从何下手。
4.有知识焦虑,但是没有找到好的办法系统地提高个人工作效率。
研发效能
学习实践方法论
黄金圈原则
概念
Why: 目标
How: 原则、指导思想
What: 具体实践
解读
子主题
子主题
研发效能
研发效能定义
子主题
软件研发本质
基本原则
不要阻碍开发人员(Don't Block Developer)
本质
流水线
灵活性
最终产品目标的灵活性
比如精益开发中:使用MVP(最小可行性产品)来不断验证产品假设
节点之间关系的灵活性
每个节点的灵活性
每个节点上开发人员的灵活性
研发效能模型
研发流程优化
针对灵活性特点1:最终产品目标的灵活性
主要是提高流程的灵活性,让它能聚焦最终产生的用户价值,以终为始地指导工作
针对灵活性特点2:节点间关系的灵活性
主要聚焦流水线的顺畅性,以保证用户价值的流动受到的阻力最小。
团队高效研发实践
针对灵活性特点3:每个节点的灵活性
主要聚焦每一个生产环节的工程实践进行提高。
个人高效研发实践
针对灵活性特点4:每个节点上开发人员的灵活性
争取让每个开发人员都能适当地关注业务、以终为始,同时从方法和工具上提高开发效率,实现1+1>2的效果。
管理和文化
管理: 任何流程、实践的引入和推广,都必须有合理的管理方法来支撑
文化:是一个团队工作的基本价值观和潜规则
研发效能度量
定义
研发效能度量代表一组可量化的数据或参数,用来跟踪和评估开发过程的健康状况。 研发效能度量代表一组可量化的数据或参数,用来跟踪和评估开发过程的健康状况。
作用
跟踪团队的表现,提高团队的绩效
提高项目计划的精确度
了解流程是否高效,寻找需要改进的关键领域
效能难以度量的原因
使用部分指标衡量复杂整体
人们倾向于关注局部指标
度量指标难以直接与用户价值关联
效能度量的根本原则
效能度量不要与绩效挂钩,而应该作为参考和工具,帮助团队提高效能。
效能度量的方法
1.目标驱动,选择正确的度量指标
度量不是目的,只是手段。我们首先要明确需要解决什么问题,然后根据这个目标,寻找合适的指标和方法进行度量
度量分类
准确度:关注产品是否跟计划、用户需求吻合,能否提供较大的用户价值
速度:天下武功,唯快不破,速度指标主要用来衡量团队研发产品的速率
质量:如果质量有问题,产品的商业价值会大打折扣
个人效能:个人开发过程中的效率指标,比如开发环境生成速度、本地构建速度等
2.先全局出发找问题,再深入细节解决问题
推荐一个工具:累积流程图(Cumulative Flow Diagram)。具体方法:用横轴表示日期,用纵轴表示每天统计的各节点任务数量进行绘制。比如,我们统计待办(Backlog)、开发(Dev)、测试(Test)、生产(Production)这4个节点。 
3.使用度量定位问题和验证解决方案
4.使用度量定位问题和验证解决方案
个人维度的指标也有很多,其中比较关键的有以下三个: 1. 本地构建时长; 2. 本地测试时长; 3. 联调环境获取时长。
5. 获取尽量公平的主观效能评价
个人高效研发
准确性
做好任务选择(以终为始,寻找最重要的任务)
自己定任务
我们应该在每天的工作间隙,花一些时间考虑自己去定义任务,问一问自己以下几个问题: 1. 预先定义的任务是否还需要做? 2. 有没有其他更重要的任务应该替代当前手上的任务? 3. 临时产生的干扰任务怎么处理?需要我来处理吗? 这些思考可以帮助我们更好地从当前任务的细节中抽身出来,让我们思路更清晰,避免把时间花在低优先级的任务上,提高准确性,进而提高投入产出比。
预先计划的任务
临时产生的任务
自己定义的任务
聚焦目标,以终为始
聚焦目标,以终为始,为目标服务的任务才最重要。 作为高效开发人员,常见的目标包括业务成功、帮助团队、个人成长。
业务成功
帮助团队
个人成长
无情的筛选,少即是多
生命有限,而工作无限,所以我们必须要对工作排优先级。 提高筛选能力的过程中发现“数字3原则”很有效,即强制把要做的事、要达到的目标,限制在3个以内。 在后续的工作计划中,也强迫自己使用数字3原则,无论是三年规划、半年规划、本周规划,还是当天工作,都“无情”地筛选出最重要的3件事。这个方法对提高准确性的效果非常好。
“数字3原则”:强制把要做的事、要达到的目标,限制在3个以内。
做好方案选择(追根究底,寻找最高效的解决方案)
如果我们能把业务目标和技术实现结合起来思考,常常能对业务的解决方案做出一些改进,甚至重新设计出更好的方案。而这样的改进,对个人研发效能的提高帮助非常大。 如果我们能把业务目标和技术实现结合起来思考,常常能对业务的解决方案做出一些改进,甚至重新设计出更好的方案。而这样的改进,对个人研发效能的提高帮助非常大。
高效沟通(利用信息的准确传递来寻找、调整目标)
高效沟通的重要作用: 1. 提高研发准确性 2. 帮助研发人员提高个人影响力
同理心原则
沟通是一个双方交流的过程,我们沟通的目的往往是希望在对方身上起作用,所以要从对方的角度考虑如何沟通。具体来说,我们需要做到至少以下三个方面: 1. 了解对方的知识背景,从而使用他能理解的语言去沟通; 2. 了解对方想要知道什么,从而能够不绕弯路,高效答复; 3. 了解对方的出发点,从而结合自己的出发点找到双赢的方向。
外在与内在同样重要
外在与内在同样重要在开发工作上表现为我们不但要重视实际的工作,也要重视别人对我们工作成果的感知。 很多开发人员从内心抵触PPT,我觉得这就是高效工作的一个重要阻碍。 我们确实需要花一些精力,去考虑如何把我们做出的东西更好地呈现出来。当然,我并不是说要来虚的,具体做出有用的东西才是王道,是前提。
冰山原则
这个原则对软件技术人员和非技术人员间的高效交流非常有用。它指的是一个软件应用系统很复杂,就像一座冰山一样巨大。但是,正如巨大的冰山只有很小的一部分露出水面一样,软件系统也只有其中一小部分对用户可见。如果你的沟通对象对软件不熟悉,他就会认为,冰山上的可见部分就是全部工作,或者说是绝大部分工作。
建设性冲突
从个人高效研发角度来说,建设性冲突也是提高准确性的有效工具。这一点在产生高质量、高效率的设计方案方面表现得尤为突出。
定义
建设性冲突是指冲突各方目标一致,但由于实现目标的途径手段不同而产生冲突。
基本核心
争论
只有在争论的过程中大家才能对问题进行深层次的挖掘,从而碰撞出思想的火花。
目的一致
只有在争论的过程中大家才能对问题进行深层次的挖掘,从而碰撞出思想的火花。
建议
放下面子,用开放的心态去接受他人的方案
放下面子,用开放的心态去接受他人的方案
如果争论过于激烈,可以明确表达自己争论的目的不是输赢,而是大家一致追求的优秀架构和产品,这样可以让大家冷静头脑,再次明确建设性冲突的目的一致的核心出发点。
管理者视角
个人如何在任务选择和方案选择方面提高准确性,以及如何使用高效沟通这一工具帮助我们提高效能。 从管理者视角出发,考虑如何围绕这三个方面去设计、修改团队实践,从而帮助研发人员提高个人研发活动中的准确性。
推动全栈研发
在全栈研发的模式下,研发人员对整个产品以及整个流程有更多的了解和把控。这样就更容易从结果出发,找到最高效的解决问题的办法。如果团队没有采用全栈研发模式,应该鼓励研发人员多参与到相关环节的讨论中去。比如让研发人员参与产品设计以及测试方案的讨论,让测试团队参与研发人员的设计方案讨论以及运维人员的部署方案相关讨论。
鼓励进行设计方案讨论
很多团队或多或少都会有一些设计方案的讨论,但这样的讨论往往数量不够、深度不够。团队的管理者应该多安排和鼓励团队成员在开始具体工作之前多花一些时间考虑、讨论应该如何解决问题,而不是简单思考之后马上扑到实现的细节中去。这样的建议对于经验不太丰富的研发人员来说,尤其有效,因为他们更容易犯这种对设计方案思考不足的错误。
鼓励高校沟通
首先要纠正部分团队成员对沟通的理解误区,让他们了解沟通与编码同样重要,有条件的话,可以提供一些相关培训,但也要注意不能矫枉过正,要杜绝只注重外在包装、PPT而忽略编码的错误。
速度
“快”之所以重要,主要有两个原因。 第一:显而易见,在方向正确的前提下,任务完成得快,效率自然就高。 第二:“快”可以让我们迅速得到反馈,从而可以尽快调整方向,有效减少软件研发的不确定性给研发效能带来的负面影响。
应用高效实践提高完成任务的速度
心无旁骛,集中精力深度工作
深度工作是由麻省理工学院计算机科学博士、乔治城大学计算机科学副教授卡尔·纽波特(Cal Newport)提出的。 深度工作指的是在无干扰的状态下才能专注进行的专业活动。深度工作使个人的认知能力达到极限,能够创造新价值,提升技能,而且难以复制。 肤浅工作是与深度工作相对应的,指的是对认知要求不高的事务性工作,它往往在受到干扰的情况下开展。肤浅工作通常不会为世界创造太多的新价值,而且容易复制。 在信息过载越来越严重的当下,我们收到大量的干扰,往往会陷入围绕肤浅工作的表面忙碌。而深度工作则是可以让我们脱颖而出,成为不可替代的人的办法。 番茄工作法工具推荐: Toggl
番茄工作法工具推荐:Toggl
合理使用工具提速
应用快速迭代的思路获取快速反馈
原则1:完成比完美更重要
具体实践1:在进行架构设计的时候不要过度计划
具体实践2:在设计和实现功能时,应该注意追求简单化
原则2:让代码尽快运行起来
脚手架
单元测试
原则3:设置本地代码检验机制
原则4: 尽早解决合并冲突
代码原子性提交
频繁Pull代码到本地
管理者视角
调整会议时间为深度工作提供环境
提供精准测试环境
固化个人优秀实践,并应用到团队中
推动代码原子性实践
可持续性
做好精力管理,保持充分的精力去面对这个行业的挑战
拥抱无聊,控制手机依赖
用反向行事日历来确保休息和高效工作
使用80/20原则寻找研发活动中的关键因素
在优化目标的选择过程中,我们选择20%的关键活动
在日常工作和优化工作的时间分配上,我们只使用20%的时间去做优化
对关键活动进行优化
研发活动中长期有效原则
抽象
用子系统来隐藏一个领域的内部细节,就是抽象。
分而治之
对系统进行拆分处理的过程,就是分而治之
高频发生的活动
第一类是重复,并且不需要太多思考的活动
利用DRY(Don't Repeat Yourself)方法优化关键因素
代码逻辑的重复
流程的重复
第二类则是研发中经常使用的某些专业技术,它重复发生,但同时需要我们积极思考。
精通所处领域的技术
目标驱动和兴趣驱动相结合,提高幸福感和保持创新的动力
管理者视角
看产出而不是看工时
提供类似Google 20%创新时间的实践
组织Hackathon,提高员工工作积极性
高效选用工具提高研发速度
常见工作任务系统性工具优化(5种工作场景)
操作系统通用操作
窗口切换
macOS
Cmd+Tab
程序启动
macOS
Spotlight(Cmd+space)
优化工具:Alfred/QuickSilver
窗口管理
macOS
BetterTouchTool
剪贴板管理
Clipy/Maccy
输入和编辑
语音输入
讯飞输入法
文字快速输入
TextExpander
重新定义按键
Karabiner-Elements
实体按键
Kinesis Pro2
HHKB
知识管理
云盘
笔记
编写文档的工具
思维导图
截屏/录屏
Monosnap/ishot
KeyCastr
GIF Brewery 3
asciinema-命令行终端录制
处理PDF文件的工具
浏览网页
Chrome
Octotree
smartUp Gestures
Firefox
Edge
编程(详细见下)
编程
Git
Git和代码原子性
代码原子性提交特点
提交包含一个不可分割的特性、子特性、修复或者优化
提交大小合适读者阅读
代码入库不会影响分支上的功能
代码原子性提交好处
提高代码可读性,从而提高代码质量
促进代码早日入库,从而提高CI(持续集成)
促进代码拆分,从而实现更好的架构
方便问题定位和回滚,从而提高产品可靠性
Git可以助力代码原子性提交的原因
Git提供方便、灵活的提交和分支处理功能,使得我们可以灵活地产生提交、修改提交、拆分提交,甚至改变提交的先后顺序
Git是一个分布式代码仓管理系统,每个开发人员在本地都有一个代码仓,从而可以放心在本地代码仓中使用上述功能,不用担心会影响远程共享代码仓
Git支持原子性的五种基本操作
基本操作一:把工作区代码改动的一部分转变为提交
整个文件提交:git add <filename>
文件的部分改动提交:git add -p <filename>
基本操作二:对当前提交进行拆分
git log --graph --oneline --all git show git branch temp # temp分支的作用是预防代码丢失 git reset HEAD^ git add -p filename # 分开提交
基本操作三:修改当前提交
git commit --amend git add
基本操作四:交换多个提交的先后顺序
git branch temp git log --oneline --graph 详细参考《Git工具——重写历史》
git rebase --interactive
基本操作五:修改非头部提交
实现代码提交原子性的Git工作流
工作流一:使用一个分支完成所有需求的开发
第1步:一个原子性的提交完成后,使用之前的操作改变提交顺序的方法,把它放到距离origin/master最近的地方。
第2步:把这个提交发送到代码审查系统进行质量检查,包括代码审查和机器检查,在等待质量检查结果的同时,继续进行其他提交的开发
第3步:如果发送到代码审查系统的提交没有通过质量检查,则需要对提交进行修改,修改之后返回第2步
第4步:如果发送到代码审查系统的提交通过了质量检查,就把这个提交推送到主代码仓的共享分支上,然后继续其他分支的开发,回到第1步。
工作流二:使用多个分支完成所有需求的开发
第1步:切换到某一个分支对某需求进行开发,产生提交。
第2步:提交完成后,将其发送到代码审查平台上进行质量检查。在等待质量检查结果的同时,切换到其他分支,继续其他需求的开发。
第3步:如果第2步发送到代码审查平台的提交没有通过质量检查,则切换回这个提交所在分支,对提交进行修改,修改之后返回第2步。
第4步:如果第2步发送到代码审查平台的提交通过了质量检查,则切换回这个提交所在分支,把这个提交推送到远端代码仓中,然后回到第1步进行其他需求的开发。
Vim
https://jungejason.github.io/vim-commands/
特点
Vim独特的命令模式使得编辑文档非常高效(命令模式)
Vim是跨平台做得最好的编辑器,没有之一(跨平台性)
高效Vim使用
命令组合
常用命令
打开文件,进行设置操作
移动光标
编辑文本
查找、替换
可视模式
更广泛的Vim工作场景
Vim不是个人主力IDE
Vim与其他工具进行集成工作
使用Vim作为其他工具的编辑器
使用管道
在Vim中调用系统工具
命令行工具集
高效命令行环境
模拟终端
item2
Terminator
Hyper
Upterm
选择Shell
Zsh
Finsh
Bash
具体的Shell配置
远程SSH的处理
最大痛点:连接断开会造成信息丢失
通过在远程服务器上运行持久的会话session
Tmux/Screen
保持连接不中断的工具
Mosh
有效命令行工具
日常操作的提效工具和技巧
第一个场景:列举文件夹和文件,查看文件
列举文件夹和文件
ls
tree
alder
exa
查看文件
cat
bat
第二个场景:查找并打开文件,进行查看或编辑工作
第三个场景:在文件夹之间跳转
第四个场景:文件管理
开发中常见工作
 1)只有重复性高的工作,才最适合使用命令行工具;否则,用来适应工具的时间,可能比节省下的时间还要多。这是命令行的一个基本特点。 2)我们这里推荐使用命令行,并不是说一定要避免使用GUI工具。正如软件研发具有高度灵活性一样,工具的使用也有高度的灵活性。我们应该根据具体任务来选用工具。在真正的工作中,最高效的情况往往是同时使用命令行工具和GUI工具,互为补充。
常见工作一:Git
原生Git
tig
grv
lazygit
gitin
常见工作二:Web访问
curl
HTTPie
常见工作三:对JSON进行处理
jq
fx
jq.node
常见工作四:查找、关闭进程
kill
pkill
fzf
常见工作五:查看日志文件
Inav
tail -F
常用工作六:命令行本身的实用技巧
!$ : 代表上一个命令行的最后一个参数
!! : 代表上一条命令
工具集成
使用管道对命令行工具进行集成
使用多个管道灵活连接多个工具
比如:grep/xargs
使用模糊查询工具
fzf
pick
selecta
ctrIp
fzy
对集成开发环境IDE进行配置,让IDE和周边工具集成
IDE与命令行工具的集成
IDE与代码仓的集成
工作入口一致性性优化
命令行
IDE
桌面快捷启动工具
网页浏览器
研发流程优化
研发流程优化基本目标和原则
☆☆☆ 从实际出发、以终为始的实用主义,是高效研发最重要的原则。 开展提效工作时,应该按照目标、原则和具体实践的顺序进行思考。 首先一定要通过具体实践的例子对这些目标和原则进行深入的理解。这是提效工作能够成功的关键。之后才是根据这些目标和原则,结合自己团队的实际情况去寻找合理的具体实践。
目标:寻找用户价值(流程产出物的准确性)
原则1:衡量每一个时间段成果的标准应该是价值假设方面的进展
这个原则是说,我们工作追求的效果应该是团队能够学习到如何更好地为用户提供价值,而不是开发了多少功能。数量不重要,学习效果才重要。
原则2:使用最小可行性产品(Mininum Viable Product)来帮助学习
这里的关键点是,要以探索价值为出发点设计产品,最快地验证价值假设,功能要尽量少,能够使用就可以。具体方法有数据驱动、A/B测试、灰度发布等.
目标:提高用户价值流动效率(流程的顺畅性)
原则1:让功能尽快流动
关键原则是降低提交的交易成本(TransactionCost)。 提交的交易成本指的是每一个提交都需要做的额外工作。只有把这个工作量降下来,才能让功能拆分有价值,否则会抵消掉拆分带来的好处。
实践:提高本地构建速度
实践:提供方便的自测环境
实践:自动化测试
实践:持续集成
实践:自动化定位问题提交
原则2:让节点之间的联动更加顺畅
实践:自动化关键流程
在关键流程方面,代码集成是一个容易出现问题的步骤,而CI/CD(持续集成/持续交付)流水线就是解决这个问题的有效办法。尤其是CI,应该说对所有软件开发公司都有巨大价值,一定要尽量利用CI提高集成效率。在工具集成方面,则应该推动工具的网状互联,从而提高自定义流程的灵活性.
实践:提高工具之间的网状互联性
原则3:让节点之间做合理的融合
比较有效的方式是:职能团队提供平台和工具,让全栈工程师能够自己处理端到端的工作。
原则4:发现整个流程中的瓶颈并解决它们
第一步,找到系统中的瓶颈; 第二步,最大限度地发挥瓶颈的产能(Exploit),尽量通过提高效能的办法解决瓶颈; 第三步,让企业的所有其他活动都让步于瓶颈改善工作; 第四步,打破(Elevate)瓶颈,如果第二、三步无效,就通过给瓶颈节点增加资源的方法来解决瓶颈; 第五步,重返(Repeat)第一步,找出新的瓶颈,持续改善。
实践:可视化
实践:复盘
代码入库流程优化
代码入库前的流程优化
核心根本目标:持续开发
原则1:规范化、自动化核心步骤
代码入库前三大开发步骤
实践
实践一:提高开发环境获取效率
方式1:借助基础设施即代码(IaC)系统
方式2:提供机器镜像和配置脚本
实践二:规范化、自动化本地检查
实践三:建设并自动化代码入库前的检查流程
原则2:快速反馈,增量开发
提供快速反馈,促进增量开发这一原则指的是开发人员可以快速验证已经完成的开发工作。 更直接的表述是,边开发边验证。具体的工程实践主要包括灵活使用各种Linter和测试、建设并优化沙盒环境、应用实时检查工具。
实践
实践一:灵活使用各种Linter和测试
方法1:以服务化的方式,提供检查的能力
方法2:用命令行工具来封装各种检查
实践二:建设并优化沙盒环境
实践三:使用实时检验工具
总结
代码入库后的流程优化
核心根本目标:高效实现持续集成(CI)、持续交付(CD)、持续部署(CD)
持续集成(Continuous Integration, CI)、 持续交付(Continuous Delivery,CD)、 持续部署(Continuous Deployment, CD) 高效实现这三个“持续”,正是代码入库之后流程优化的根本目标。
定义
持续集成(CI)
定义:在团队协作中,一天内多次将所有开发人员的代码合入同一条主干。它的目的在于帮助开发人员尽量早、尽量频繁地把自己的改动推送到主仓进行集成,从而减少大量代码冲突引发的低效能问题。
持续交付(CD)
定义:持续交付是一种软件工程方法,在短周期内完成软件产品,以保证软件保持在随时可以发布的状态。也就是说,对每一个提交,把集成后的代码部署到“类生产环境”中进行验证。如果代码没有问题,后续就可以手动部署到生产环境中。
持续部署(CD)
定义:持续部署则更进一步,它会立即把持续交付产生的产品自动部署给用户使用。持续部署的定义是,将每一个代码提交,都构建出产品直接部署给用户使用。
共同的本质
让每一个代码提交都经过一条流水线进行自动化检验,通过后进入下一个阶段。这里的下一个阶段具体包括代码并入主仓、产品进入测试环境、产品进入类生产环境、产品最终进入生产环境等
原则
原则一:流水线的测试要尽量完整
原则二:流水线的速度要尽量快
方法1:如果通过增加硬件资源来提升运行速度需要的成本太高的话,可以对测试用例按优先级进行分类,在流水线运行的时候,不需要每次都运行所有测试用例,只选择其中几次进行全量测试即可。
方法2:如果通过增加硬件资源来提升运行速度需要的成本太高的话,可以对测试用例按优先级进行分类,在流水线运行的时候,不需要每次都运行所有测试用例,只选择其中几次进行全量测试即可。
方法3:运行测试的时候,按照一定的顺序运行测试用例。比如可以先运行速度快的用例,以及历史上容易发现问题的用例,这样可以尽早发现问题,避免不必要的资源浪费。
原则三:流水线使用的环境要尽量和生产环境一致
方法一:软件包最好只构建一次,保证各种不同环境都用同一个包。如果不同的运行环境需要不同的参数,可以以环境变量的方式传递给软件包。
方法二:使用Docker镜像的方式,把发布的产品以及环境都打包进去,实现环境的一致性。在我看来,这正是Docker的最大好处。
方法三:尽量使用干净的环境。比如,测试时,使用刚从镜像产生的系统;又比如,使用红黑部署,每次产生新的部署时,直接丢弃旧的环境
5个持续关键点
研发流程优化的常用方法
分支管理策略
分支管理
共主干开发分支
定义:基于主干的开发方式也叫共主干开发分支方式(trunk-based)
分类:共主干开发方式下,根据是否允许存在短期的功能分支(Feature Branch)
主干开发有功能分支
主干开发无功能分支
Facebook的选择:禁止功能分支
代码合并回master时的选择
rebase
由于只采用一个开发分支,并且只允许使用rebase操作,Facebook的整个开发模式非常简单,步骤大致如下: 第一步,获取最新代码:  第二步,本地开发,然后执行以下命令产生本地提交:  第三步,推送到主代码仓的master分支:  在rebase的时候,如果有代码冲突就先解决冲突,然后使用以下命令更新自己的提交:  最后,重复步骤3,也就是重新尝试推送代码到主代码仓。
facebook的选择
merge
主干分支模式的优势
Facebook实践措施
几千名开发人员同时工作在同一条主干
不使用功能分支,直接在master上开发
必须要使用rebase才能入库,不能使用merge
主干开发分支模式优点
促进开发人员把代码频繁合入主仓进行集成检验
确保线性的代码提交历史,给流程自动化提供最大方便
其他主要分支方式
方式一:Git-flow工作流
分支
长期分支
master
develop
短期分支
新功能分支
发布分支
热修复分支
步骤
Git-flow工作流的特点是对各种开发任务都有明确的规定和步骤: 开发新功能时,从develop分支拉出一个前缀为feature-的功能分支。 在该功能分支上进行开发工作,完成之后合并回develop分支,并删除该功能分支。 发布新版本时,从develop分支拉出一个前缀为release-的发布分支,部署到测试、类生产等环境进行验证。 如果发现问题,则直接在发布分支上修复。 如果验证通过,则把该发布分支合并回master和develop分支,并在master分支上打tag,同时删除该发布分支。 发布热修复和发布版本相似,它从master拉取分支,完成后合并回master和develop(或者当前发布分支)
缺点
流程复杂,学习成本高
容易出错,比如容易出现忘记合并到某个分支的情况,不过这个问题可以使用脚本自动化来解决
不方便进行持续集成
有太多的代码分支合并操作,解决冲突成本比较高
方式二:Fork-merge
步骤
开发人员对主代码仓贡献代码的步骤如下: 1)开发人员产生个人代码仓; 2)开发人员在本地备份个人代码仓; 3)开发人员在本地开发,并把代码推送到自己的个人代码仓; 4)开发人员通过Web界面,向主代码仓的管理人员提出推送请求; 5)主代码仓的管理人员在自己的开发机器上取得开发人员的提交,验证通过之后再推送到主代码仓。
缺点
步骤繁琐,不太适用于公司内部
优点
类似主干分支模式。主仓干净,便于管理
方式三:由功能分支组成的发布分支工作流
步骤
具体方法是利用工具对分支管理实现高度自动化。 开发人员在Web界面上自助产生功能分支。 编码完成后,通过Web界面对功能分支进行组合,产生发布分支并验证和上线,上线之后分支才会自动合入主库。
优点
基于功能进行开发。开发人员可以快速产生功能分支进行编码、验证工作
灵活:能够方便地对功能进行组合并发布到对应环境中进行测试和发布。出了问题,可以方便地添加或者删除功能分支
缺点
对工具的依赖比较高
该方式大量封装底层的实现,使得开发人员不清楚底层的情况,在出现问题时不太容易解决。
分支管理策略的原则
尽量减少长期分支的数量。这个原则可以简化流程,降低出错率
代码尽早合并回主仓。这个原则让我们可以使用CI/CD等方法提高代码的质量
无论使用哪一种策略,都要严格规定管理流程,最好通过工具帮助执行
分支管理策略QA
代码合并时是否使用merge?
代码在合并到主干的时候,有rebase和merge两种方式可供选择。通常来说rebase的优势更明显,但使用merge也有一定好处。第一是解决冲突工作量比rebase小,第二是可以清晰地在分支里看到一个功能的所有提交。而在rebase中,一个功能的提交往往是分散的。如果团队规模很小,产品处于POC阶段,merge会比rebase更方便一些。
是否使用单分支开发方式?
单分支开发集成早,质量比较好,不过对团队成员成熟度以及流程自动化程度要求都比较高。所以,如果你的团队规模比较小,或者成员比较有经验的话,应该尽量使用单分支开发方式。另外值得一提的是,即使选择多分支开发模式,也要想办法把集成提前
如果提供功能分支让成员共享,应该在何处建立这个分支?
如果团队规模不大,可以允许在主仓创建功能分支,不过要注意定时删除不再使用的分支,避免影响Git的性能。如果团队规模较大,可以考虑使用Fork-merge方式,在上面提到的个人代码仓里创建功能分支,从而避免对主仓造成污染。
分支管理总结
发布策略
发布分支
在共主干开发模式中,在需要发布的时候会从master拉出一条发布分支进行测试,稳定之后发布给用户使用。 如果在发布分支中发现问题,先在master上修复,然后使用cherry-pick命令把修复合并到发布分支上。 分支上线之后,如果该分支需要长期存在,比如产品线性质的产品,就保留分支。 如果该分支不需要长期存在,比如SaaS产品,我们就可以存档或直接删除分支。Facebook采用的是后者。
周部署
周部署流程: 第一步,从master上拉出一个发布分支:  第二步,在发布分支进行各种验证。 第三步,如果验证发现问题,开发人员提交修复到master,然后使用cherry-pick命令把修复合并到发布分支上。接着回到第二步继续验证,直到验证通过。  验证通过后,将当前发布分支部署到生产环境。我们把该分支称为当前生产分支。同时将上一次发布时产生的生产分支存档或者删除。
日部署
流程类似热修复部署
热修复部署
热修复部署: 在进行热修复部署时,先在当前生产分支上拉出一个热修复分支,具体步骤分析如下。 第一步,拉出一个热修复分支:  第二步,开发人员提交热修复到master,然后使用cherry-pick命令将其合并到热修复分支上:  第三步,进行各种验证。 第四步,如果验证中发现问题,回到第二步重新进行修复验证。如果验证通过,则发布当前热修复分支,同时将这个热修复分支设置为当前的生产分支。后续如果再有新的热修复,就从这个分支拉取进行发布。
总结:代码分支管理和部署流程图
详细流程参考文章: 《Rapid Release at Massive Scale》
全栈思路
优化方法
通过DevOps和SRE打通开发和运维
DevOps和SRE
异同
DevOps定义
DevOps(Development和Operations的组合词),是一种重视软件开发人员(Dev)和IT运维技术人员(Ops)之间沟通合作的文化、活动或惯例。它通过软件交付自动化和架构、流程的变更,使软件的构建、测试、发布更加快捷、频繁和可靠。
SRE定义
SRE(Site Reliability Engineer,网站可靠性工程师),是一个职位,是软件工程师和系统管理员的结合,主要目标是创建可扩展且高度可靠的软件系统。为达到这个目标,SRE需要掌握如下相关知识:算法、数据结构、编程、网络编程、分布式系统、可扩展架构、故障排除等。SRE使用系统和工具支撑其完成工作,比如自动化发布系统、监控系统、日志系统、服务器资源分配和编排工具等,而这些系统和工具往往需要自己开发和维护
异同
DevOps是打通开发和运维的文化和惯例,而SRE是DevOps的一个具体实践。它们的相同点在于都是通过打通Dev和Ops去提高研发效能;区别在于,DevOps是文化,SRE是职位。如果要类比的话,DevOps与SRE的关系,就像敏捷跟Scrum的关系
目标
DevOps和SRE要解决的根本问题:开发和运维这两个角色的目标不一致,导致研发和上线流程不顺畅,最终严重影响软件上线的效率和质量
原则和方法
原则一:协调运维和开发人员的目标、利益
方法:全栈开发
全栈开发是指每一个工程人员的工作涵盖了不止一个领域,虽然他专攻这些领域中的某一个,但会对所有领域负责。也就是说,全栈开发人员对产品结果负责,而不是只对某一个具体环节负责,从而实现目标和利益的统一。
第一,增加新的运维角色,用开发的方式去做运维
第二,将开发人员的职责描述修改为快速开发和上线稳定的高质量产品,让他们也参与到一部分运维工作中去。
原则二:推动高效沟通
方法1:设置聊天室(比如IRC),用于沟通部署进展和问题
方法2:引入ChatOps,通过自动化的方式提高部署相关的沟通
方法3:把代码提交相关的信息提供给大家自助使用
实践
步骤1:对团队目标达成共识,并重新定义职责
步骤2:设计制定CI/CD、快速反馈、高效团队沟通等流程
步骤3:引入工具,实现自动化
高效信息流通
团队成员愿意共享是有效沟通的前提
要让团队成员了解信息沟通的重要性
建设机制,鼓励共享的行为
设计流程和使用工具,推动研发信息高效沟通
战略目标相关的信息
代码相关的信息
研发过程中用到的各种文档
各种标识信息
沟通工具的选用技巧
沟通方式比较
合理选择沟通方式
解决方法:解决这个问题的办法很简单,就是要求大家针对不同的情况,对实时性、可追溯性,以及对他人的干扰程度进行综合考虑
如果问题不紧急,尽量使用邮件,避免使用即时聊天工具和电话。为了确保大家能够及时回复邮件,可以在团队内规定检查邮件的频率,比如每天至少检查一次或者两次。如果问题紧急,使用即时聊天工具、电话。如果要讨论的问题比较复杂,或者是非常紧急,则直接选择电话,或者面对面沟通。
团队高效研发
研发环境:让开发人员不再操心环境
开发机器
IDE
本地环境与联调环境
开发过程中使用的各种工具、数据和配置
测试环境与类生产环境
提供高效研发环境的原则
舍得投入资源,用资源换取开发人员的时间
对环境的获取进行服务化、自助化
注重环境的一体化、一致性,也就是要把团队的最佳实践固化下来
代码审查
定义
代码审查指的是代码作者以外的人员对代码进行检查,以寻找代码的缺陷及可以提高的地方。需要注意的是,按照定义,人工检查才是代码审查。机器进行的检查通常叫作代码检查或者代码自动检查
作用
1. 尽早发现Bug和设计中存在的问题
2. 提高个人工程能力
3.团队知识共享
4.针对某个特定方面提高质量
5.统一编码风格
分类
按照审查方式
工具辅助的线下异步审查
优点
审查者可以灵活控制审查时间,减少对自己工作的干扰
在工具中的讨论会留下文档,方便事后参考
缺点
实时性不好,以及对复杂问题的讨论效率较低
面对面审查
优点
快
可以高效地审查不方便用文字讨论的代码
缺点
大量使用的话会严重影响审查者的心流,给审查者带来较大干扰
按照审查人数
一对一审查
定义
审查者单独对代码进行审查
优点
安排起来比较方便,也更容易避免多人讨论时造成的效率低下
缺点
基于工具的一对一审查中,代码作者通常会把代码同时发给几个人审查,以避免出现由于单个审查者最近过于繁忙而耽误审查进度的情况。这就可能会出现几个审查者同时审查一段代码的现象,造成重复劳动
团队审查
定义
团队成员聚在一起进行代码讨论。这种方式适合专项讨论
优点
大家一起讨论可以检查出更多问题,质量更有保障
缺点
因为要开会,所以很容易出现会议效率不高的通病
按照审查范围
增量审查
优点
能把有限的时间花在最容易出问题的地方
全量审查
场景
专项检查
在刚开始引入代码审查时,对遗产代码进行一次审查
优点
关注整体质量
缺点
工作量大,不能常常进行
按照审查时机
代码入库前门禁审查
定义
把代码审查作为门禁的一部分,要求代码在入库前必须通过人工审查。这也是最常见的审查方式
优点
优势很明显,如果没有流于形式的话,可以在代码入库前的最后一步拦截问题,从而避免入库后昂贵的缺陷修复花销
缺点
由于太过死板而导致代码入库效率降低
代码设计时审查
定义
在设计阶段进行代码审查
强调
代码设计时审查的用处很大,但在实践中却常常因为大家对它不够了解而被忽略。
代码入库后审查
定义
审查已经入库的代码
优点
既不阻塞代码入库,又可以对提交的代码进行审查,只要入库代码没有马上上线,风险就很小
作用
入库后审查还有一个作用,可以提高遗产代码的质量
总结
如何有效引入、执行代码审查
步骤和方法
步骤一:达成代码审查应该计入工作量的共识
方法1:预估工作量的时候就会考虑代码审查的时间
方法2:代码审查的质量还会作为个人绩效考评的一个重要指标
步骤二:选择试点团队逐步落地
选择试点团队时,最好是找成员经验丰富、对技术有追求,同时当前所做业务又不是特别紧急的小团队。这些团队的成员有兴趣、有精力,也有能力去学习好的代码审查实践,容易出成果。
步骤三:选择工具和流程,把机器检查和人工审查高效结合使用
工具
GitLab、GitHub、Gerrit、Phabricator、Review Board
工作流
1)将代码提交到本地Git仓库
2)把提交发送给代码审查工具
3)代码审查工具开始进行机器检查和人工审查
4)如果审查没有通过,就打回重做:开发人员修改后重新提交审查,直到审查通过后代码入库
示例
1)使用GitLab、Jenkins和SonarQube进行配置。具体来说,使用GitLab管理代码,代码入库后通过钩子触发Jenkins,Jenkins从GitLab获取代码,运行构建,并通过Sonar分析结果。感兴趣的读者可参考《集成GitLab、Jenkins与Sonar实现自动代码检查》
2)使用Phabricator作为控制中心,结合原生的Git Server进行配置。具体来说,直接使用原生的Git Server作为代码仓服务器。用户将改动提交到Phabricator,进行人工审查,以及通过Phabricator提供的钩子和插件机制进行机器检查。审查通过之后,Phabricator负责将代码推送到Git Server上。关于Phabricator的配置,请参考其官方文档。另外,这里使用了原生Git Server来管理代码仓,我们也可以使用GitLab或者GitHub代替。
注意
1)代码审查者应该把最宝贵的时间投入到逻辑、设计等难以自动化的问题上,至于代码风格、静态检查、单元测试等工作,尽量让机器自动化完成
2)考虑让人工审查和机器检查同时进行。这个操作乍看起来似乎有违常理,因为如果首先进行机器检查,通过之后再进行人工审查的话,应该可以因为机器检查对提交的过滤而节省人工审查的时间。绝大部分公司也是这样做的。但事实上,人工审查和机器检查的关注点的重合率不高,所以两者同时进行的话,在加快反馈速度的同时,造成的浪费并不大
3)考虑让人工审查作为整体审查是否通过的唯一标准。也就是说,只要人工审查通过,代码作者或者审查者就可以立即将其入库,即使这个提交的机器检查没有通过,甚至机器检查还没有结束运行。这样做可以充分利用人的灵活性来处理各种特殊情况
步骤四:制定团队代码审查指南
1)代码审查过程中代码提交的大小。可以给出一个推荐行数限制。注意,要保持灵活性而不应该强制
2)代码审查反馈速度。比如规定三天内给出回复
3)审查中需要重点关注的对象。每个团队应该根据自身业务特点和所使用技术寻找最值得关注的点
关键操作
操作一:提高提交的原子性
操作二:提高提交说明的质量
关键原则
原则一:相互尊重
1)提高提交说明的质量。这是对审查者最基本的尊重
2)把提交大小控制在一个合适阅读的范围内,减少审查者的心智负担
3)尽量提早发出审查需求,不要求马上反馈,让审查者能够更好地安排时间,减少代码审查造成的干扰
原则二:基于讨论
在审查的过程中谨记代码审查的目的是讨论,而不是评判,管理者一定要在团队中强调这个原则
审查者切记不要说教。说教容易让人反感,不是讨论的好方式
审查者提意见即可,不一定要提供解决方案
想办法增加讨论的趣味性
合理处理技术债:让快速研发可持续
技术债成因
主动引入:即开发人员知道某一个实现会产生技术债,但仍采用这样的实现。最常见的情况是,由于业务压力,在时间和资源受限的情况下不得不牺牲质量
被动引入: 即不是开发人员主动引入的技术债
一是产品不断演化,技术不断发展,导致原先的设计、实现落伍
二是开发团队的能力和水平有限,没有采用好的开发方法、实践
技术债影响
1. 每一步累积的技术债都会叠加起来,为下一步开发增加越来越大的难度
2. 长期来看,如果一直借债不还,开发新功能的速度就会越来越慢,产品维护也会越来越难,最终甚至导致无法维护、必须推倒重来的结果
处理技术债的基本原则
原则一:要利用技术债的好处,必要时要大胆“举债前行”
原则二:要控制技术债,并在适当的时候偿还部分技术债
控制技术债的步骤
步骤一:让公司管理层意识到偿还技术债的重要性,从而愿意对其投入资源
解决技术债的第一步,就是让管理层意识到偿还技术债的重要性,从而愿意投入资源去解决。一个比较直观、有效地让管理层理解技术债的通用方法,就是使用上面提到的技术债与经济债务的类比去解释
步骤二:采用低成本的方式去预防技术债的产生
主动引入的技术债:要尽量让管理层和产品团队了解技术上的捷径将会带来的长期危害,从而在引入技术债时客观地对其短期收益和长期损害进行权衡,避免引入不必要的技术债。
被动引入的技术债:由产品演化导致设计落伍的问题不是很好预防,而由开发团队的能力问题引入的技术债,则可以使用加强计划和代码审查等方法实现低成本的预防。
加强计划:可以帮助开发人员更合理地安排工作,从而有相对充裕的时间去学习并选择更优秀的功能实现方案。
代码审查:它可以帮助我们在早期发现一些不必要引入的技术债,从而以更低的成本去解决它。
步骤三:识别技术债并找到可能的解决方案
复杂度相关技术债
解决复杂度问题的基本原则是,把一个系统拆解为多个子系统,用抽象和分层的方法,让我们的大脑只需同时面对有限的信息,并且能够有条理地深入每一个子系统中查看细节。具体的解决方法有:
对系统进行二进制组件或者代码层面的解耦
使用简单化的设计编码原则,避免不成熟的优化
对常见的“坏味道”做出一些规范,比如限制代码行的长度、禁止循环依赖、限制圈复杂度
对复杂的设计添加注释
重用性相关技术债
DRY就是解决重用性问题的基本原则
应用层面,复用业务单元,典型案例就是业务中台
架构层面,复用基础设施后台
组件层面,避免出现责任重叠的组件、数据存储等
代码层面,避免出现重复函数、代码块
步骤四:持续重构,有节奏地解决高优先级技术债
技术债任务处理方法1:把技术债的任务和业务相关的任务放到一起,在每一个迭代中持续完成。这种方式的好处是可以通过技术债和业务的联系,更清晰地显现出每一个技术债任务的价值。
技术债任务处理方法2:使用突击的处理方式,在某个特定的时间段集中解决技术债问题。
开源
开源过程的关键步骤
1)公司/员工对某项目有开源的意愿
2)管理者权衡利弊,决定是否开源,确定开源后的项目维护计划
3)进行法律和信息安全方面的审核
4)选择授权协议
开源软件授权协议(Open-source License)
开源软件授权协议用来规定使用者一方享有的权利和受到的限制。这是大家比较熟悉的一类协议,包括GPL、MIT、Apache
开源贡献协议
开源贡献协议,则是对软件贡献者一方进行权力和责任的限定。它赋予开发人员对开源项目贡献代码的权利,也授权项目管理者按照软件授权协议去发布软件
CLA(Contributor License Agreement,贡献者许可协议)
DCO(Developer Certificate of Origin,开发者原创证书)
5)选择版本控制代码服务商(比如,GitHub、GitLab、BitBucket、Gitee等)
6)代码模块化,与公司代码分离
7)正式开源,发布信息
7)正式开源,发布信息
挑战
软件开源之后,公司和开源社区目标不一致是非常普遍的现象。在我看来,这可以算是开源项目的最大挑战
解决方法
内部Fork,让开源社区继续自由发展:既然从开源社区资源得不偿失,就把代码挪回公司内部获取完全的管控和自由度
对开源代码仓实施强管控,但这样做的最终结果往往是开源社区Fork一个新项目另起炉灶,和第一种方法其实差不多
采用不同的分支来支持不同的目标。这样做的好处是公司依然可以获得开源社区的资源支持,但坏处是分支管理、版本管理很烦琐,也缺乏Fork的灵活性。
开源利弊
好处
1)提高代码质量。开源通常需要把代码进行模块化,这会大幅提升代码质量。同时,开源之后代码会对外部可见,激发开发人员提高代码质量
2)获取开源社区的免费帮助
3)提高程序员的积极性。开发人员通常都愿意在开源项目工作,因为它对个人成长和个人品牌都有好处
4)提高公司声望。开源可以扩大公司影响力,也可以增加公司对人才的吸引力
5)回报开源社区
缺点和挑战
1)定制有挑战。开源之后,公司失去了对代码的绝对掌控权,需要仔细设计,才能确保足够的灵活性继续支持公司的使用场景
2)内外协调有挑战。沟通本来就需要成本。开源之后,沟通成本更大,需要找到合适的方式,提高沟通效率,加强合作
3)开源社区和公司对项目发展目标不一致。这是开源最大的挑战,需要根据实际情况尽量寻找双赢的解决方案。
开源最适合的公司类型
大公司
需要通过开源获取影响力去扩展业务的公司
开源适合的项目类别
平台
基础设施
工具
业务层项目不适合开源,因为通用性不强
高效上云
云计算优势
定义
云计算把许多计算资源整合起来,利用软件实现自动化管理,通过网络为用户服务。其中的计算资源包括服务器、存储、数据库、网络、软件、分析服务等
优势
优势一:服务化
分类(抽象程度)
软件即服务(Softwareas a Service,SaaS)
平台即服务(Platform as a Service,PaaS)
基础设施即服务(Infrastructure as a Service,IaaS)
原则
第一个原则是,在业务开发中,尽量使用云计算栈中位置靠上的部分。也就是说,优先使用SaaS,PaaS次之,最后才是IaaS。
常见模式
一个常见的模式是,初创公司在业务刚起步时,使用SaaS或者PaaS快速开发业务;业务成长到一定规模之后,再逐步转到IaaS以及私有云,以降低成本。
优势二:自助化
开发环境的获取
CI/CD流程实现
优势三:弹性和共享
云计算挑战和解决方法
挑战
为了充分使用云的弹性伸缩能力,我们必须实现分布式的软件架构,以支持其水平扩展
解决方法
方法一:集中管理和团队自治相结合
加强集中管理的最重要手段是信息可视化
方法二:高效的错误处理
信息可视化。通过数据可视化、监控、预警,迅速发现错误以便及时处理
错误隔离。把错误控制在一定范围内。比如,微服务的一大好处就是可以把错误限制在单独的服务中
提高系统容错性。确保一个服务的问题不会影响其他服务,形成所谓的“雪崩效应”。具体办法包括限流、熔断机制等
自动修复。能够自动探测到问题并采取修复措施。其中最常见的一个办法是重启服务,对无状态服务非常有效
测试
测试左移
定义
在研发流程中,把测试的覆盖范围从传统的测试节点中释放出来,将其向左扩展,介入代码提测之前的部分。
原则
原则一:调整团队对测试的态度
原则二:把测试添加至开发步骤中
方法1:让测试人员参与开发阶段的方案设计
方法2: 开发人员全栈开发,这样更彻底,也更有效
原则三:把测试添加至产品需求步骤中
为促进需求评审过程中可以更好地做到对测试的考虑,推荐使用BDD(Behavior Driven Development,行为驱动开发)研发方法。BDD通过特定的框架,用自然语言或类自然语言,按照编写用户故事的方式,从用户的视角描述功能并编写测试用例,能够让业务人员、开发人员和测试人员始终关注业务的可测性
原则四:频繁测试、快速测试
方法
规范化、自动化本地检查
建设并自动化代码入库前的检查流程
提供快速反馈,促进增量开发
提升测试运行的速度
并行运行测试用例。比如把测试用例放到多台机器上运行,用资源换时间
提高构建速度。比如使用精准构建缩短构建时长,从而降低总体测试运行时间
精准测试。在代码改动时重点关注与之最相关的测试用例
分层测试。在不同流水线中运行不同测试用例集
减少不必要的用例。比如,识别不稳定的用例,定期对其删除或者优化
工具推荐
一个是Facebook使用并开源的Buck系统,可以用来提高构建速度
一个是Google开源的Bazel,支持精准构建和精准测试
测试右移与高效部署
定义
把测试的覆盖范围从传统的测试节点中释放出来,将其向右扩展,更多地融入代码部署、发布,甚至上线之后的步骤中
部署方式
方式一:蓝绿部署
采用两个分开的集群对软件版本进行升级。它的部署模型中包括一个蓝色集群和一个绿色集群,在没有新版本上线的情况下,两个集群中有一个对外提供服务。另外一个运行旧版本。
方式二:红黑部署
红黑部署与蓝绿部署非常相似,唯一区别在于红黑部署在部署过程中动态获取一个集群,并在部署结束后立即释放,从而充分利用云计算的弹性伸缩优势,避免蓝绿部署方式始终有一半机器闲置的情况,大大提高资源使用率。
方式三:灰度发布
灰度发布就是把部署好的服务分批次、逐步暴露给越来越多的用户,直到最终完全上线。
目标
减少发布过程中新旧服务切换造成的服务中断时间——蓝绿部署和红黑部署都能实现无宕机部署(Zero Downtime Deployment)
实践方法1:利用负载均衡切换线上流量
实践方法2:使用功能开关切换线上流量
控制新版本上线时带来的质量风险——灰度发布就是一个典型例子
实践方法1:部署阶段的实践
第一种检验方法:集成测试
第二种检验方法:流量镜像测试
第三种检验方法:压测
第四种检验方法:配置方面的测试
实践方法2:发布阶段的实践
第一种检验方法:灰度发布
技巧1:让灰度发布的服务先面向内部用户,也就是通过Dogfooding,来降低出现问题时造成的损失;
技巧2:使用现有的一些部署工具和平台发布,比如Spinnaker已经对灰度发布有了比较好的支持,可以考虑直接使用,从而降低引入成本。
第二种检验方法:监控
监控是安全发布必不可少的关键环节。在发布过程中,应该注意监测用户请求失败率、用户请求处理时长和异常出现数量这几个信息,以保证快速发现问题并及时回滚。
实践方法3:发布后阶段的实践
第一种检验方法:监控
第二种检验方法:A/B测试
第三种检验方法:混沌工程
原则
部署
部署(deploy),指的是我们把可执行软件包复制到生产环境的服务器上运行,但暂时还不使用它为用户提供服务。这个阶段比较耗时,不过因为还没有面向用户,所以风险很小。
发布
发布(release),指的是把部署好的新版本暴露给用户的过程。这个过程可以通过负载均衡的切换快速实现,但因为新版本开始正式上线,所以风险很大,一旦出现问题就会造成较大损失。
发布后
发布后(post-release),指的是服务完全上线以后的阶段。因为此时产品已经完全上线,我们的主要工作不再是预防,而是监控和降低损失。
持续进步:研发流程&工程方法
协作方式的发展趋势
团队远程办公、灵活工时办公会越来越普遍
远程办公的第一个好处,即克服人才的地域局限性,就凸显了出来
远程办公的另一个好处是,大量减少通勤时间,进而提高研发产出
灵活工时办公,本质是任务驱动
远程办公技巧
尽量使用视频会议而不是电话会议。有研究表明,由于缺少了由面部表情和肢体语言传递的信息,电话会议的效率会比面对面沟通的效率低很多。
做好信息的数字化。建设好任务系统、文档系统等,让研发人员在工作中能自助式地从这些系统中获取信息,减少对面对面沟通或者实时聊天系统的依赖
聊天工具和其他工具的集成会越来越深入和多样化
云平台的发展趋势
云计算最大的发展趋势应该是Docker和Kubernetes带来的各种可能性
Kubernetes的最大作用在于可以用它高效建设PaaS
PaaS平台有一个缺陷,它容易出现灵活性不足的问题
解决PaaS灵活性不足的一个方法是灵活生成新的支持定制化需求的PaaS平台
趋势
如果研发团队较小,会选择使用第三方服务商通过Kubernetes提供的PaaS平台
如果研发团队较大,很可能会基于Kubernetes建设适合自己的PaaS平台
CaaS
CaaS(Container as a Service,容器即服务)是一种允许用户通过基于容器的虚拟化来管理和部署容器、应用程序、集群的云平台,属于IaaS平台的范畴
应用开发的趋势
云原生开发方式
应用程序运行在云端,需要基于云的架构设计,这就意味着我们需要一套全新的理念去承载这种开发模式。这套理念,就是云原生开发(Cloud Native)。由Heroku创始人Adam Wiggins提出并开源、由众多经验丰富的开发人员共同完善的12原则,是云原生开发理念的理想实践标准
服务网格
复杂的服务拓扑结构,是云原生应用的一个重要难点。而服务网格是解决这个难点的一个有效手段
服务网格是用来处理服务间通信的专用基础设施,它提供了应用间的流量、安全性管理,以及可观察性等功能
服务网格比较流行的开源软件
Linkerd
Istio
AI方面发展趋势
AIOps
1.检测并诊断异常。通过对历史故障数据进行分析学习,找到规律,从而在新故障出现或者即将出现时,及时发现,并给出一些可能的诊断
2.智能弹性扩容、缩容及流量切换
还可以利用AI做更智能的流量切换,更进一步提高资源利用率。
CD4ML(Continuous Delivery for Machine Learning,机器学习的持续交付)
机器学习中有很多需要人工参与的步骤,我们可以通过提高这些步骤的自动化程度来提高其效率。CD4ML将持续交付实践应用于机器学习模型的开发,以便随时把模型应用到生产环境中去。
语音输入
管理和文化
打造高效团队
寻找目标
业务目标(80%)
1. 弄清楚公司和上级对团队的预期,并达到这个预期,是团队的基础目标;
2. 在基础目标之上,还要给团队设定一个进取目标。我们需要分析公司的发展方向,以及团队的实际情况,找到那些既符合公司利益,又能通过额外努力实现的目标。
技术目标(20%)
1. 偿还技术债。
2. 前瞻性技术目标。作为技术管理者,我们要有灵敏的技术嗅觉,对即将出现的技术挑战,做一些预防和准备。
目标管理
SMART
作用:SMART是一个有效设定目标的原则
定义: Specific(具体)、Measurable(可衡量)、Attainable(可达成)、Relevant(与主目标相关)、Time-bound(有明确的截止期限)
举例:一个目标可能被定义为今年下半年实现用户讨论功能,但很明显这个定义不够清晰。而另外一种定义方法是今年12月31日之前,实现用户讨论功能模块,在主页以及至少一个其他页面使用,并且用户使用率大于10%。
总结:SMART目标更明确、具体,更利于团队完成好的业绩,也为管理者实施绩效考核提供了更好的标准。
OKR
作用:OKR是一个很好用的目标管理工具
定义:OKR中的O表示目标(Objective),该目标需要能够鼓舞人心,使每个成员达成一致并受到启发; 而KR则表示关键结果(Key Result),是达成目标需要注意的度量。
领导和管理本质区别
领导者告诉团队需要去哪里
管理者告诉团队如何去那里
关键点
1.牢记OKR最重要的目的是让全公司对齐目标。这是执行OKR最关键的原则
2. OKR不是一个HR工具,也不是绩效管理方法。 绩效管理方法通常包括目标、度量和考核(激励/惩罚)。 OKR只包括目标和度量,没有考核,是一个目标导向工具。
OKR之所以在目标对齐上非常有效,在很大程度上得益于团队成员可以自己制定与公司目标一致的关键结果,从而发挥主观能动性,真正体现OKR的指导作用。 如果OKR跟绩效挂钩,团队成员承担风险的意愿和内驱力就会大大减弱,倾向于制定更容易实现的KR,于是失去了OKR的目标导向的意义。所以,OKR不应该跟绩效挂钩。
那么使用OKR之后怎样进行绩效考评呢? 答案很简单,只要评估团队成员具体完成的工作对公司的贡献度即可。甚至可以继续使用KPI,让它与OKR并存。比如,公司高层可以使用KPI,利用数字衡量绩效,而整个公司则同时使用OKR帮助进行目标对齐。
任务执行
人:调动主观能动性
基本原则是把团队成员的利益统一起来,从而激发大家的主观能动性,自己想办法去达成目标。
统一团队利益的主要方法是采用康威定律来组织团队结构,让它与产品结构相吻合,使产品的成功成为团队成员一致的努力方向。
流程:选择恰当的方法论、原则、实践
工具:根据实践进行选择
原则1:选择工具时要根据场景的复杂程度选择自建或者第三方服务/工具。 对简单、单一场景,推荐使用开源工具; 而对复杂的系统和流程,则可以考虑使用付费工具,这样通常比自建工具的性价比高。 作为技术管理者,我们要时刻考虑投入产出比。
原则2:工具虽然重要,但背后的方法论和原则更重要
从奈飞谈硅谷公司文化
定义
文化是决定一群人行为方式的共同认知、价值观和信念。
推行文化步骤
1. 定义核心价值观;
从公司文化的维度提高研发效能,首先需要定义公司所需要的文化。由于文化比较抽象,所以常见的定义文化的方式是定义核心价值观。价值观是团队成员做事的思考依据,是文化的具体体现
价值观可以帮助公司实现的目标
产品上线速度
产品有效性
客户满意度
员工满意度
2. 在招聘、流程方面设计方案推动文化建设;
奈飞公司文化(辩证看待)
引入人才控制混乱
奈飞公司认为: 在公司规模变大时,不应该引入规则,而是应该引入更多人才来控制混乱。 只要招收到优秀的、负责任的人,并给予他们自由发挥的空间,他们就能够灵活高效地解决公司在成长过程中遇到的各种复杂问题。因此,只要引入人才的速度超过复杂度的增长速度,就可以让公司在成长的同时,持续保持高效能和创新能力。这就是奈飞的基本思路。
HR方面,他们高薪招聘人才、奖励优秀员工;同时对不合适公司发展的员工则容忍度很低。 基本思路是:一个员工如果称职,就用高于市场平均水平的薪酬去招聘或留住他;否则,就尽快解聘。
取消每年定时的绩效考评,也没有年终奖。仅在平时实时考评,绩效考评结果只有合格与不合格两种。评判依据是员工能否胜任当前工作,并不太考虑过往表现。对于绩效考评不合格的员工,没有其他大公司常用的PIP计划(绩效提高计划),而是直接用丰厚的遣散费解雇;而对于绩效考评合格的员工,也不是按照每年以一定的百分比提升工资,而是根据市场价进行调节。也就是说,在绩效考评合格的前提下,不管你的表现怎样,你的薪资都会根据市场平均水平来调高或者降低,但肯定会高于市场平均水平以保证你愿意留下来。
措施能够确保员工始终有能力应对当前的挑战,并且是负责任的“成熟”人才(所谓成熟,是指这些人才理性、有主观能动性)
高薪可以招聘到胜任当前工作的人才
如果个人能力发展跟不上公司的发展,就淘汰
因为成熟人才理性,所以他们能够接受这些非常规但特别客观的评定标准,愿意留下来。
建立基于信任的管理机制
这种松散的、基于信任的管理可以充分利用人的灵活性来解决复杂度,可以在公司运行的方方面面对研发效能提供帮助
奈飞文化思考
优劣
奈飞采用了很多非常规的,甚至极端的方式去推行文化,所以这些年来确实做到了持续的高效能和创造性,业绩也非常亮眼
极端政策在给奈飞带来成功的同时,也产生了相当的负面作用。因为公司对低绩效员工的容忍度非常低,解雇人员的频率比较高,所以有些人认为奈飞内部存在一种“恐惧”文化,他们时常处于害怕的状态,担心自己会不会突然被解雇。
对奈飞的文化有两点不太认同
第一,他们超级强调透明,认为一个成熟的人可以接受任何客观的评价
第二,太强调当前表现而不考虑过往贡献。这一定会降低员工的归属感,进而降低工作积极性
3.持续推动文化建设
管理者以身作则
明确提出价值观
注意文化的演进
工程师文化(FaceBook)
定义
工程师文化的本意是工程师这个群体的行为方式的共同认知、价值观和信念。本来工程师团队的做事方式可能千差万别,有好有坏,但后来“工程师文化”逐渐演化成正面的工程师的做事方法。也就是用正确的工程方法、思路来完成工作的文化。
Facebook的工程师文化可以用一句话总结:黑客之道。这里的黑客并不是贬义词。事实上,黑客在程序员界本是一个褒义词,指的是动手能力极强的程序员,他们创造、实验、打破常规,可以让计算机做任何他想做的事,即使计算机本身不同意。
黑客特质
优化无止境:黑客认为优化无止境,产品无完美。在大部分人认为服务已经无法改善,或者满足现状的时候,会直接上手做进一步的优化。
持续进步:黑客不追求一蹴而就,一劳永逸。他们更喜欢快速发布小规模更新,并从中吸取经验教训,通过长久努力不断进步。
代码为王:黑客更在意代码实现。代码胜于雄辩,只有真正实现了的东西才有价值。
能力为王:黑客有极度开放和精英为王的心态,不会因为谁的头衔高就默认其权威。相比之下,黑客更看重的是技术,以及把想法变为产品的能力,说白了就是谁行谁上。
核心价值观
专注于影响力(Focus on Impact)
迅速行动(Move Fast)
勇往直前(Be Bold)
保持开放(Be Open)
创造社会价值(Build Social Value)
具体实践
重视工程师文化的宣传
从流程、工具方面进行推动
工程师文化落地
目的
推行工程师文化的目的是提高开发人员的积极性和创造性,从而更高效地进行软件生产,在竞争中取得优势。
认知
要最大化地激发开发人员的自我驱动能力,根本出发点是理解开发人员这个群体的特性:每一名开发者首先都是知识工作者
管理学大师彼得·德鲁克在《卓有成效的管理者》中说:“我们无法对知识工作者进行严密和细致的督导,我们只能协助他们。知识工作者本人必须自己管理自己,自觉地完成任务,自觉地做出贡献,自觉地追求工作效益。”从这个角度来看,每一个知识工作者,都是管理者
原则
让员工做感兴趣的事
这里的感兴趣,不只是狭义地觉得任务有意思,而是开发人员对工作的整体状况感兴趣,包括项目前景、技术栈、挑战性、团队成员等。有研究证明,如果任务有意思、有挑战性,又是加以努力就能完成的,那么员工的参与度和满意度就会非常高。
让员工做感兴趣的事,主要在于可以让员工尽量灵活地选择岗位和转岗。但这是一把双刃剑。它很可能会在短期内给公司和团队带来负面影响。尤其是团队较小的话,每个人都很关键,自由选岗、转岗更难实现。
实践场景
入职
日常工作
转岗
实践方法
Bootcamp
Hackathon
Hackamonth
让员工拥有信息和权限
让员工拥有信息
实践一:代码共享
实践二:看板
实践三:使用Wiki来记录信息
让员工拥有权限
实践一:对于商业软件,先购买再获取授权
实践二:鼓励互相贡献代码
建议1:先从风险小的项目试点,鼓励互相贡献代码;
建议2:这种代码贡献虽然并非本职工作,但也要根据它对公司的贡献大小,在绩效考评中加分。
实践三:提供宽松的容错环境
落地经验
实践一:使用Q&A会议促进信息上下流通
实践二:使用Wiki推动信息共享
绩效调节
员工调节方向方法
1. 持续反馈。主管要随时给员工反馈,帮助其调节工作的方向和方式。
2. 360度绩效考评系统。每年进行两次总结性绩效考评。
360度绩效考评
认知
Facebook的360度绩效考评系统的核心,是通过收集同事之间的反馈来评价员工对公司的贡献。整个过程尽量关注公司的整体利益而不是小团队的局部利益,尽量收集客观的具体实例来评估贡献而不是简单依赖于客观数字。整体来讲,这个方法可以比较客观、公正地评价员工对公司的全局贡献。
关键问题
1.由谁给你写评价
被考评对象自选1~2个同事写评价; 主管指派1~2个同事写评价; 被考评人员自评; 主管的评价; 如果被考评者是管理者,他的所有直接下级都要给他写评价
2.评价内容是什么
1. 这个同事在上一个绩效考评周期中,对公司最大的1~2个贡献是什么?请用事例说明。
2.这个同事在上一个绩效考评周期中,在什么方面采取不同的做事方式,可以对公司有更大的贡献?
3. 如何定结果
评定结果的方式,是汇总对被评估对象的所有评价,并以此为依据,由他的主管和同级的其他主管一起讨论决定。讨论的基本依据是员工对公司的整体贡献
4. 如何应用结果
绩效考评结果应用包括是否涨级、工资底薪是否要调节,以及年终奖金额
两个原则
原则一:绩效考评中重点关注贡献度
1. 问题描述强调以贡献度为根本衡量标准。注意这里并没有提到这个人的技术水平怎样、开发效率怎样。因为技术和效率都是为贡献度服务的,一个员工即使技术再厉害,但如果对公司的贡献不够的话,绩效也不会好
2.衡量贡献的维度,是对公司的贡献,而不是对团队的贡献。因为,对团队的贡献最终也要以对公司的贡献来衡量。这种衡量方式让员工更关注公司的整体利益,从而避免出现团队的局部利益和公司的整体利益不一致的现象。
原则二:提高绩效考评的客观性和公正性
1.每一条评价都一定要有事例支持,有数字的话更好。
2.员工给其他同事做评价的质量,也是他自己绩效考评的重要组成部分。这样可以保证每个人都会尽量做客观的评价。以我为例,在第一次给同事写评价时,写得比较简短、空洞,结果被主管两次打回重写。后来,我每次写绩效考评时都特别认真。
3.意见的收集,覆盖的人群要全面,包括同事、自评、上下级。在给自己选择评价人时,要选择对自己的工作比较了解,可以做出客观评价的同事。不能随便选择和自己关系好的同事。
4.最终决定绩效结果的讨论中,虽然主管的评价比重较大,但其他同事提供的评价占比也很可观。同时,同事的评价是参会者可见的。这样可以尽量避免出现主管一言堂的情况。
问题
1. 360度绩效考评系统依赖于人的主观反馈,所以容易出现评价不客观的情况
最有效的解决方案是主管有意识地进行控制。如果发现有不客观的评价,就对评价者的绩效减分。
2. 360度绩效考评系统的另外一个问题,是耗时较长
解决方案是使用第三方提供的专业工具,会有一些效果。不过,考虑到客观地评价给公司带来的好处,多花一些时间是值得的。
落地实践
步骤
1.制定职级系统,详细描述每一个级别的技术预期和贡献度预期;
2.对公司的现有员工进行级别评定;
3. 对整个360度考评系统,进行文档化、正式化,并在公司内宣讲;
4. 正式使用这个制度,进行绩效考评。
注意
1. 宣讲时,要强调对公司贡献度的客观评价,是采用这种评定方式的根本原因;
2. 执行时,关注上文中提到的为保证客观公正性的四个关键点;
3. 确保反馈的保密性,为保证大家愿意写出一些真实想法,不能让员工知道对方对自己的评价。