e-works数字化企业网  »  文章频道  »  基础信息化  »  运维管理

DevOps实施落地的2大法宝:粒度&解耦

2017/10/9    来源:运维派    作者:佚名      
关键字:DevOps  软件开发  
一句话概括我所做的事情就是:帮助研发团队改进研发流程,包括使用工具、使用方法、借鉴他人经验等方式,让大家的软件开发效率变得更高。

    经常有人问我:我的团队适不适合做DevOps?我的产品适不适合做DevOps?这就是个伪命题,这个问题在于你怎么看待你所管理的过程,如果愿意并能够把管理的过程简单化,就肯定可以做DevOps,且做DevOps的过程就是在不断简单化管理过程的过程。
 
    软件研发管理过程全景
 
 传统开发 VS 敏捷开发
 
    到底软件研发管理过程是什么样的?如图所示,我们要管理的就是图上的点和线。图上最下面比较粗的线上列出来的简写其实就是CMMI定义的管理过程。
 
    用CMMI模型可视化地展示一个软件研发的管理过程,从最左边的需求提起,可以看到包括两大部分的内容:
 
    技术架构——从技术的角度怎样来描述产品长成什么样子,这里看到的就是一个大的产品,下面分成很多子系统,每个子系统里包含很多模块,这就是所能看到的软件的技术架构。
 
    条目化需求,条目化需求就是用户提出的一个一个的他希望软件帮助他做到的不同的场景。
 
    往右一点是设计过程,软件的架构设计就是将用户所希望实现的场景和技术架构进行映射,需要识别的是通过哪些技术可以实现用户所希望实现的场景,并且还要在用户场景不断影响技术架构的过程中保持架构的稳定性、可扩展性、性能等。所以它所做的就是把底下的框框和上面的框框联系起来。
 
    再往右有一个项目计划,这里我列出来了一些项目,项目里会有开发任务、测试用例、可能还会有bug等,项目是从左边的条目化需求引过来的,这是敏捷的做法。
 
    传统的软件开发的做法是:用户想做这个事,先做分析,需要实现哪些技术模块,然后要求把技术模块的技术点梳理成所谓的开发计划,它所传递的项目来源是来自于产品的模块,这是一种瀑布的做法。就是在软件开发过程中,将业务需求打散形成整个产品的完整设计,针对完整设计进行完整开发和完整交付。
 
    它和直接使用条目化需求组织开发过程的区别在于:在你进行完整设计、完整开发的过程中,会发现到了最后收敛的时候,当真正实现了这些软件需求,需要通过一些软件的版本进行交付的时候,你必须要让这些模块的功能收敛到用户希望的场景上。实际上你交付的还是用户场景,只是在开发的过程中把它变成了技术语言,在最后交付的时候再把技术语言转化为业务语言。
 
    这两次转化就意味着我们必须要整体开发整体交付,也就造成了管理粒度非常大,随之而来的就是各种问题。
 
    敏捷开发从过程管理上要把握一个非常重要的原则:中间的开发过程必须围绕一个一个条目化的业务需求来组织,而不是围绕技术功能点。用户要什么我们就开发什么,就怎样去组织开发过程,最后交给他什么。因为就算是你把它打散成技术需求,最后交付的还是业务场景,这是没有变化的。技术与业务之间转化的过程,会造成非常多的问题,包括之前说的依赖问题,都是和过程的组织方式有关系的。
 
    就这一点在我过去所服务过的客户里一些传统的开发团队都非常难做到,因为这和他们现在的管理方法、组织过程以及他们对软件开发的认知都是不一样的。他们可能都会提我们要做敏捷,可能也会说我们要用用户故事来进行需求梳理,但他们没有意识到用用户故事的时候,更深层次的要求是:整个开发过程都要围绕单个用户故事作为管理粒度,来推进整个管理过程并且最后进行交付。
 
    再往右可以看到编码、版本、运维的各种环节,代码的变更会从开发任务产生出来,也可能会从测试用例产生出来,但最后都会被收敛到某一个版本上,而这个版本会按照顺序进入到我们的开发环境、测试环境、准生产环境和生产环境,最后在环境里产生出一些反馈,再回到需求,这就形成了完整的软件研发过程的闭环。
 
    结合前面介绍的内容来看,如果从管理过程来理解软件研发,管理的就是这里面的点和线;如果从工程角度来理解软件研发,更多的倾向是:从开发测试这个环节开始,怎样能够让做出来的东西更快地进入到最后的环境,并且在这个过程中保持其跟踪性以及我们对质量的控制。
 
    总结:研发过程改进,就是对上图中的点和线建立对应的管理单元的过程;并将这些管理单元形成能够快速交付需求的管理体系。
 
    软件研发过程:管理属性和工程属性
 
 传统开发 VS 敏捷开发
 
    软件研发过程具有管理属性和工程属性。管理属性定义了用户要我们做什么;工程属性定义了我们的团队真正做出来了什么,就是我们交付的东西,这两个是软件开发里非常重要的转换,而这个转换靠统一的版本管理来衔接。就是要建立一个统一的版本号的规范,在任何时候都可以通过一个编码快速识别出现在软件开发处于什么样的状态、现在的需求处于什么状态、现在需要交付的东西是哪个。
 
    至此,如果再次反思这个过程就会对第一大法宝——粒度有一个深入的理解了。软件开发过程要管理的其实就是这个粒度,目标是尽量缩小管理粒度。在整个软件研发体系里流动的是被管理的内容,需求、任务、测试用例、编写的代码、交付的模块都是被管理的单元,管理单元越小意味着越容易管理,交付的效率越高。
 
    持续交付就是持续解耦
 
    前文讨论得更多的是管理属性,现在来看工程属性。从工程属性上我们要做的就是持续交付。持续交付到底是什么,持续交付意味着软件一直处于可交付状态。
 
    持续交付本身并不完全等同于CI/CD,不完全等于持续集成和持续部署,因为持续集成和持续部署只能保证有一个可交付的产品,或者有一个可交付的代码集并可以很快把它转化成交付件,且在交付的过程中可以自动进行,CI/CD主要做的是这件事,而本身代码是否处于交付状态靠管理过程控制粒度进行保证。
 
    持续交付实施框架
 
    持续交付
 
    上图展示的是持续交付实施框架,把持续交付分成了7大领域,并且把当前的实践状态分成了每100天交付1次和1天交付100次。实际上在任何一个团队里,当你希望把自己的交付速度提升到每天交付一百次,那你需要从这7个领域进行规划、设计、实施,在这7个领域里我们到底在做什么,归结到底就是:解耦。
 
    持续交付的挑战:系统耦合
 
    持续交付
 
    想要把解耦说清楚,可以从一个简单的场景——取钱来看。站到ATM机面前,把卡插进去、输入密码、输入金额、拿走现金,对于用户来说是再简单不过的事情,但其实这里面的技术非常复杂,在ATM机里需要处理很多的事情:机器系统控制、智能卡识别、接收用户输入、连接银行系统、监控等;还要把信息和数据传输给银行,这个过程中又涉及到数据加密、数据完整性、监控等;到了核心银行系统后需要查找账户、账务信息、进行审计和风险控制等。
 
