整个课程会带大家先从理论出发,思考为什么有流程
大家以后工作的团队可能不一样,那么不同的团队也会有不同的流程,这背后的逻辑是什么
然后会带大家按照走一遍从需求到上线的全流程,告诉大家在流程的每个阶段,究竟要做什么
最后会给大家介绍一下我们实践当中怎样让流程更加有效率,让程序员的生活更美好,而不是把人变成拧螺丝的机器
当我们要开发的产品复杂了之后,究竟会遇到哪些问题?
按照阶段来看: 比如我们的想法可能不同,每个人都有自己的想法 甚至有一些还是馊主意,怎么去把这些各种各样的意见统一,这样团队就需要一个决策的过程
多人或者多端配合开发的时候,每个人都有自己的安排,你的代码跟我的代码怎么合到一起,什么时候一起联调?都需要有流程
再到后面开发出的产物交付测试,遇到了BUG怎么修,怎么让测试的功能之间不相互影响
最终好不容易我们的产品要上线了,上线要通过哪些方式,上线之后的运维又要做哪些事情 这些都需要有一个规范和流程
按照我们最传统的也是最直觉的模型
把整个软件开发按照各个阶段排成一条线 前一个阶段完成之后进行下一个阶段
后来互联网公司的流程逐渐倾向于敏捷
其实这里的敏捷指的更多的是一种思想
追根溯源的话 2001年的时候,有一帮程序员,在美国犹他州的一个滑雪圣地举行的一次聚会,在聚会上他们定了这个宣言 就是因为当时的软件开发流程太过于重视流程本身,没法快速灵活的适应市场变化
在实践当中,现在敏捷已经发展出了一套规模化的管理的框架
也就说所谓的SAFe 这套框架是为企业中实施敏捷开发提供一套方法论
如果说敏捷开发是一个团队内部的协作方式,那么SAFe就是在企业中,多个敏捷团队之间怎样配合
如果大家到了目前一些比较大的厂工作,应该实际接触的就是这套模型
比较理论的东西我们不去深入讨论:比如精益产品开发,敏捷软件开发,系统思考等等,这里专门开一门课都未必能讲完
如果一个scrum就是一个战术小队
敏捷教练就好比是小队的队长,产品负责人是负责联络指挥部和发布任务的人,
其他团队成员就是特种兵 大家也不是按照一个方阵去前进,而是用更敏捷的方式去前进,也就说敏捷发布火车
我们每个迭代有两周,同时我们有两个scrum,
因此站会是两个scrum交替进行 带大家过一下整个流程
从时间表上可以看到,我们会在迭代的第二周周二开grooming会议,周五开planning会议 至于评审和反思会议,一般要是需要的时候才会开。
回到我们开头的例子,如果要开发一个类似抖音一样的复杂产品,那么需要的不是一个程序员,而是像这个的几十上百个这样的团队,通力合作 背后也不仅仅是程序员,还有各种各样的团队成员共同努力,才能最终把我们的想法变成实际的产品
说到需求阶段,马斯克在接受一个采访的时候讲过一个故事
他们在做特斯拉生产线的自动化的时候,有一个零件的安装自动化总是出问题
特斯拉的工程师为了优化这个自动化流程,投入了大量的资金和精力
后来马斯克问他们的技术人员,为什么需要这个零件,
结果发现大家居然并不清楚 最后证明其实在电动车上,根本不需要这个零件
所以围绕着这个不应该存在的问题,进行了大量投入,造成了很多浪费
所以,这个故事就告诉我们一个道理,不要浪费时间讨论不应该存在的问题
还记得我们刚才提到grooming会议,就是在那个会议上,大家会讨论什么需求该做,什么不该做
这个会议 现在我们的几个产品经理现在都不用我们动手,轮到自己的时候自己先砍几刀,说:这几个可以不做,但是其他的必须做
不过大家也都不跟他们客气,该砍的还是砍
不过玩笑归玩笑,我们作为后端开发,除了砍需求,还要学会站在用户的角度评估需求
需求究竟应该怎么评估 这里教大家一个MVP的思维方式
如果我们要给用户造一辆车,我们不应该第一天给他一个轮子,第二天给两个轮子,第三天给他一个底盘,第四天才让他开上车
我们应该先给用户一个简单能用的产品,比如一个滑板车,一个自行车,根据用户的反馈我们再逐步把车的功能升级,最终变成用户想要的产品
另外一个评估需求的方法,也是我们日常工作中安排自己任务的一个方法,就是四象限法:
当你很多任务的时候,可以按照这个坐标,把他们按照重要性和紧急程度分类
有些事情既重要又紧急,那么我们就应该先去做,不重要又不紧急的可以最后做
而有些事情虽然重要但是不紧急他们的优先级应该比那些紧急但是不重要的事情高,因为如果我们不去处理,后面他们就会变得又重要又紧急
这个理论的原则是先判断事情的重要性,再判断紧急程度
一个高效的占比,应该是大多数时间在处理重要但不紧急的事情,因为一旦一件事情变成了紧急,那我们就容易犯错误,因此如果每天大部分时间都在处理重要且紧急的事情,那么其实是不健康的
首先大家正在一个时代的变革中,因为云原生的发展,现在的后端开发工作跟几年前已经有了很大的区别
什么是云原生? 作为后端开发同学,大家应该把Kubernetes和容器技术作为一个基础知识,
如果过去在虚拟主机的开发是用剑决斗 那在云原生技术爆发的当下,就是能在决斗中用枪了
所以就像这张图一样,“大人,时代变了”
当然我们这门课不会太着重去介绍云原生和相关的技术细节,后续会有专门介绍服务架构和微服务的课程
我们这里重点介绍一下这种变化对我们日常的开发会产生什么影响
云原生下的开发,一个最大的区别就是部署的形式不同
传统虚拟机上的服务开发,是在物理机或者是更底层上虚拟出多个虚拟主机,
然后在每个虚拟主机中安装软件和依赖
虚拟机需要有专门的运维人员维护 本地开发的时候也大多是直接在电脑上运行程序
而开发云原生的后端程序,容器是从操作系统中虚拟出来的,所有容器共享宿主机的系统,
通过cgroup,namespace和union mount实现了容器之间的隔离
因此在部署的时候,应用和其依赖的系统是整体打包成一个镜像的
后端开发不再依赖运维人员创建程序的运行时环境
云原生带来的另外一个改变就是微服务
在之前的几年,web应用的主要架构师SOA架构,在一个服务中多个不同的模块构成了一个部署单元,各个模块作为一个整体部署和伸缩 这种架构下往往服务会形成一个很大的代码仓库,大家共同维护一个大型的系统
好处是模块之间的调用不需要通过RPC网络,
但是坏处就是加减机器的时候不能安模块处理 开发的工作也需要多人共同进行充分的集成测试,保证不会把别人的东西改坏
而微服务架构是把模块拆到不同的服务中去,拆分的粒度更细,可以让每个模块独立的更精确的扩容/缩容
同时可以让少数几个人维护一个仓库,更适合敏捷的开发流程
缺点是 不同服务之间要进行RPC通信,网络开销变大;
另外多提一嘴,Martin Fowler的这篇文章是比较著名的一篇介绍微服务的文章,他也是之前我们敏捷宣言的发起人之一,感兴趣的同学可以多去了解一下这个人的文章
云原生让我们的开发环境也逐渐云化
新人入职往往前面几天导师安排的工作就是搭建开发环境 一旦开发环境出了问题,排查和解决起来都非常痛苦 而云原生的IDE就可以很好的解决这个问题
借助容器技术,可以轻松创建一个模拟线上的开发环境
比如你不要再纠结本地多个java的版本,go和python的还有依赖的库也可以随意切换
讲完了云原生,接下来影响我们开发的最大因素就是团队的分支策略
不同的分支策略往往影响团队的开发流程
这里假设大家没有深入使用过git,简单介绍一下,
我们日常工作中写代码都是基于主干的某个版本进行修改,改完之后再把代码合并回主干形成新的版本
这里就会有一些协作上的问题: 多个团队成员各自用什么分支?修改有冲突怎么解决?出了问题代码如何回退?
为了应对这些问题: 有些团队会有一个专门的分支叫做release分支,大家都把代码合并到release分支,然后测试,发布,之后再把release分支合会master
有些团队会直接把开发的分支合入master,然后再用某个master上的commit发布
之所以有各种各样的分支策略,就是因为我们在后续的测试和发布阶段要按照对应的分支和commit进行交付
大家在实际工作中,一个项目的分支会变得非常复杂,
因此在团队中一定要统一分支的规则 什么分支是做什么的,每个人都要清楚 并且对于git的知识也是需要重点掌握的
一个有经验的开发和新人写的代码,往往最大的差别不是功能的实现,而是在于代码的风格和规范
比如有一些原则可以很容易遵循:
良好的注释习惯,有复杂的地方时间长了自己都会忘
不要有魔法数字和魔法字符串,比如在判断条件里判断某个变量等于2,2代表什么?可以用常量来定义
重复的逻辑可以抽象成公共的方法,不要到处copy代码,不然每次修改都要改很多地方
正确使用IDE的功能进行重构,不要手动去编辑或者全局替换
另外在开发阶段还要进行自测和文档编写,
在开发过程中,随时进行一些静态代码扫描,也能显著提高代码质量
遵守开发的规范就像大家随手捡起手边的垃圾,是一个对团队有益的好习惯
到了测试阶段,这里向大家推荐一本书《google软件测试之道》
测试应该是伴随着开发的全部过程的,每写一段代码之后就要想办法测试这段代码
有的人可能以为测试人员 负责保证代码的质量,但是这是一个很常见的误区
质量不是测出来的 BUG也不是因为没有测试 产生的(Bug是自己写的),希望大家在以后的工作中,能够为自己的代码负责
左边这个图是传统的测试金字塔模型,他的意思是:
越底层的测试粒度越细,就需要越多的数量去覆盖所有场景,越顶层的测试越能用少量的case覆盖大多数场景 但是有一个软件开发中的常识:越早发现的缺陷解决成本越低 因为85%的缺陷是在开发阶段引入的,而如果要在上线之后修复他们,花费的成本可能是一开始就解决他们的数百倍 所以我们还是要尽可能早的发现bug,进行充分的单元测试
我们日常开发的应用,可以简化成图中的模型
由客户端发送请求到网关,网关请求到后端服务器
比如我们抖音的测试同学,可能每人手里会有好几个手机,分别用来测试不同的功能 对于后端的服务,也可能有不同的版本,因此在测试中会有一个虚拟的环境概念
我们用特定的设备可以通过某些设置,让他请求到对应的后端服务器,从而达到测试对应的后端服务的目的
这样一个从客户端到服务端的一整套体系,称为一个环境
在实际的工作中,我们一般至少需要三套环境:
功能环境是用于 开发和测试新开发的功能的
集成环境是为了 把不同的功能合并在一起测试
回归环境是为了 验证新的功能对老功能没有影响
具体要根据你开发的应用采用的架构,这里只是一个最简化的模型
所以飞行员起飞前的检查项,很多是有血淋淋的教训的
在互联网公司, 我们会制定很多的发布规范,这些规范的背后,往往也会有一些严重的线上事故
这里推荐大家看一部纪录片《空中浩劫》 里面从一片空难飞机残骸中调查原因的过程,就很像我们平时分析线上事故的过程
举个简单的例子,假如发布过程中页面突然打不开了 我们可以使用chrome的开发者者工具,
发现有一个接口连接失败 这个过程就很像我们通过黑匣子寻找事故的原因
一个请求就像一个链条,我们可以顺着链条一节一节的去推理和定位问题
实际上在发布过程中,除了出问题要快速定位,根据角色的不同,还需要做一些常规的检查
比如: 发布负责人要负责通知各个相关人员,观察各个服务的发布状态
变更服务的相关RD要按照规范检查日志,监控,响应线上的告警
值班同学要关注用户的反馈等等 就像起飞前飞行员要进行的检查一样,每完成一项就打一个勾
先发一台机器 没问题 再全面发布
其实发布的模式还不止这几种 实际工作中,
我们的发布使用的是滚动发布,发布的负责人需要关注滚动的粒度和时间,以及具体执行的进度
因为这种方式对用户的体验最平滑,同时公司也有强大的流量控制能力,能够平滑的切换流量能够支持滚动
但是仍然有一些场景需要使用蓝绿发布
可能有些公司因为发布需要在用户低峰期进行,所以在那些公司发布的时候,往往都是在夜深人静的时候,这也就是程序员经常要晚上加班的很大一个原因
当故障发生之后,我们是有几个关键的动作的:
首先是止损,尽快去让服务恢复功能
其次是要让服务的上下游感知到出了问题 当上面两个动作做了之后大家才需要去定位和修复问题
所以大家不要反过来,线上页面都打不开了,第一时间打开IDE开始看代码 这个其实是有问题的
经过需求阶段我们讨论该做什么不该做什么
开发阶段我们按照规范去实现产品
测试阶段我们去验证产品,修改缺陷
发布阶段我们按照流程规范上线
运维阶段我们观察线上监控和日志
一个完整的软件开发周期就走完了
互动思考题: 如果每个过程都要一步步去执行,生活会美好吗?如何优化这个流程?
在之前的流程里面有很多的繁琐的规范和操作;这些操作无疑能让我们的服务质量提升
但是另一方面,又会导致我们工作的效率下降 所以往往大家会在质量和效率之间区一个平衡
技术的发展,让质量和效率同时得到了提高
把规范融入流程,把流程自动化 从需求到上线全流程自动化,我们就同时提高了质量和效率
DevOps理念 所谓DevOps,就是由左侧的Dev 和 右侧的 Ops组成
从需求plan开始,写代码code,编译build,测试test,发布release,运维deploy,监控Operate 形成了一个闭环;
于是我们可以进行持续集成,持续交付
也就说CI持续集成和CD持续交付 ; 大家谈CI/CD的时候其实往往独立去谈,其实整个流程是密不可分的
在DevOps的基础之上,我们还可以怎样优化?
这里就引出了一个效率竖井的概念
可以看到,从需求到交付的过程中 我们真正产生价值的开发,测试 等等动作占比是很低的
大量的时间可能是在等待和传递 比如测试一直在等开发把环境部署好 另外人和人之间的沟通,也很慢
因此我们更近一步,把价值流,作为全流程的指标
这边举一个例子 工厂接用户的订单生产 中间可能会有A B C三个步骤
我们可以分析每个步骤所耗费的时间以及他所产生的价值 去优化团队的研发流程
这个也是我们团队现在在做的一个事情
还记得我们团队的流程吗?
每天都要开站会,每天都要写代码,每天都要修bug 除了这些日常的工作,其实每天都会有一些重要的事项
比如周一, 一般大家周一都会有一些周一综合症 大家可以处理一下上周遗留的事项
这天的主要内容可能主要在PM和UED那里,因为他们要准备第二天要讨论的需求列表
周二
一般迭代开始的周二,最重要的事情就是需求规划会议,也叫grooming会议
这个会议上打开需求管理平台的页面,发现累计了92个需求
在会议上PO和PM阐述各个需求的价值
Scrum Master和架构师会确认需求中包含的技术任务
最终,会议确定下个迭代要做70个需求,并给你安排了10个需求
到了周三 这一天还是要为第二天的发布做准备,
比如测试和修复缺陷 之前开发的需求要提交敏捷发布火车的车票准备上车
对其他人的代码做一下code review 测试还可能在回归测试的时候发现了一些缺陷需要你修复
周四一般会有一次日常的发布,之前在前一家公司的时候,每次发布都会在群里发一张关公,保佑发布顺利
这张图片就是当时发的关公原图 如果很不巧,发布过程中监控出现了异常,马上终止发布止损,
然后再定位问题 发现是自己代码有问题,就需要回滚代码或者修复
周五 我们一般都会用于对下个迭代的需求进行评估 还记得周二分配给你的10个需求?
结果由于工作量,只能完成其中8个 经过讨论,我们按照优先级,把2个需求移出迭代 然后把这8个需求按照开发和上线的时间进行排期
可以看到,作为一个后端开发,其实真的需要像一个全能战士一样 既要讨论需求,又要测试,还要负责发布
总结一下我们的课程 这个过程也是一个逐渐成长的过程
一开始进入一家公司,我们肯定要学习公司的流程,团队成员分工,开发的节奏这些 背后其实是有理论依据的,就我们现代软件开发的几种模型
然后当我们真正成为了一个后端开发的角色,在需求到上线的各个阶段,我们需要去执行 需求评估,开发,测试,发布,运维
更进一步,当我们越来越有经验,甚至以后可能有些会承担团队的管理,那么就需要去思考怎样去优化这个流程,让大家的生活越来越美好