从组织设计到工程实践,你的组织是真敏捷吗?

敏捷实践与螺旋动力模型自管理探讨
2023年5月26日
敏捷给我推开一扇门
2023年6月7日

第一部分 工程实践-极限编程

组织、团队、个人层面的敏捷实践

敏捷先贤们总结了一些关键实践,帮助个体、团队、组织3个层面突破瓶颈,并取得了一定成效,今天我们重点介绍组织和个体两个层面的实践。

极限编程(XP)

极限编程的整个实践分为3层,中间是团队级的,核心包括测试驱动开发(TDD:Test-Driven Development)、结对编程(Pair Programming)、重构(Refactoring)和简单设计(Simple Dasign)。这都是极限编程所推崇的基本实践。

交付周期

软件开发,是像开车,还是像发射炮弹?这二者的区别在于:发射炮弹时我们清晰地知道目标在哪里,可以精确地测量目标,然后提前把炮调好,一发炮弹搞定;而开车,我们只知道要去哪儿,这是一个比较模糊的目标,去目的地的路径可以相对确定,但途中的情况是不确定的,我们也不能把方向盘锁死。

软件开发就像开车,要在行进过程中不断调整,通过调整缩短交付周期,在短交付周期下不断调整方向来达成目标。

你的组织交付周期多长?

缩短交付周期,快速交付,带来的好处包括:

1.快速失败:我们做的事情有一定的概率是不对的,快速失败发现错误,就可以及时止损,避免在错的事情上投入太多的精力和资源;

2.减少返工浪费:如果可以快速验证,返工的地方就比较小,返工带来的浪费也较少;

3.减少库存浪费:在制品的数量也会减少,降低库存的浪费;
尽快交付价值。每次交付的东西都比较小,可以快速产生用户价值,也不会有很多东西做了但没用。

思考:你的组织的交付周期是多长?数月?每月?几周?几天?每天?每天数次?

有哪些因素阻碍了我们缩短交付周期?

每个组织的交付周期差距很大,有些传统团队几个月到半年才有一次交付,有些互联网产品一天有数次交付。

既然快速交付有那么多好处,那我们肯定要想办法缩短交付周期。在此之前先要了解哪些因素阻碍了缩短交付周期。

1.回归测试慢:理论上每次交付都应该有完整的回归测试,如果回归测试就需要一天的话,那肯定不可能一天交付一次了。回归测试慢、成本高,大家就倾向于把周期延长,攒一攒再一起交付,以减少做回归测试的次数。

2.代码屎山:让我做一个东西,半天都找不到在哪改,一改到处都是错,也没办法快速交付。

3.不敢简单设计:给我一个需求,我尽可能地把它各方面都考虑到,复杂设计的结果是留下一堆用不着的代码。

4.集成难:每一次集成都鸡飞狗跳,一堆代码冲突,集成完了后,我这好好的你那出错了,你那正常我这出bug了,大家还得花一段时间来修复集成缺陷。

5.上线难:经常听到有些团队说,今天要上线就意味着今天要加班了,要遭受一轮上线的痛苦。上线难导致大家倾向于往后推迟上线交付的时间,延迟痛苦的到来。

为什么自动化测试不好做

大家都知道回归测试要快,就要实现测试自动化。前些年开始出现一个岗位,叫测试开发,很多人理解测试开发就是过来写自动化测试脚本的。

为什么自动化测试不好做?

测试脆弱。让不是开发的第三个人来写自动化测试脚本的话,这个脚本往往是脆弱的,很容易被破坏,因为他不知道内部的运行原理,只能从外部进行观测。因为他使得测试比较脆弱。脆弱的测试团队就不太相信它,脚本就慢慢变成一个临时的验证手段,而不是一个长久保护;

增加了额外的工作。团队认为写测试是增加额外工作,本来我写代码自己测试一下没问题就交付了,现在写完生产代码还得写测试代码,写完测试代码才能交付。

为什么极限编程可以

为什么采用极限编程的实践可以解决这些问题?

测试驱动开发。不增加额外⼯作。以前的方法是先写生产代码,然后人肉对它进行验证测试,这两部分都是要花时间的。在测试驱动开发里,相当于把人肉测试的时间置换成了编写测试的时间,且把这个时间大幅度缩减了,因为测试是自动的、快速的,只要点一下“run”,测试就跑一遍;