软件开发中的三级耦合
 
    这十几二十个系统意味着数十个团队和上百人的团队规模,也就是当你把一个简单的用户场景从技术架构角度去看的时候,打散成技术点都会变得非常复杂,这在金融业银行业尤为严重。
 
    这样复杂的系统造成的结果我称之为“涟漪效应”。在一个平静的水面扔下一颗小石子,会在水面荡开一圈圈的涟漪,如果水中有几颗树,涟漪会撞到树。如果把石子理解成需求,树就是受到影响的系统,一个石子的场景相对简单,尝试一下同时扔下两颗石子,第一颗石子扔下去荡开的涟漪在碰撞树的过程中会和第二颗石子荡开的涟漪产生交叉反应,继续影响,产生反过来的影响,这是复杂系统中分析需求、进行架构设计时难解决的问题,就是系统耦合的典型场景。怎么解耦是软件工程领域必须解决的问题。
 
  首先我们需要知道软件开发中到底是怎样的耦合。软件开发中有三级耦合:    
 
    首先我们需要知道软件开发中到底是怎样的耦合。软件开发中有三级耦合:
 
    代码级耦合。所有人在同一个代码分支上同时迁入迁出代码,也就是大家同时开发同一个产品,这种情况下团队规模是没有办法超过20人的,这是一个经验数字,想象一下一个超过20人的团队频繁地在同一个代码分支上进行迁入迁出,基本上是无法工作的。
 
    组件级耦合。不管是什么开发语言都会有包管理器的概念,比如前端可能会用到npm、bower,比如做Python会用到pip,这些包管理器所做的就是进行组件级的解耦。
 
    组件级解耦是指:当我不是直接引用你的代码,而是通过你对版本管理的包进行引用的时候,就可以在一定程度上延迟包的变化对我的影响,比如说我可以一直引用一个1.0的包,但是这个包的开发者已经在升级2.0,但我可以完全不理会他那条分支上的代码变化,我就只引用1.0的包,这时两个团队就被解耦了,如果这是一个产品的两个部分,也被解耦了。
 
    组件级解耦有个最大的限制条件:到达软件上线时间点的时候,要统一同一个应用里的所有的包的依赖。当然我说的这是一个单体应用,所有的代码编译到一起,在一个运行时RunTime里运行,如果是这种情况,那么包管理的隔离就只能到达产品发布的时间点,如果这几个团队开发同一个产品,就算在开发过程中可以让大家去引用不同版本的包,但是如果要一起上线,那么必须在上线的时间点统一大家用的所有的包的版本,不然没办法在同一个环境运行。所以组件级耦合只能解决在开发测试过程中的一定程度的解耦,没办法帮助团队彻底解耦。
 
    怎样才能彻底解耦?就会应用到现在炒得火热的微服务,其实它所做的就是彻底的运行环境级别的解耦。
 
    大家经常看到,很多的web api都会在url里面标识不同的版本号。比如团队1发布了v1版本的api,并且已经被团队2消费;那么团队1可以继续按照自己的步调发布v2版本的api,而团队2可以继续使用团队1的v1版本的api;团队2可以在自己觉得舒服的时间点来升级到支持团队1的v2版本。这样,团队1和团队2就彻底解耦,可以独立完成需求,开发,测试,交付的整个过程。
 
    这时这两个团队从需求、开发、测试到交付的整个过程都是可以不去互相影响的,因为就算运行时在生产环境,这个服务被部署了以后,他们都可以在不同的版本间进行切换,这样就保证了每个团队都可以自主地组织自己的开发过程。
 
    实际上它就是降低了管理单元,让管理单元可以小到一个团队里边,甚至小到几个开发人员,这时可能看到的还是几百人的大团队,其实里面是一个一个小的独立运作的细胞,这些细胞都可以按照自己的步调去移动、去发布、去测试,这样大家才能更加高效地工作。
 

责任编辑:李欢
本文为授权转载文章,任何人未经原授权方同意,不得复制、转载、摘编等任何方式进行使用,e-works不承担由此而产生的任何法律责任! 如有异议请及时告之,以便进行及时处理。联系方式:editor@e-works.net.cn tel:027-87592219/20/21。
e-works
官方微信
掌上
信息化
编辑推荐
新闻推荐
博客推荐
视频推荐