测试,因为这时功能还没实现,测试一定是失败的,我就去写生产代码让测试通过,然后有了新的功能,还是先写一个测试,又是失败的,因为新特性还没实现,就再去写生产代码让测试通过。通过这样一个不断写生产代码和测试的过程,随着功能开发越来越多,测试也越写越多,整个测试就构成了一个代码保护,形成了完整的测试套件,按照这个方法写出来的所有代码都会被测试覆盖;

重构减缓代码腐化。导致代码屎山的原因是代码腐化。复杂代码,随着代码量的增长,代码的可读性和可维护性是逐渐下降的,时间长了就会越写越不好。相信每一个程序员本身都是想把代码写好的,但是他不敢,因为他没有完整的测试套件,不知道对代码的整理是对还是错,整理反而可能带来bug,那还是不动它了。有完整的测试套件后,整理代码的时候,每提取一个函数马上就运行测试,如果测试通过,说明没有破坏任何东西,如果测试不通过,还可以把刚才的操作回滚。这样一来我们就有勇气对代码进行重构了,重构可以减缓代码腐化,完整测试套件可以保护重构。

简单设计减少工作量。简单设计不是简陋设计,简单设计是说我的代码刚好实现当前的功能,不会出现做了一个东西暂时用不到,但将来某一天什么情况下可能会用到的情况,不做这种猜想,现在给我什么需求,我的代码就刚好能实现这个需求,不多也不少。没有测试套件保护的时候,是不敢做这种简单设计的,我们希望一次性把需求做完之后就尽量不要改动,因为一旦改动就可能改坏;

持续集成减少集成难度。集成的难度有两个:一是容易引发bug,二是有很多集成冲突,集成的时间越长,产生冲突的概率就越高,因为大家的变化交叉的概率越高了。有了完整的测试套件后,每次集成都可以进行验证,我们就有胆量可以进行更频繁的集成,频繁的集成又进一步带来了集成难度的下降。

推行极限编程有哪些难点

前面介绍了极限编程可以帮助我们解决很多问题,但事实上使用极限编程的公司和团队却不多,因为要做到并不容易。那推行极限编程有哪些难点呢?

改变编程习惯。传统的编程习惯是不愿意看到失败的,不管是运行失败,还是编程错误,又或者是功能不能用,失败对我来说都是个打击。大家没有快速失败的习惯。其实失败有时候是一个好事,在极限编程的TDD实践中,要求先写测试,一开始很多人是不敢运行的,明明功能还没实现,测试肯定是通不过的,为什么还要运行?其实测试通不过对我们来说是件好事,因为我们已经有个测试套件可以证明代码不能符合某一个逻辑了,等测试通过,代码就写完了。一开始进行测试驱动开发的人可能对这个产生恐惧,习惯了以后,大家逐渐对失败有了更全面的认识,快速失败能快速验证我们在这个方向的努力是错的,可以及时止损;

遗留代码重构。如果代码已经成为屎山了,遗留代码的重构肯定不是一个轻松的工作,不是一天两天可以做完的,有些比较大的项目库,可能得持续好多年才能慢慢把代码重构完,这也会带来一些阻碍;

技能训练。需要学习新的技能,改变旧的习惯,有一些短期的培训,但训练也不是一蹴而就的,还需要长时间的持续练习,包括跟教练结对编程等。

第二部分 组织设计

敏捷组织设计

推荐一本书《敏捷组织设计》。

软件开发是生产还是设计

决定一件事情怎么做之前要先了解它的本质是什么。软件开发如果是生产,那我们就按照传统已经证明的可以高效生产的方式来处理和组织;如果是设计,那我们要按照怎么样设计比较好的方式来组织。

我们先来对比一下生产和设计的区别。

可重复性,生产的可重复性很高,比如生产杯子的过程和工序尽量追求标准化;而设计的过程中相同的工作很少。

探索未知,设计的每次工作都是在探索未知;而生产的未知在设计阶段就解决了,需要批量生产的时候,未知的因素几乎已经不太存在了。

协作模式,设计可能要求大家尽量协作;而大部分生产讲究的是分工。

批量大小,设计的批量要小,每一点都要,因为可能做一点就要去验证一点,以小批量的方式不断交付;生产刚好相反,大批量才能降低成本。

工序拆分,设计的工序一般不建议拆得很细,因为设计的每个环节都有交接的成本,拆得太小会增加交接时间,比如开发完后到下一步做测试,这就产生了交接、等待,还可能产生返工,等待和返工都是常见的浪费,拆得越小,交接得越多,效率就越低;而生产的工序要拆细,每个人做一个尽可能简单的工序,才符合社会化大生产的要求。

价值取向

1.价值导向 VS 可预测性

设计追求的是价值导向,我们做出来一个什么样的有用的东西(设计),它达到了某些目标。Scrum也强调,我们要优先做最有价值的东西,而不是说多长时间内或在某某年月日之前要把这些功能做完。而生产追求的是可观测性,在几天内要生产多少个零件或产品。

2.响应变化 VS 成本效益

这是另外一个矛盾点,响应变化和成本效益。

相信大多数公司都不是为了降低成本而存在,我们的目的是向客户交付我们的价值,软件本身交付的价值更需要的是响应市场的变化,而不是成本效益。

如果你去问老板,他肯定说两个都想要,这是一个错误的想法。这两者中有一个是你存在的理由,另一个则是你的约束。对于大部分软件开发而言,响应变化是我们存在的理由,在满足这一点的前提下,再想办法降低成本,而不是直接把降低成本当做目标。

有些企业是按照成本优先的方式进行组织设计的,其策略是将所有人的时间尽可能地占满,就像高速公路堵满了车,变成停车场了,所有车都没办法畅通行驶,映射到企业中,每个人的时间都被具体工作占满了,没办法响应变化,最终将会导致组织效率变缓,甚至停滞。

3.内驱力 VS 外部激励

对于销售或生产,采用外部激励就可以了,比如计件工资或销售提成等;而设计是知识活动,外部激励很难对其产生驱动,或者驱动的时间很短,这就需要更多地强调内驱力,比如和他共识一个宏大的目标、愿景等。

组织文化

1.职能组织 VS 跨职能组织

职能组织比较常见,比如有产品部、开发部、测试部、运维部等,就是按职能进行划分的一个组织。

跨职能组织是什么呢?很多组织在推行DevOps,DevOps这个词的本意就是跨职能的,但它跨的范围不是很大,Dev和Ops,把开发和运维放在一个团队里,它推崇的一点就是跨职能组织。

2.矩阵组织 VS 能力团队

组织形式是矩阵组织还是能力团队?

矩阵组织是有开发团队、测试团队等,甚至开发团队还细分为Java开发、前端开发、手机端开发等部分,当一个项目需要哪些角色的时候,从各种职能团队中派几个人去临时组建这个项目,项目完成后再各自回到原来的团队。

能力团队是,比如五个人成立一个完整的小团队,里面既有后端开发,也有前端开发,还有测试、运维、产品等,不管要做什么项目,这个小团队都是一起去。能力团队就是团队具备一定的能力,以团队为单位去做一件事。

3.层级组织 VS 扁平组织

层级组织讲究控制,一层层划分;扁平组织往往会以某一个业务成果来进行划分,比如开发某一个产品,或维护某一条业务线,以这个进行组织。

4.开放式布局 VS 相互隔离

这个跟办公室的装修和布局相关,敏捷组织里有很多细节,大家可能之前没关注到。传统公司的办公室很多是格子间设计,员工之间相互隔离,有些团队甚至不在一起办公,沟通存在较多的障碍。

开放式布局就是简单的一张大桌子,一个团队十来个人围在一起工作,不同团队之前可能最多用白板或屏风围成一个空间。敏捷宣言里强调个体和互动胜过流程和工具,开放式布局的好处是更加鼓励大家的互动和面对面交流。

5.即兴协作 VS 正式协作

层级结构更多带来的是正式协作,比如你有一件事需要跟另一个团队的成员沟通,在一些严格层级管理的公司你们是不能直接沟通的,必须先找到你的Leader,你的Leader去找到对方团队的Leader,对方Leader再找到他,四个人坐在一起才能进行一次沟通。即兴协作是有事直接沟通。敏捷组织鼓励即兴协作。

拨打免费咨询电话 021-63809913