目录
TOC generated by https://magnetikonline.github.io/markdown-toc-generate/
前言
在过去项目的开发和迭代过程中,遇到了不少业务方和开发方预期不一致导致的冲突,在所谓的”敏捷迭代“的过程中,也没有感受到敏捷带来的效率或者项目可控性的提升。学而不思则罔,思而不学则殆,于是带着工作中的疑问来阅读”整洁”系列的新作。
疑问1: 为什么直观感受上推行敏捷没有带来效率上的提升,每个时间周期内能做完的事情或者需求还是那么多?
疑问2: 为什么项目仍然会一直 delay?
疑问3: 每日站会的目的是什么?为什么研发在站会时都心不在焉,而且不愿意开?
这个读书笔记并不是一个完整的中文翻译,只摘取书中的关键观点,针对每个观点与我过去项目管理中的经验做对比,并提供一部分我自己的想法。
第一章:敏捷的起源
敏捷的关键点其实是尽量保持人员的稳定,同时坚守对质量的维护。在这两个前提下,把时间点和需求量的取舍交给最终用户来进行。
铁十字,项目中必须要做的权衡
The reason that these techniques fail so spectacularly is that the managers who use them do not understand the fundamental physics of software projects. This physics constrains all projects to obey an unassailable trade-off called the Iron Cross of project management. Good, fast, cheap, done: Pick any three you like. You can’t have the fourth. You can have a project that is good, fast, and cheap, but it won’t get done. You can have a project that is done, cheap, and fast, but it won’t be any good.
观点总结:
- 就像我们的日常生活被物理定律支配一样,软件开发也有基本规律。书中称为 The Iron Cross (铁十字),即:对于一个项目,在质量、速度、成本、完成度4个维度中挑选3个,舍弃一个,不会有一个项目能高质量、低成本、快速地把所有需求都完成。如果一个项目能低成本、快速地把所有需求都完成,这个项目一定质量不高。
- 项目经理需要做好权衡,把这4个方面都做到足够好即可,不需要做到100%。
实际项目:
- 在过去的软件开发项目中,质量意味着 bug 率和代码可维护性,交付的产品中有多少未修复的 bug,有多少单元测试覆盖。速度意味着一个需求的交付周期。成本意味着有多少人参与。完成度意味着有多少需求完成了,特别包括一些为了使用体验而提出的优化需求。
- 在上一个项目当中,项目初期有一个明确的完成时间点,且评估下来时间上很紧张,同时项目的范围的约束有简单的功能点罗列,所以在项目开始时,我们的权衡就是:
- 质量 (Good) 70%。因为我们在完成项目的同时希望可以做成一个可移植的产品,并且没有人愿意接手垃圾代码,所以单元测试、代码风格、同行评审是一开始就强制加在提交流程里的。但是对于一些不影响主流程的 bug,可能就决定暂不处理了。
- 速度 (Fast) 90%。由于项目的周期很紧,所以速度是最不能牺牲的一部分。
- 成本 (Cheap) 50%。由于内部人员的支持不足,成本上被迫做了很大的牺牲。
- 完成度 (Done) 30%。由于其他方面的限制能调整的空间太少,只能在完成度上做牺牲,对于用户体验不好的地方暂时不做处理,能把功能性需求完成就行。对于 UI 上不好看的地方也暂时不处理。
思考:
- 和 CEO 的一个比较大的分歧就在于铁十字是不是能改变。对于 CEO 来说,一个公司的存亡往往意味着能以更低的成本(Cheap)、更快的速度(Fast)做出体验更好(Done\Good)的产品来满足客户。但是对于我来说,这个权衡是实实在在存在,并且得做的,而作出的牺牲都可能被归咎于团队的积极性和主观能动性不高,毕竟多改几个 bug (Good),多做几个需求(Done)都是可以通过加班来提高的嘛。
- 在其他的资料中,也提到类似的看法,比如 Atlassian(做 Jira 的公司)提到 The iron triangle of planning
。
- 传统的项目管理有3个需要权衡的铁三角:工作范围(比如需求点和功能点)、资源(经济资源和人力资源)、时间(交付里程碑)。这3个被称为铁三角,就意味着在改变一个要素的情况下,是不可能不影响其他两个要素的。比如在增加需求的情况下,不加资源是不可能按原时间交付的。
- 但是实际工作中,总是会有要求需求要全部做完,人员也没有额外的变动空间,时间节点也是限制死的。这时候大家是怎么办的呢?其他人的博客其实也提到过 The Lie of the Iron Triangle 在这种情况下,其实牺牲的就是铁三角的第四个面,也就是当这三个条件无法组成三角形时,质量就流失了。我们会加班工作,跳过必要的测试步骤,压缩用户培训时间,压缩部署流程中的检验环节,跳过文档的撰写,不修复一些低优先的 bug。于是我们就交付了一个质量有问题的产品。作为这个产品的作者,程序员,无疑是悲哀的。
敏捷的目的
As the iterations progress, the error bars shrink until there is no point in hoping that the original date has any chance of success.
This loss of hope is a major goal of Agile. We practice Agile in order to destroy hope before that hope can kill the project.
- Sprint is the term used in Scrum. I dislike the term because it implies running as fast as possible. A software project is a marathon, and you don’t want to sprint in a marathon.
观点总结:
- 敏捷迭代的目的不是使开发速度更快,也不是使项目不会 delay。恰恰相反,敏捷迭代的目的,是在早期把项目不会 delay 的希望给打碎,避免像瀑布式开发,到了交付前几天或者几周,才发现项目无法交付。
- 敏捷迭代中每个迭代叫一个“冲刺”,但是这个词并不好,因为一个软件项目是一场马拉松,在跑马拉松的时候你不会一直保持冲刺的姿态。
实际项目:
- 实际工作中,“敏捷”往往给人一个感觉,”敏捷“迭代会使得项目开发的速度变快,这个其实从一开始就不是“敏捷”的意义。
- 在我做的上一个项目中,其实并不需要敏捷迭代来预警,从一开始的项目计划排下来,就没办法排一个不 delay 的计划。
思考:
- 敏捷的意义在于预警,在于可控性。可控性不意味着不会 delay,而是及早地把问题暴露出来,及早地采取措施解决问题。但是如果项目一开始就没有一个计划能不 delay,那么无论用什么项目管理或者迭代的方法,还有什么意义呢? 当然有意义,项目的目标是实现商业价值,错过了时间可能会减少商业价值,所以不 delay 不能作为项目的最终目标之一,最终目标应该是以最大化项目的商业价值为目标。
- 至此,疑问1和疑问2都被解释了,其实敏捷并没有打算解决我们认为的开发效率和项目 delay 的问题。那么敏捷团队是怎样看待并处理 delay 这件事情呢?
管理项目的铁十字 (The Iron Cross)
Remember, the date was chosen for good business reasons. Those business reasons probably haven’t changed. So a delay often means that the business is going to take a significant hit of some kind.
Brooks’ law states: Adding manpower to a late project makes it later.
Everyone knows that you can go much faster by producing crap. So, stop writing all those tests, stop doing all those code reviews, stop all that refactoring nonsense, and just code you devils, just code. Code 80 hours per week if necessary, but just code! Producing crap does not make you go faster, it makes you go slower. This is the lesson you learn after you’ve been a programmer for 20 or 30 years. There is no such thing as quick and dirty.
Anything dirty is slow.
If the organization is rational, then the stakeholders eventually bow their heads in acceptance and begin to scrutinize the plan. One by one, they will identify the features that they don’t absolutely need by November. This hurts, but what real choice does the rational organization have? And so the plan is adjusted. Some features are delayed.
观点总结:
- 当我们通过敏捷迭代开发了一段时间之后,我们可能会发现项目或者交付物会 delay,这时候怎么办呢?常见的方案有几个:
- 修改交付目标时间点。这个方案简单,但是往往后期会被作为一个事故诟病。
- 加人。根据 Brooks 定律,加人会导致项目进一步 delay。因为新人加入项目之后需要原项目组的人分配额外的时间进行培训和问题解答,会影响原项目组的人的效率,而新人往往要过几周才能不需要指导地完成工作,就意味着这几周内,效率是比原来要低的。但是如果时间够长,整体团队效率还是能较之前有提升的。
- 降低质量。这个方案往往是大多数人采取的方案。例如时间不够的时候,不写单元测试,不写注释,不写文档,不做代码评审,不做完整的回归测试,不做用户培训,不使用灰度发布。这样可以写出很多脏代码。但是做过20、30年开发的人都知道,没有哪个脏代码可以很快开发完成的,越脏的东西,越慢。
- 砍需求,减少需求范围。让用户放弃一部分需求是很困难的,特别是用户出资支持这个项目开发的时候,更难。但是如果整个组织和用户是理性的,在不修改时间的前提下,会很痛苦地接受这个事情,砍掉一部分需求。
实际项目:
- 作为项目经理,无时不刻在面对这4个方案的选择,每个方案都需要克服一定的压力才可能落实。改时间的话往往意味着 KPI 不达成,或者合同违约。而砍需求对用户来说也是一个很痛苦的决定,这个对话也会很艰难。于是看似简单的方法就变成了加人或则会降低质量。在我上一个项目中,频繁的人员变化导致了许多的重复工作,项目背景、代码框架需要重新介绍,需要重新磨合,但却是项目慢慢变好的一个必经之路。而质量,则是最难坚守的一道坎。后端的代码一直坚持着单元测试,但是前端却很难用类似的方法进行覆盖管理,也是后续项目迭代越来越慢的一个原因。
思考:
- 对于一个产品经理或者项目经理来说,最难的应该是坚守产品的质量,但在我看来,这也是区分一个平庸的项目经理和一个优秀项目经理的关键点。没有经历过软件开发的人,不会理解代码质量对于长期发展的影响有多深。
- 敏捷的关键点其实是尽量保持人员的稳定,同时坚守对质量的维护。在这两个前提下,把时间点和需求量的取舍交给最终用户来进行。
第二章:为什么要敏捷
程序员的职业素养 (Professionalism)
We in this industry sorely need to increase our professionalism. We fail too often. We ship too much crap. We accept too many defects. We make terrible trade-offs. Too often, we behave like unruly teenagers with a new credit card. In simpler times, these behaviors were tolerable because the stakes were relatively low. In the ’70s and ’80s and even into the ’90s, the cost of software failure, though high, was limited and containable.
观点总结:
- 在当今的社会,生活的方方面面已经离不开程序员的代码贡献了,app、网站、公共交通、政府、银行、医疗等等都被软件应用打通了。想象你写的那些代码会被作用到这些关键的领域,而你的一个 bug 可能导致他人损失金钱甚至生命,那我们对待手上的代码时,应该要保持更高地专业度和职业素养才行。
实际项目:
- 在之前的项目中,即使我很希望能保持最高的专业度,所有代码都有测试用例覆盖,每个提交有对应的单元测试执行,每个环境的部署都有自动的健康检测等等。但是做这些事情短期看不到什么成果,而且会导致成本大幅上升,就根本推不下去。
思考:
- 作为一个程序员,难的不是尽力写出好的代码,或者保持高的专业度,难的是上司或者领导迫于商业或者其他压力,要求你不写测试用例,不测试直接上线等等。
一些对程序员的合理的期望 (Reasonable Expectations)
What follows is a list of perfectly reasonable expectations that managers, users, and customers have of us. Notice as you read through this list that one side of your brain agrees that each item is perfectly reasonable. Notice that the other side of your brain, the programmer side, reacts in horror. The programmer side of your brain may not be able to imagine how to meet these expectations.
Meeting these expectations is one of the primary goals of Agile development. The principles and practices of Agile address most of the expectations on this list quite directly. The behaviors below are what any good chief technology officer (CTO) should expect from their staff. Indeed, to drive this point home, I want you to think of me as your CTO. Here is what I expect.
观点总结:
- 敏捷开发的一个主要目的是达到以下的一系列期望,这些期望是针对程序员的。可以把这些期望想象成敏捷开发的目标。敏捷的方法论就是为了达到这些期望而设计出来的。
- 我们不交付垃圾 (We will Not Ship Shyt)。 这个听起来是个废话,但是现实是,这确实需要作为一个期望提出。所以敏捷会强调测试、重构、简化设计,从而保证交付给客户的都是高质量的、用户友好的产品。
- 技术上持续可部署 (Continous Technical Readiness)。 敏捷要求在每个迭代结束的时候,系统都是处在一个可部署的状态。如果用户选择不部署更新,比如做完的功能点还不够多,或者商业时机没到,这是一个商业决定,这没关系。但是在每个迭代结束的时候,所有完成的功能都需要是写完代码、测试过、写清楚文档的。所以敏捷要求每个用户故事都足够小,从而保证可以在一个迭代中高质量地完成。
- 稳定的产能 (Stable Productivity)。 在项目一开始的时候,往往会发现功能做的很快,因为没有老的代码库的依赖,没有历史包袱,但是随着项目发展,同样复杂度的需求可能会需要花许多2-3倍的时间,这往往是很多非研发背景的客户或者管理者无法理解的。其实出现这个情况就意味着代码的架构设计或者逻辑结构有问题,需要优化或者重构,但是重构应该是随着每个需求小范围的进行的,不应该整体推翻重来。同样的,敏捷要求的测试、结对编程、重构和简化设计都是保持稳定产能的关键。
- 低成本地进行修改 (Inexpensive Adaptability)。 研发经常会抱怨需求一直变更,但是好的架构和好的程序设计应该是能灵活应对需求的变更的,如果无法灵活应对,则代表你的架构或者设计很差。程序员的意义也正是在于可以实现需求变更。同样的,敏捷要求的测试、结对编程、重构和简化设计都是保持低成本地进行修改的关键。
- 代码的持续优化提升 (Continous Improvement)。无畏地把事情做好 (Fearless Competence) 人类渐渐地把事情变得更好,代码也不应该例外,不应该因为时间的流逝,代码渐渐腐化。而代码的腐化往往出现在尝试走捷径的时候,例如一个需求可以选择:做一个简单修改,但是留下一个 magic number;也可以选择:做一个小重构,把变量抽离开。此时有很多人都会不敢做这个小重构,因为担心改出一些意外的 bug。但是如果有面向测试编程的支持,所有的需求都有自动化的测试用例,如果测试用例都跑过了就意味着没问题,那么我相信大部分程序员都不会害怕做这样的小重构。而敏捷推崇的结对编程、面向测试编程、重构、简化设计都是为了支持这一点。
- 测试应该找不到问题 (QA Should Find Nothing) 应该尽量做自动化测试 (Test Automation) 当测试跑一遍他们的测试用例的时候,他们应该能得出系统一切正常的这个答案。当测试发现 bug 的时候,研发团队应该复盘在研发的流程中,哪一步出错了,从而保证下一次不会出现同样的问题。同样的,对于测试来说,重复的手工测试是耗时、昂贵、而且不人道的,如果留给测试时间不足的话,那么无论怎样对测试用例进行取舍,交付出去的都是一个没有被完整测试过的产品,所以我们应该用自动化测试来覆盖所有可以覆盖的测试用例,让测试只需要测那些无法自动化的部分。这也是让研发团队可以做到交付测试无 bug 的必经的一步。
- 我们为其他人互相打掩护 (We Cover for Each Other) 客户不会关心你的私人生活是不是有什么变故,生病、度假都不应该影响到整体,不应该让整个团队停摆。所以敏捷的结对编程、完整团队、集体拥有的思想都是为了达到这个目标的。
- 诚实的预估 (Honest Estimates) 所有的预估,都应该是诚实的。最诚实的预估是 “我不知道”。但是呢,即使一些事情自己不知道,也应该基于自己了解的信息提供一些信息。比如我们可能无法预估出某个任务可能需要花的时间有多长,但是我们可以和已经做过的事情比较,比如任务 A 比任务 B 简单,但是比任务 C 复杂,这也是非常有价值的。或者我们也可以给出不同置信度的预估,比如任务 A 有 5% 的可能在 3 天内完成,有 50% 的可能在 6 天内完成,有 95% 的可能在 20 天内完成。这个信息也可以给项目经理很多帮助。
- 你需要说“不” (You Need to say no) 即便我们工程师是为了解决问题而存在的,但是当事情没有一条可能完成的路径时,无论上级或者外部有多大的压力,也需要把 “No“ 说出来。敏捷的完整团队思想是为了支持这一点的。
- 持续学习 (Continous Agressive Learning) 无论公司支不支持,即使没有机会,也要自己创造机会去学习,从而适应这个快速变化的行业。
- 做导师 (Mentoring) 最好的学习方式是教其他人,所以尽量去做导师辅导新人。
实际项目:
- 这是一个很长的期望列表,我也针对这个期望列表来对照看看在过去的项目中做的如何。
- 我们不交付垃圾 (We will Not Ship Shyt)。 这个可以说是意外地做得最差的一条。无论是在哪个公司,我都对过去交付的产品不够满意,在 Bloomberg,即使一个老牌的大公司,大部分代码也缺少单元测试,甚至很多代码都无法在业务流程中进行测试。而其他的创业公司,有一部分新项目有比较好的单元测试覆盖,但是也仍然缺少端到端的自动化测试,所以至今也没有一个产品或者公司是在这一条让我可以拍着胸脯说,我交付的产品我满意。
- 技术上持续可部署 (Continous Technical Readiness)。 意外的这一条倒是做的还不错,现在大部分的公司都有了自己的 CI 系统,可以在研发提交之后自动进行单元测试、自动部署。所以至少在每个迭代结束的时候,只要及时把 bug 修复,是可以做到持续可部署的。
- 稳定的产能 (Stable Productivity)。 这一点在 Bloomberg 这样的大公司做的是比较差的,因为历史包袱太严重,每个需求的修改都是牵一发而动全身,而大部分代码又没有单元测试,就大大拉低了整体团队的迭代速度。在熵简的我负责的项目中,后端的代码都是有完整的单元测试覆盖的,从而保证了整体后端迭代的速度并不太受时间影响而变化,但是前端的代码却没有这个覆盖,也导致了整体前端的迭代速度会相对较慢。不过前端的自动化测试也一直是一个国内外较难进行的工作。
- 低成本地进行修改 (Inexpensive Adaptability)。 这一条和 “稳定的产能“ 其实类似,在代码健康的情况下,整体的修改成本不会太高。但是有一点是敏捷没有提到的,在代码设计时,如果代码的底层逻辑是与实际业务设计贴近的,那么修改起来的成本也会和实际业务贴近,更容易被客户接受。例如某个实体是否是唯一的,是否作为可能被重用,在数据库、页面、处理 API 的定义上尽可能去和业务逻辑贴近,从而保证业务发起的修改复杂度更可控。
- 代码的持续优化提升 (Continous Improvement)。无畏地把事情做好 (Fearless Competence) 这一条无论在哪个公司,都没有很好地做到。一个是由于业务时间线的压力,当研发提出需要对某部分的代码进行重构的时候,业务领导往往不会支持这个任务的排期。另一个是由于程序员自身的恐惧,害怕由于自己修改了代码导致 bug,不光要熬夜加班改 bug,可能也会影响到自己的绩效。这两个问题,前者可以让领导认同敏捷的思想,从而推行定期清理技术债的行动。后者则一方面靠程序员的自我修养,另一方面靠敏捷的完整团队的意识,责任共担,从而让大家可以做对的事。
- 测试应该找不到问题 (QA Should Find Nothing) 应该尽量做自动化测试 (Test Automation) 我不认在国内任何一家公司能做到这个程度,在我呆过的公司也没有一家做到的。我认同这个思想,但是可能太理想化了。
- 我们为其他人互相打掩护 (We Cover for Each Other) 在 Bloomberg,所有的功能都有主负责任和副负责人,同时代码评审也很认真,所以很好地达到了这个要求。但是在创业公司,大部分人对这一点其实是排斥的,因为能暂时完成、替代其他人的工作往往被认为是工作内容不饱和,团队产能有冗余,管理层就会希望进一步压榨产能,直至团队成员缺一不可。
- 诚实的预估 (Honest Estimates) 与其说是诚实,不如说是有技巧地预估。当无法给出一个准确答案的时候,给出一个相对值或者概率值。但是这个在之前的项目中,给出相对预估的有,但是给出概率预估的我还没遇到。
- 你需要说“不” (You Need to say no) 这一点在之前的项目中基本没有做到。特别是创业公司,被扣了一顶帽子 “创业公司就是要把不可能完成的事情做成”,那这时所有的 “No” 就变成了和公司对着干的行为,是无法生存下去的。
- 持续学习 (Continous Agressive Learning) 做导师 (Mentoring) 这两点主要得看公司对于这两个行为的支持程度。Bloomberg 是完全支持的态度,但是创业公司往往都是明着或者暗着反对的态度,比如把工作量排到996或者007,基本也不会有时间进行额外的学习或者 Mentor 了。
思考:
- 这些期望描绘了一个敏捷迭代的乌托邦,如果能达到 50% 基本就是一个不错的公司了,如果能达到 80%,就可以列上程序员的理想雇主了。
- 预计在未来10年内,这些期望都不会完全被认同,比如自动化测试就需要很长的时间才能完成覆盖和补全,如果哪个公司能让程序员低成本地进行自动化测试,这家公司也会因此创造极大的财富。
权利法案 (The Bill Of Rights)
The goal of Agile was to heal the divide between business and development.
Notice, as you read these rights, that the rights of the customer and the rights of the developer are complementary. They fit together like a hand in a glove. They create a balance of expectations between the two groups.
观点总结:
- 敏捷的目的是修复业务方和研发方的鸿沟,而权利法案就是两方制衡的方案。
- 用户不光指的是最终的使用者,也包括内部的产品经理和项目经理。
- 用户的权利:
- 用户有权知道整体的安排,以及每个需求完成所需的代价。
- 整体的安排不代表在某个时间点一定会交付某个需求,需求的内容和交付时间点,这两者之一是需要可以进行调整的,相对灵活的。需要可调整的并不意味着可以不预估,还是要预估一个带可能性的时间帮助用户处理相关事宜。
- 用户有权知道每个迭代预计会完成的功能/需求/产出。
- 用户有权在一个可以运行的系统上看到工作的的进度,可以尝试用不同的测试用例来验证。
- 用户有权改主意,有权在花合理的代价的前提下改需求。
- 修改需求或者功能是可以的,只要能对应付出价格/时间上的妥协,这也是软件开发行业存在的意义。而合理的代价意味着软件的设计应该是好的,灵活的,而不是需要推倒重来的。要不怎么叫“软”件呢
- 用户有权知道时间计划和工作量预估的变化,同时选择修改需求范围以保证某个时间点的交付。
- 用户可以在任意一个时间点取消项目,并且拿到一个可以运行的,反映了至今为止投入的可以工作的系统。
- 开发者包括研发、测试、需求分析师等。
- 开发的权利:
- 开发者有权知道每个需求的优先级和清晰的描述。
- 这条要求了开发者拿到的需求是固定并清晰的。这个可能和前面用户能改需求的权利相违背,但主要区别在于时间范围。在一个迭代的内部,需求需要是固定并清晰的,在迭代和迭代之间,需求是可以变化的。
- 开发者有权在任何时候高质量地完成工作。
- 这条意味着,不能因为需求做不完而要求开发者做出违背职业素养的事,比如跳过测试、文档、代码审核,或者明知有安全隐患却不处理。
- 这条也许是最难的一条。
- 开发者有权向同事、领导、客户寻求并获得帮助。
- 开发者有权提出工作量预估,并且更新修改自己的工作量预估。
- 预估不代表承诺。
- 预估不可能准确,预估永远只是个预测值。
- 开发者有权主动获取自己的责任范围,而不是被动分配。
- 关键点1: 计划内,要么需求范围,要么时间点需要是灵活的,不能两个都是定死的。用户没有权利要求在某个时间点前一定要完成某些功能,用户只能通过修改需求范围来达到所需要的时间点。为了使用户能理性地作出这个判断,需要给他提供足够的信息,包括每个工作的预估时间和代价。
- 关键点2: 不能因为需求做不完而要求开发者做出违背职业素养的事。
实际项目:
- 在上一个项目中,用户的权利基本都是可以得到保障的,除了一点,就是当前项目的状态。项目的状态都是经过美化过的,没人愿意承认当前的项目当中问题一大堆,显得自己能力不行,但是哪个项目会是一帆风顺没有坎坷的呢?
- 在上一个项目中,研发的权利是没办法得到保障的。
- 无法高质量地完成工作。当需求来不及做的时候,第一处理方案总是加班,在长期无偿加班的时候,开发者也很难保持一个完美主义的状态把事情做到 100 分,于是就产出了低质量的产品。如果第一处理方案也没法处理,第二处理方案往往是跳过测试、跳过文档、跳过审核,跳过这些看似不会立即产生价值的阶段。
- 无法拿到清晰描述的需求和优先级。在面对强势的客户时,客户提出的需求在一个迭代内可以变化两三次,导致前一个需求还没测试完,需求就又变了。
- 预估即承诺。在预估的时候,管理层认为预估应该要尽量贴近实际,所以偏长的预估往往会被 challenge。而在实际推进的时候,预估又被认为是“承诺”,导致“承诺”的时间内永远完不成工作。此时理性的研发工程师的做法就是提高预估的时间,从而避免延期风险,但这样一来,用户就得不到真实的信息了。也违背了“诚实预估”的期望。
思考:
- 如果在所有人都认同这个权利法案的前提下,项目的推进是可以在一个理性且高效的节奏里进行的,关键是所有人都认同这个权利法案。而这个关键就要求大家都了解到每个权利背后的原因,没有做过研发的人是很难理解的,比如为什么不能承诺某个事情在某个时间点前一定要完成。
- 使所有人都认同这个权利法案的最好时机是在项目启动会,在明确了整体项目基调之后,后续的细则措施也会好推行很多。
第三章:敏捷的业务方最佳实践
项目计划和估时
How do you estimate a project? The simple answer is that you break it down into its constituent pieces and then estimate those pieces. This is a fine approach; but what if the pieces themselves are too big to estimate with any accuracy? You simply break down those pieces into smaller pieces and estimate them.
If you would like an accurate and precise estimate of a project, then break it down into individual lines of code. The time it takes you to do this will give you a very accurate and precise measure of how long it took you to build the project—because you just built it.
There’s a saying among older programmers: “I can meet any deadline you set for me, as long as the software doesn’t have to work properly.”
观点总结:
- 项目的计划和排期常见的方法是把一个大项目,拆成小的工作包,对每一个工作包进行估时后,再进行汇总。如果有某个工作包没办法估时怎么办呢?把它拆成更小颗粒度的工作包。这样循环下去,最小的颗粒度可以拆分到每一行代码。
- 如果我们想要一个很精准的时间预估,那么我们就需要把任务拆成每一行代码,但是如果这样做了,那这个项目也就做完了,这样的预估会花很长时间。而时间预估的目的是获得一个不精确的预估,预估得越不精确,所需要花在预估上的时间也越少,反之亦然。
- 预估的时候可以用 PERT 方法,预估三个时间,一个 10% 可能完成的时间,一个 50% 可能完成的时间,还有一个 90% 可能完成的时间,项目经理利用这三个时间来做项目计划。
- 只要不要求软件正常工作,我可以满足任何时间要求。
实际项目:
- 在上一个项目中,由于管理层认为“预估时间”等于“承诺时间”,而研发又倾向于预估一个 50% 可能完成工作的时间。这就导致了预估时间有 50% 可能是不够的,也就意味着有 50% 的延期可能。
思考:
- 在预估的同时,最好也能把预估不准的可能因素给列出来,包括第三方库的使用、新架构的引入、新的业务流程的熟悉等。这样项目经理才能把这些导致预估不准的要素也作为项目风险考虑进去。
- 对于 “预估时间” 怎样看待,有很多分歧意见。很多人会认为如果不能让工程师承诺一个时间,就会不断拖拉导致延期。其实这个观点只是希望用 “预估时间” 形成一个限制,避免需求范围的扩张和工作摸鱼。但避免需求范围扩张的最好方式是通过验收条件来限制,例如设计一个合理的 Acceptance Test。而由于软件工程本身是个很需要创造力的脑力工作,单纯用时间来限制并不能保证创造出高质量的工作。
用户故事和估时
A user story is an abbreviated description of a feature of the system, told from the point of view of a user.
So, we pick a story from the batch that we consider to be of average complexity. Then, we choose a number of points for the story. It is now our Golden Story. It is the standard against which all other stories will be compared.
The iteration begins with the Iteration Planning Meeting (IPM). This meeting should be scheduled to be one-twentieth the duration of the iteration. The IPM for a two-week iteration should require about a half a day.
A spike is a meta-story, or rather, a story for estimating a story. It is called a spike because it often requires us to develop a long but very thin slice through all the layers of the system. That will allow the developers to do the work necessary to estimate the original story, which can be implemented in a future iteration.
观点总结:
- 每个用户故事是一个需求的简短描述,简短到可以一眼看完,但是又能明白要解决用户的什么问题。
- 可以在早期挑选一个平均复杂度的需求作为黄金故事,也就是锚点。这个用户故事在后续会用来评估是否有估时膨胀的问题,例如登陆功能在一开始只需要3个 story point,但是在半年后,类似的一个功能却需要30个 story point,这说明在这半年内发生了估时膨胀。
- 迭代规划会议需要安排相对于整个迭代 1/12 的时间。例如两周的迭代需要大概半天进行迭代规划会议。
- 一个 spike (尖刺) 是指为了能以期望的准确度来预估某个用户故事,而进行的活动。这个活动的完成目的就是可以预估该用户故事。
实际项目:
- 在上一个项目中,没有锚点需求,但是也没有明显的估时膨胀的现象,因为在每个迭代中,任务的相对复杂度会和早期的类似任务进行对比,避免估时膨胀。
- 迭代规划会议确实是相对耗时的一件事,因为要让迭代中参与的所有人都明白这个迭代中要做的事情,所以 1/12 的比例也是相对合理的。在上一个项目中也是类似的安排。只不过把会议拆成了两个,一个是需求讲解的会议,一个是估时和冲突讨论的会议。
思考:
- 估时膨胀的问题是许多领导层担心的事情,但在实际操作中,如果团队的成员都是有较好职业素养的,其实并不太容易出现。但设立一个锚点需求可以帮助许多刚开始采用敏捷的团队了解怎样快速上手。
- 还有一个常见的情况就是缺乏足够的信息来进行精确的预估。此时往往需要用一个单独的任务来进行调研,团队的实际实践中,需要把握调研的深度,深入到足够进行预估即可,避免在调研上无休止地进行。
迭代的计划
The stories that are valuable but cheap will be done right away. Those that are valuable but expensive will be done later. Those that are neither valuable nor expensive might get done one day. Those that are not valuable but are expensive will never be done. This is a return on investment (ROI) calculation. It’s not made formally, and no math is necessary. The stakeholders simply look at the card and make a judgement based on its value and its estimated cost.
At the midpoint of the iteration, many stories should be done. With only a week left, it’s not likely that they are going to get 20 more points done. So the stakeholders remove enough stories from the plan to reduce the remaining points to 10.
On Monday, when the next iteration begins, how many points should the stakeholders plan for? Eighteen, of course. This is called yesterday’s weather.
观点总结:
- 不是所有的用户故事都需要被完成的,根据 ROI (Return On Investment),可以将用户故事根据成本和回报分成4个象限,从高价值低成本 -> 高价值高成本 -> 低价值低成本 进行安排迭代。而低价值高成本的用户故事可能永远都不会被安排到。
- 在迭代的中间点,需求方需要根据已完成的故事点数,进行任务的调整,如果预计能完成更多任务就加一些用户故事进来,如果预计完不成的话,就删去一些用户故事。从而帮助团队在迭代结束的时候,尽量交付完成的用户故事。
- 在下个迭代开始的时候,如何预估团队的速度呢?最简单的就是按照上一个迭代完成的用户故事的总点数。
思考:
- 在项目背景的不同情况下,对于一部分低价值、高成本的用户故事可能也需要做。例如签订了与成本无关的总价合同,在总价合同中要求了该部分需求需要实现。这时候客户其实不关心项目的实现成本,能多实现一些需求就是一些。但换个角度想,合作都是基于善意基础的,如果一方表现出非善意的情况,另一方的理智做法是选择对自己价值保留最大的做法。例如甲方如果真的非善意地提出了某低价值高成本的需求需要实现,乙方在权衡合同缔约的成本和实现成本之后,也是可以做出一个理智判断的。从博弈论的角度来说,在进行的合同中,此类的需求不会太多,否则乙方一定会选择缔约来终止合同的。
- 在管理团队时,许多人会认为任务排得越多越好,团队的速度预估高一些更好。但这样往往会导致团队的重心分散,所有的事情都是高优先,所有的需求都必须要完成,结果结束的时候完成了一部分不那么重要的,而重要的需求没完成。
迭代中管理
The goal of each iteration is to produce data by getting stories done. The team should focus on stories rather than tasks within stories. It is far better to get 80% of the stories done than it is to get each story 80% done. Focus on driving the stories to completion.
观点总结:
- 迭代的目的是收集数据
- 在一个迭代中,如果有一部分用户故事没有完成,要在迭代中后期选择牺牲一部分用户故事,以保证交付尽量多完整的需求。
实际项目:
- 在上一个项目中,并没有完全按照这个最佳实践进行,由于需要牺牲的用户故事也是有极大的用户价值的,而且程序员在进行上下文切换的时候,会有一部分的工作效率的损失,所以从长期项目的进度角度,并没有按照这个最佳实践进行。
思考:
- 在敏捷的原则中,为了应对迭代和迭代之间可能进行的频繁的需求变更,所以对于完整地完成一个用户故事会特别看重,毕竟没有完成用户故事的话,也就无从谈起针对已上线功能进行迭代了。
- 同时为了迭代的数据收集是尽量准确的,我们不相信程序员说的 80% 已完成的话,我们只相信完成、通过测试、可以上线的功能演示。
QA和测试
If QA has not already begun to write the automated acceptance tests, they should start as soon as the IPM ends.
Acceptance test writing should go quickly. We expect them to all be written before the midpoint of the iteration.
After the midpoint, if all the acceptance tests are done, QA should be working on the tests for the next iteration.
Developers and QA should be communicating intensely about these tests. We don’t want QA to simply “throw the tests over the wall” to the developers.
观点总结:
- QA 和测试应该完全用自动化的方式来实现,而用户故事满足的需求应该是代码通过了对应用户故事的测试用例。这样可以在开发提交之后迅速检验是否符合要求,测试就不会是链路的最后一段。
- QA 应该在迭代中期完成所有自动化测试的撰写,完成之后可以写下个迭代的测试。
- QA 和开发在测试撰写的过程中应该积极沟通,而不是测试写完之后就扔给开发。
实际项目:
- 测试的完全自动化难度很大,在上一个项目中,后端的项目是有完整的单元测试,集成测试也很容易通过 rest api 的调用实现。但是前端的项目迟迟不能实现自动化,由于前端代码的特性,元素的定位和状态的识别一直没有一个银弹。
- 由于前端项目没办法进行自动化,就还是需要手动测试的补充介入,也导致测试仍然在交付链路的最后一段,承受者很大的压力。
- 在上一个项目中,由于大部分用例没有自动化,研发也并不关心测试写好的逻辑,而是等测试执行后发现问题了,才跟测试沟通。
思考:
- 前端的测试自动化仍然是业界发展的一个重要方向。在我离职之前原本希望推动一个改进,将测试工程师和前端工程师之前搭起一个桥梁,例如约定一个元素定位的机制,类似特殊的 html tag attribute 之类的,帮助测试解决元素定位的问题。如果能把前端的测试进行自动化,整体的迭代和交付速度才能真正提高。例如在 3000 多人的 Bloomberg,QA 团队就用 UI 测试框架实现了常见的功能测试,两三天内就能验证完整体的系统正确性。而在上一个10多人的团队中,却仍然也要1周才能验证完毕。
团队速度
We expect that after the first few iterations, the slope will be zero—that is, horizontal. We don’t expect the team to be speeding up or slowing down over long periods.
If we see a positive slope, it likely does not mean that the team is actually going faster. Rather, it probably means that the project manager is putting pressure on the team to go faster. As that pressure builds, the team will unconsciously shift the value of their estimates to make it appear that they are going faster.
If the velocity chart shows a consistent negative slope, then the most likely cause is the quality of the code. The team is likely not refactoring enough and they are probably allowing the code to rot. One reason that teams fail to refactor enough is that they don’t write enough unit tests, so they fear that refactoring will break something that used to work. Managing this fear of change is a major goal of team management, and it all comes down to the testing discipline.
As velocity falls, pressure on the team builds. This causes the points to inflate. That inflation can hide the falling velocity.
One way to avoid inflation is to constantly compare story estimates back to the original Golden Story, the standard against which other stories will be measured.
观点总结:
- 团队速度大概是所有管理层最关心的东西之一。一般来说在开头的几个迭代后,速度的变化就会趋于0,长期来看速度不应该变快,也不应该变慢。
- 如果我们发现速度变快了。大概率不是团队真的更高效了,而是管理者的压力逼得大家把预估都往高了估,这样可以让自己看起来效率变高了。这就是预估膨胀了。
- 如果我们发现速度变慢了。大概率是因为重构做的不够,而重构不够的原因是单元测试不够,所以大家害怕重构。解决这个问题的办法是规划测试的原则,在后面还会提到。
- 预估膨胀可能会掩盖速度变慢的事实,一个避免预估膨胀的办法就是不断把预估时间跟锚点任务进行对比。
实际项目:
- 许多管理层并不认为速度长期应该是平稳的,而是应该越来越快的。例如团队成员的成长,工具集的优化和增加以及大家对业务的理解加深都应该让速度变快。但事实是,能保持团队速度不变就很不容易了。确实团队的磨合、成长可以让原本可能需要3天的任务在1天内完成,但是随着项目的进行,复杂度增加的速度往往大于团队能力的增加,导致综合来看速度很难保持不变。
思考:
- 对于速度的变快和变慢,都应该作为数据的一部分进行收集和分析。只有理解变化的原因,才有可能进行团队的下一步优化和管理。
测试用例
Requirements should be specified by the business.
The business writes formal tests describing the behavior of each user story, and developers automate those tests.
Acceptance tests are a collaborative effort between business analysts, QA, and the developers. Business analysts specify the happy paths. QA’s role is to write the unhappy paths. There are a lot more of them than there are of the former.
It is the programmers’ job to run the tests. It is the programmers’ job to make sure that their code passes all the tests.
观点总结:
- 测试需求应该来自于需求方。
- 需求方撰写用户期望进行的操作流程。QA 撰写错误操作流程的测试用例。QA 和程序员一起把测试进行自动化。
- QA 交付测试给开发后,由开发执行对应的测试并且保证测试通过。
实际项目:
- 要求需求方参与测试用例的撰写是很奢侈的一件事,在过去的项目中,需求方并没有时间参与。
- 研发的工资往往比测试要高,所以要求研发协助测试进行测试的自动化和执行也是一件管理层不愿意做的事情。
思考:
- 据我所知,AWS、Google 之类的海外互联网企业,测试工程师的地位和薪资与研发是不相上下的,这也解释了为什么他们的测试自动化建设这么好。我认为这是需要从上至下的支持才能达到的。
完整团队
The practice of Whole Team was initially called On-Site Customer. The idea was that the shorter the distance between the users and the programmers, the better the communication, and the faster and more accurate the development.
The goal of the practice is to minimize the physical distance between these roles. Ideally, all members of the team sit together in the same room.
Moreover, there is a huge opportunity for serendipity. An on-site customer may look over and see something on a programmer’s or tester’s screen that doesn’t look right.
Notice that this practice is counted as a business practice, and not a team practice. That’s because the primary advantages of the Whole Team practice accrue to the business.
观点总结:
- 完整团队就是把项目中的工作组和客户的物理距离尽量拉近,尽量缩短沟通成本。
- 很有可能不经意间发现他人的理解错误(serendipity)。
实际项目:
- 在过去的项目中,我并没有作为驻场长期参与过,同时由于疫情影响,有很长时间团队是处于在家办公的状态。
- 在家办公的精力可集中时间其实是比集中办公要多的,但是沟通的顺畅程度是不如集中办公的。
思考:
- 在家办公和集中办公各有利弊。
- 在实际操作中,往往存在一个矛盾即集中办公的环境不如在家办公,驻场开发的环境不如在原公司开发,所以项目组对于驻场有比较强的抵触情绪。但假设驻场环境的休息设施、办公环境、饮食都能达到比较高的标准,强力推行集中式的项目开发,是可以被项目组较好接受的。这也是 Snapchat、Github 等硅谷新秀的做法,但是这在外包型的以成本为导向的项目中可能并不现实。
- 对于初创公司,时间效率大于一切的情况下,更适合特种兵式的项目推进模式,即所有人都在一个物理区域,快速抢占时间窗口。对于成长型公司,更关注于质量、流程、成本的情况下,可能对于集中办公的需求反而不需要那么关注,而更应关注整体的效能比。
第四章:敏捷的团队最佳实践
比喻语
The idea is that in order for the team to communicate effectively, they require a constrained and disciplined vocabulary of terms and concepts. Kent Beck called this a Metaphor because it related his projects to something else about which the teams had common knowledge.
In his groundbreaking book Domain-Driven Design,2 Eric Evans solved the metaphor problem and finally erased our embarrassment. In that book, he coined the term Ubiquitous Language, which is the name that should have been given to the Metaphor practice. What the team needs is a model of the problem domain, which is described by a vocabulary that everyone agrees on. And I mean everyone—the programmers, QA, managers, customers, users…everyone.
观点总结:
- 项目中常会自然而然地出现一些 “黑话” 或者说 “比喻”,用来替代该项目中的特定的一些设计模式、需求、背景等等。这些 “黑话” 可以在项目中避免歧义,加快项目组内的沟通效率。
- 在一个项目中使用的 “黑话” 其实是领域驱动设计的一种体现,研发、测试、用户、项目经理,所有角色都用这套 “黑话” 来保证语义的精确和统一。
实际项目:
- 实际例子往往不好找,但很容易遇到。例如常见的 “garbage collection” 垃圾回收概念,其实就是 “黑话” 的一种,可以快速定位描述一个项目中的特定场景。
可持续的节奏
That was the moment that I learned that a software project is a marathon, not a sprint, nor a sequence of sprints. In order to win, you must pace yourself. If you leap out of the blocks and run at full speed, you’ll run out of energy long before you cross the finish line.
Thus, you must run at a pace that you can sustain over the long haul. You must run at a Sustainable Pace. If you try to run faster than the pace you can sustain, you will have to slow down and rest before you reach the finish line, and your average speed will be slower than the Sustainable Pace. When you are close to the finish line, if you have a bit of spare energy, you can sprint. But you must not sprint before that.
Managers may ask you to run faster than you should. You must not comply. It is your job to husband your resources to ensure that you endure to the end.
Working overtime is not a way to show your dedication to your employer. What it shows is that you are a bad planner, that you agree to deadlines to which you shouldn’t agree, that you make promises you shouldn’t make, that you are a manipulable laborer and not a professional.
This is not to say that all overtime is bad, nor that you should never work overtime. There are extenuating circumstances for which the only option is to work overtime. But they should be extremely rare. And you must be very aware that the cost of that overtime will likely be greater than the time you save on the schedule.
The most precious ingredient in the life of a programmer is sufficient sleep. Make sure you know how many hours of sleep your body needs, and then prioritize those hours.
观点总结:
- 作者用一些自身的例子说明了透支自身的精力往往会做出一些不好的技术决策,这些技术决策会导致后续花更多时间来弥补。所以透支熬夜等等操作是效率低下的。
- 软件开发就像一个马拉松,用一个稳定的速度推进的总体效率,比用阶段性冲刺透支的平均速度更快。
- 管理者可能会要求你不断加速,但是你不应该服从,作为专业的软件研发人员,是你的责任保证你能坚持到最后。
- 加班并不是一个好的用来展示忠诚度的手段。加班只能说明你没做好计划,你同意了你不该同意的 deadline ,你承诺了你不该承诺的事情,你是一个可以被操纵的劳动力而不是一个专业人士。
- 加班也不是完全不好,而你完全不应该加班。有一些情况下,加班是唯一的选择,但这种情况应该很少。而且你也应该意识到加班的副作用会大于节约的时间。
- 睡眠对于程序员来说是最重要的一个因素,你需要知道你一般睡几个小时是足够的。每缺少一个小时的睡眠,会丧失白天两个小时的高效工作时间。
实际项目:
- 所有人应该都知道加班对身体、精力的透支是会影响长期项目的整体速率的。但是在精力状态不好的情况下,做出了不好的技术决策并上线,后续的影响却不是所有人都能意识到的。不了解软件工程的管理者会把这个归结到技术能力的不足,而忽略工作状态的影响。
- 在当前的环境下,管理者都有责任提升团队的研发效能,但是研发效能一定是有上限的,那么如何判断一位成员的研发效能达到瓶颈了呢?许多管理者的方法就是看他的状态是否是精疲力尽的,只要他看起来还精神抖擞,那他就仍有潜力。这也导致了加班是让管理者认同忠诚度的手段。这其实是管理者的懒政,由于不好衡量一位成员的知识成果产出,所以选择衡量他的时间投入。
- You get what you measure. 如果管理者主要关心的是工作时间最大化,那得到的也只是工作时间最大化,而不是研发速率最大化。
思考:
- 作为打工人,对于大环境没有能力进行改变的情况下。应当有两种选择:
- 选择一个关心 impact 而不是工作时间的公司。例如微软、Google、Facebook、字节跳动 等企业文化中强调工作成果而不是工作时间的公司。在这样的公司中,我们可以自我把控工作节奏,保证长期可提高的稳定输出。
- 在一个关心工作时间的公司中,做好向上管理。即不断给你的 manager 一种你在努力工作,且接近筋疲力尽的状态,包括平时聊天、工作回复等细节中体现。于此同时在自己的工作中掌握好输出和学习的节奏。简而言之,磨洋工。
- 作为管理者:
- 加班应该作为一个双刃剑来看待。可以短期加速某些事项的完成时间,但是会遗留下未知的副作用。权衡收益之后,理性判断是否应该使用加班作为项目推进的推手。
- 非技术管理者很难对技术上的产出好坏做一个判断。在这个情况下,尝试在技术产出的衡量上做到公平公正就是一个 hard way。那么与其关注研发时间,不如关注业务上需要发展的目标,将目标作为衡量结果的手段。如果管理者中没有技术管理者,那也无法做到以技术为核心的科技公司,这并不是一件坏事,但要认清事实,摆正态度。以业务结果为导向并不是一件坏事,但自我标榜为科技公司,又无法对技术产出做出评价的,就会出现目标的涣散。
共同拥有并负责
No one owns the code in an Agile project. The code is owned by the team as a whole.
Collective Ownership does not mean that you cannot specialize. As systems grow in complexity, specialization becomes an absolute necessity. There are systems that simply cannot be understood in both entirety and detail. However, even as you specialize, you must also generalize. Divide your work between your specialty and other areas of the code. Maintain your ability to work outside of your specialty.
Each programmer owned their own modules, and no one else was allowed to touch them. These were grossly dysfunctional teams who were constantly involved in finger pointing and miscommunication. All progress in a module would stop when the author was not at work. No one else dared to work on something owned by someone else.
观点总结:
- 作者推荐所有人都对整个代码库负责,而不是指定某人负责某个部分。但这不代表不能有人在某方面深钻,对于某些大型复杂的项目,不可能有人可以同时了解所有细节,所以在这种情况下只要保证能在你深钻的方面之外也能工作即可。
- 如果是每个人都负责一个自己的模块,就很容易出现两个情况:
- 每个人都只关心自己的模块,沟通中有很多误解。出了问题容易相互甩锅指责。
- 一旦负责该模块的人请加或者有事,这个模块相关的事情就无法推进。
文中也举了一个打印机公司的例子佐证。
实际项目:
- 共同拥有主要创造的是一个合力,即沟通顺畅,责任共担,减少团队内摩擦的效果。但是需要付出的是在一些细小的任务上所花的时间变多了,多出来的时间主要是知识转移的时间。这个实践在大部分大型公司内是被认同的,我所呆过的 Bloomberg、微软都是支持跨团队间的知识分享和 inner sourcing 的。但是在大部分小型公司,或者从小型公司出来的同事中不太被认可。因为互相的知识转移会导致直接的时间损耗,同一个事情完成的时间会变长。
思考:
- 是否实施这个实践主要看管理层对沟通效率的理解。当一位成员在尝试了解他平时工作不太需要接触到的部分时,管理层的态度是:“他是不是只是好奇,想找个借口摸鱼?” 还是 “他了解这部分事情之后,就可以站在更高的角度思考问题了。“ 也决定了团队内对共同拥有这个实践的态度。
- 从分布式系统健壮性的角度考虑,其实小公司就像一个 POC 阶段的产品,可以暂时不关心健壮性,一个模块由专人负责,迭代快速。但是当公司规模扩大后,就像一个部署在多台服务器上的分布式系统,服务器宕机后的容灾、服务器间通信的效率就成了必须解决的问题,那么共同拥有这个实践也就是一个很好的解决方案,本质上就是制造冗余的缓存,使得服务器宕机后由备机可以顶上,而一部分信息的获取也可以通过缓存来加速。
持续集成
In the early days of Agile, the practice of Continuous Integration meant that developers checked in their source code changes and merged them with the main line every “couple of hours.”6 All unit tests and acceptance tests kept passing. No feature branches remained unintegrated. Any changes that should not be active when deployed were dealt with by using toggles.
The point is that Continuous Integration only works if you integrate continuously.
The continuous build should never break.
There have been teams who, under the pressure of a deadline, have allowed the continuous build to remain in a failed state.
观点总结:
- 持续集成的关键之一是要持续地提交,一旦有人长时间不和主分支合并提交,就会有大量合并冲突。
- 持续的编译不应该失败,一旦失败了就要举全队之力修复。
- 持续的单元测试失败也不应该被忽视,所有被暂时忽视的单元错误,以后也大概率不会被修复,就导致了一个系统的千疮百孔。
实际项目:
- 持续集成在实践的时候主要有三个难点:
- 持续集成所需的基础架构。在我之前主导的项目中,基础架构的搭建并不算难,毕竟现在的云服务相当完善,私有化部署环境中也有 jenkins 等开源解决方案。主要难点在于部分前端项目例如 Unity/UE4 游戏开发项目,iOS项目等,未必有完善的命令行工具支持所有的操作步骤。
- 持续集成所要求的自动化测试覆盖。持续集成的一个要求是集成的代码能保证基本的正确性,否则就会出现原来的 bug 还未解决,新的 bug 又被提交上来的情况。这就要求研发能写好单元测试或者其他的自动化测试,来保证提交的代码没有大的问题。
- 持续集成与交付时间压力之间的博弈。在生产环境出问题的时候,往往需要提交临时补丁或者更新包进行修复。这些临时补丁可能很容易就使一些单元测试失败,这时候业务方就会施压跳过失败的单元测试直接发布,而这也是潘多拉魔盒的开端,一个项目的持续集成质量也会在这些妥协的博弈中不断下降。
思考:
- 持续集成最大的好处在于:项目经理有信心,已完成的工作在下次交付的时候可以顺利打包部署。而不会出现代码 “写完了”,但是无法合并进代码库,无法打包的情况。
- 这个好处的代价是,把所有代码合并、测试的工作前置了。有的人觉得这是一种负担,每次提交代码都需要解决冲突、修复单元测试。但总的工作量其实没有变化,即使提交代码的时候不解决,后续打包发布的时候也还是需要解决的。
第五章:技术实践
这章中提到的很多时间和大部分程序员的工作方式不同,所以很多程序员倾向于不实施这些技术时间。但是这些技术时间是敏捷迭代的精髓,没有测试驱动开发、重构、简化设计等实践的话,敏捷只是一个形式空壳。
空壳案例:https://martinfowler.com/bliki/FlaccidScrum.html
测试驱动开发
Accountants are taught, in the early days of their schooling, to enter the transactions one at a time and compute the balance each time. This allows them to catch errors quickly.
Programmers who learn TDD are taught to enter every behavior one at a time—once as a failing test, and then again as production code that passes the test. This allows them to catch errors quickly.
The Three Rules of TDD
- Do not write any production code until you have first written a test that fails due to the lack of that code.
- Do not write more of a test than is sufficient to fail—and failing to compile counts as a failure.
- Do not write more production code than is sufficient to pass the currently failing test.
Benefits
- Easy ebugging
- Good Documentation
- Fun
- Test Completeness
- Testable Design
- Courage to make change
观点总结:
- 测试驱动开发就像会计记账一样,会计一笔一笔记,记完核对资产负债表帐是否是平的。这样如果记错了就会快速发现。软件研发的时候,也把每个功能一个个写,写好一个测试和代码就测一遍,这样能快速发现有 bug 的地方。
- 简化版的测试驱动开发可以很简单,首先写测试让当前的测试 fail,然后改代码让测试 pass,往复循环。把颗粒度拆细到 compile 不通过也算测试 fail。
- 测试驱动开发有很多好处,包括:
- 很容易 debug,因为每个循环的时间就几分钟,所以让测试 fail 的原因一定是这几分钟内的修改,范围小,容易排查。
- 测试本身就是活文档,而且这个文档本身是跟着代码不断更新的。
- 有趣。写测试的过程就像设计一个关卡,而写代码通过测试的过程就像是通关的过程,是一个充满正反馈的循环。
- 测试用例会很完善,因为每写一段代码都会有对应的测试,每个异常都会有异常捕获的测试。
- 整体设计是松耦合,可测试的。因为需要先把测试用例设计好才做实现,所以可测试性会更强。
- 最重要的是,在需要清理旧代码、改别人代码的时候,会更有勇气,因为我们可以相信测试用例只要都通过了,就是 OK 的。
实际项目:
- 这个实践在实际项目推进中其实有挺多难点的:
- 项目早期测试设计带来的额外时间成本。早项目刚开始时,可能会需要写很多项目基础性的代码,例如数据库连接、数据结构定义等等,这些代码本身的实现很简单,但是写测试的时间往往与实现他们相同。所以会带来额外的时间成本,而管理团队往往不能接受这个时间成本。
- 开启一个新项目的机会不多,很多时候往往是在旧项目上做修改,而旧项目的架构设计对于可测试性的考虑不多,导致了为了写一个新功能的单元测试,可能需要先对 20% 的项目进行重构,并补充重构的单元测试。这对业务方来说也是不可以接受的。
- 在之前的项目中,我们采取了折衷的方案,对于关键的业务逻辑进行大量单元测试的覆盖。对于难以 mock 的部分进行手动测试的覆盖,并对于稳定需求进行自动化集成测试。对于大部分的业务需求修改,单元测试已经可以帮助研发有勇气进行快速清理和修改了。
思考:
- 我还没有机会尝试过完整的 TDD,不过从过去的经验中,单元测试的帮助是毋庸置疑的。我会在后续的 side project 中尝试以 TDD 的形式进行开发,再回头补充这部分的感想。
重构
The process of refactoring is woven intrinsically into the Three Rules of TDD in what is known as the Red/Green/Refactor cycle.
- First, we create a test that fails.
- Then we make the test pass.
- (Refactor) Then we clean up the code.
To say this differently, it is hard enough to get code working, let alone getting the code to be clean. So we first focus on getting the code working by whatever messy means occur to our meager minds. Then, once working, with tests passing, we clean up the mess we made.
We do not reserve time in the schedule for such large refactorings. Instead, we migrate the code one small step at a time, while continuing to add new features during the normal Agile cycle.
观点总结:
- 重构并不是一个一次性的大动作,而是贯穿在研发中的正常步骤。按照 TDD 的步骤,我们先写一个测试用例,这时候测试 fail,然后再写代码让测试 pass,最后重构使代码简介漂亮。
- 对于一些涉及面较大的重构,我们也不会一次性预定几天、几周甚至几个月来进行,而是会把重构拆成小的步骤,和其他的功能迭代一起进行,在这期间,测试仍然可以通过,系统也仍然可以部署交付。
实际项目:
- 在过去的项目中,小型的重构往往是程序员自发进行的,但是对于需要较多时间的重构,往往是单独排期进行。这个主要是由于程序员不知道如何在不影响当前系统的情况下进行渐进重构。
思考:
- 重构的颗粒度拆分是这个循环过程中的关键,一次性重写大段的代码简单,但是把重构拆成不影响单元测试的小代码相对而言就很难,也很考验程序员的设计功底。
简化设计
The practice of Simple Design is one of the goals of Refactoring.
Kent Beck’s rules of Simple Design are as follows:
- Pass all the tests.
- Reveal the intent.
- Remove duplication.
- Decrease elements.
观点总结:
- 简化设计是重构的目标之一。
- 简化设计有几个标准:
- 需要能通过所有测试。
- 代码自身能表达代码的意图,例如好的命名、结构、注释等。
- 没有重复代码。
- 尽量减少代码元素,减少类、方法、变量的数量。
思考:
- 这个在 Clean Code 代码整洁之道中已经阐述很多了。
结对编程
First of all, pairing is optional. No one should be forced to pair.
Pairing programmers sometimes adopt different roles. One may be the driver and the other the navigator. The driver has the keyboard and mouse; the navigator takes a longer view and makes recommendations. Another role option is for one programmer to write a test, and the other to make it pass and write the next test for the first programmer to pass. This is sometimes called Ping-Pong.
Pairs are generally short-lived. A pairing session can last as long as a day, but more often they last no more than an hour or two. Even pairings as short as 15 to 30 minutes can be beneficial.
The goal is to spread and exchange knowledge, not concentrate it.
Indeed, many teams have replaced code reviews with pairing.
Various studies have indicated that the direct cost might be about 15%.
观点总结:
- 结对编程其实不是一个新事物,但也不是一个强制的要求。可以一个人写代码一个人看,也可以一个人写测试一个人写实现。
- 结对编程的时间一般都不长,从十几分钟到几个小时左右。
- 结对编程的目标是让知识可以更好地在团队内传播。
- 有的 team 用结对编程替代了代码评审。
- 结对编程可能会导致解决一个问题所花的时间上升 15%。
实际项目:
- 结对编程的出现往往是自发的,例如 Junior 的程序员有问题解决不了, Senior 的程序员在帮助的时候就出现的结对编程。
- 对于我来说,许多高效的学习和知识传递都发生在结对编程的过程中,在我第一任老板边上看他排查问题、读代码、读日志、撰写邮件等等的过程中,学到了很多难以在书本上学到的细节知识。
- 我也很乐意鼓励团队内的成员进行结对编程,主要是鼓励新成员多问问题,鼓励老成员在被问问题的时候多用结对编程的方式教导。
思考:
- 结对编程的好处有挺多的,但实践起来主要有两个难点:
- Junior 的程序员可能会不好意思问问题,怕问问题会让自己显得菜。这个主要需要做一些心理建设,放下心理负担才能更好成长。
- Senior 的程序员会担心花许多时间在结对编程会降低产出。知识的传递一定是会消耗一部分额外精力的,所以这个主要靠管理层的支持。
- 对于大部分 team,自发的结对编程往往是性价比最高的。所以大家可以不用干预这类行为。
第六章:落地敏捷
推行落地敏捷是非常苦难的,也许最主要的原因是很多组织想错了敏捷的真正含义。敏捷的价值是:勇气、沟通、反馈、简洁。
敏捷提供的价值
Courage: a reasonable degree of risk-taking. Communication: We value direct and frequent communication that crosses channels. Feedback: The Agile disciplines we have studied are virtually all geared toward providing rapid feedback to the folks who make important decisions. Simplicity: The next Agile value is simplicity—in other words,being direct.
观点总结:
- 勇气:勇气不是鲁莽。在只完成了 MVP 的情况下部署发布是需要勇气的,但是未经测试而发布是鲁莽的。
- 沟通:敏捷鼓励面对面、多渠道的沟通,敏捷的实践也是为了能让沟通自然而然地发生而提出的。
- 反馈:许多敏捷的实践是为了能尽快地给决策者提供反馈而制定的。
- 简洁:简洁不光是代码的简介,还有组织架构、文化的简洁。
实际项目:
- 在之前的项目中,发布 MVP 的人往往需要承受 MVP 失败的后果,所以一次两次以后,就没人愿意拍版发布了。但却有许多决策者愿意发布未经测试的软件,只为了能不被苛责项目的延期。
- 在过去的项目中,我们可以快速地反馈,但是决策者并不能正确地对待反馈。对于延期、范围扩大等反馈,往往是以牺牲质量或者加班为最终结局的。
- 简洁的代码是相对容易实现的,但简洁的组织架构却不行。信息的不透明和各方相互的揣测都是企业文化上带来的阻碍。
思考:
- 敏捷提供的价值很好,但是是否能落地实施,要看这个企业的文化是否是开放、务实的,而企业文化不是靠说出来的,是靠做出来的。如果企业文化并不能接纳敏捷,那么敏捷提供的价值只是表面的形式罢了。
转型成为敏捷
The transition from non-Agile to Agile is a transition in values. The values of Agile development include risk-taking, rapid-feedback, intense, high-bandwidth communication between people that ignores barriers and command structures. They also focus on moving in straight and direct lines rather than mapping out and negotiating the landscape. These values are diametrically opposed to the values of large organizations who have invested heavily in middle-management structures that value safety, consistency, command-and-control, and plan execution.
Can Agile teams exist in an organization with a strong middle-management layer that opposes Agile? I have seen this happen upon occasion. Some software development teams quietly use Agile values to drive their development, while also conforming to the rigors imposed upon them by middle management. So long as middle management is satisfied that their procedures and standards are being followed, they may leave the development teams to their own devices.
It is not uncommon to see small organizations transition completely to Agile. They have no middle management, and the values of the executives and developers are strongly aligned.
观点总结:
- 敏捷所推崇的价值观例如冒险、快速反馈、高密度无阶级的沟通。而这些价值观与大公司的中层管理结构所推崇的安全、可持续、令行禁止是相左的。所以在大公司推行敏捷最难的是中层的不支持。
- 在一些大公司也有成功落地敏捷的,即一部分团队用敏捷来进行自我管理,但同样做好向上管理,向中层领导着提供他们需要的交付物。
- 在小型组织中落地敏捷相对简单,因为研发和CEO的目的是一致的,小型组织中没有中层。
实际项目:
- 我对中层的固化感触不是很明显,也许是在职业生涯中还没有过大公司中需要对中层进行向上管理的经历。不过对于小型团队,接受敏捷的速度是比较快的,毕竟没有繁文缛节,只要上下都对这个理念认同,就很容易推行下去。
敏捷的迁移
In the best case, the individuals who make the transition will join to form new Agile teams that manage to hide from middle management. If that’s not possible, they will likely seek (and find) employment at a company that shares their values.
Indeed, over the last twenty years, we have seen this migration of values taking place in the industry. New companies that embrace the Agile values have been formed, and programmers who desire to work in an Agile manner flock to those companies.
We will eventually see larger companies create new divisions that use Agile for their software development. We will also see Agile consulting companies used more and more by larger organizations that have been unable to transform their existing development staff.
观点总结:
- 对于接纳了敏捷的个人来说,他们会尝试加入新成立的敏捷团队,并隐藏在中层的管理下。如果没有条件的话,他们会跳槽去其他有条件的公司。
- 在过去的20年里,有不少新公司接纳了敏捷的文化并且工程师倾向于在那工作。
- 大公司也可以有敏捷的文化,但那往往是重新成立的部门,而不是从原有的部门转变过去的。
思考:
- 目前大部分公司的敏捷还是停留在比较表面的程度,开个站会就算敏捷了。但我也确实看到类似字节跳动这样宣传务实、直接文化的公司在招聘方面有不少优势。
敏捷培训
Does an Agile team need a coach? The short answer is “No.” The longer answer is “Sometimes.”
First, we need to differentiate between Agile trainers and Agile coaches. An Agile trainer teaches a team how to conduct themselves in an Agile way. They are often hired from outside the company or are internal trainers from outside the team. Their goal is to inculcate the Agile values and teach the Agile disciplines. Their tenure should be short. Each team of a dozen or so developers should require no more than one or two weeks of training. Everything else they need to learn they’re going to learn by themselves no matter what the Agile trainer says or does.
In general, Agile coaches are not trainers. They are members of the team whose role is to defend the process within the team. In the heat of development, developers may be tempted to go off process. Perhaps they inadvertently stop pairing, stop refactoring, or ignore failures in the continuous build. It is the coach’s job to see this and point it out to the team. The coach acts as the team’s conscience, always reminding the team of the promises they made to themselves and the values they agreed to hold.
In Scrum, the coach is called a Scrum Master.
Nowadays, it is all too frequent that we see Scrum Masters who are not coaches at all but are simply project managers doing what project managers always did.
观点总结:
- 敏捷不需要专门的长期的培训师,只需要一个短期的培训师。短期的培训是让团队了解敏捷的基本原则。
- 长期的培训师的角色应该由团队内的成员来担任,主要职责是捍卫敏捷的原则。在研发压力大的时候,团队可能会倾向于不遵守敏捷的原则,这时候应该有人跳出来说 “这是不对的”。
- Scrum Master 就是长期的培训师,敏捷的卫道者。但目前的情况下,大部分的Scrum master 都是项目经理,他们只是在做项目经理应该做的事。
实际项目:
- 在我过去参与过的团队中,有的组织过一两天的 scrum 的短期培训,然后就由一位团队内的成员担任 scrum master,但是 scrum master 的职责也仅停留在组织站会等流程性事务上,没有深入到研发的最佳实践中。
- 对于临时组建起来的团队,每个人的背景不同,对敏捷的理解不同,就导致了草草开始敏捷流程,但只有一个敏捷的表象,大家对流程定义的站会、迭代、估时等都没有达成共识。其实这时候是很需要一个短期的敏捷培训的。
思考:
- 一个短期的培训师是很有必要的,好的培训师可以让团队意识到敏捷的优势,以及对当前工作内容痛点的解决。只有痛点足够痛,才能让大家明白这样做的意义是什么。
- 一个长期的培训师(Scrum Master)一定是对敏捷的原则十分认同的人,否则对于测试、质量、沟通等等方面就不会秉承初心,也就很难彻底推行下去。
敏捷认证
The Agile certifications that exist are a complete joke and an utter absurdity. Do not take the certifications seriously.
What would a real Agile certification program look like? It would be a semester-long course, complete with Agile training and the supervised development of a small Agile project. The course would be graded and the students held to a high bar. The certifier would guarantee that the students understood Agile values and showed proficiency in executing Agile disciplines.
观点总结:
- 敏捷的证书没什么用。
- 真正敏捷的认证应该是至少一个学期的课程,完成一个小的敏捷项目,并且有一个较高的评分标准,从而保证能专业地执行敏捷原则。
实际项目:
- 我接触的敏捷培训师看起来是只上了几天敏捷的培训课,但没有做过实际开发的,所以程序员在上敏捷的培训课的时候,也并没有被吸引的感觉。
思考:
- 没有经历过项目研发痛苦的“纯培训师”是不能理解项目成员的痛点的,没有理解痛点,那所教授的内容也就只是一知半解的搬运罢了。
大型企业中的敏捷
Agile is for small- to medium-sized teams, period. It works well for such teams. Agile was never intended for large teams.
Large teams are a solved problem.
Agile is the set of disciplines by which we organize small software teams.
观点总结:
- 敏捷是针对于小型软件团队的一系列原则,它只在小团队里好用。
- 大团队的管理已经有方案了,类似军队、企业、政府的管理都相似。
思考:
- 我并不认同这一观点,大团队的管理并不是直接把大拆小就完事了,团队之间的合作、沟通一样也是需要解决的问题。而软件工程中的合作、沟通也与军队、政府不同。但为了解决这个问题,也需要有同等的实践才行,也许作者对大型组织管理没有足够深刻的认识,所以认为这是一个已解决的问题。
敏捷的工具
引自 Tim Ottinger and Jeff Langr, April 16, 2019,非作者观点。
Regardless of whether they use hand or power tools, carpenters always seek to master each implement they choose for their toolbox.
Agilists are known for using whiteboards, tape, index cards, markers, and various sizes of sticky notes (small and flip-chart-size) for visual management of their work.
These Agile Lifecycle Management (ALM) systems, ranging from open source to polished and expensive “shrink-wrapped” products, allow you to collect Agile team data, manage long lists of features (backlogs), produce sophisticated graphs, provide cross-team summary views, and do some numerical processing.
Yet, despite being feature rich and commercially successful, ALM tools utterly fail at being great.
观点总结:
- 工具是为了完成事情所服务的。
- 敏捷的推行者一开始用的是白板、数字卡片、马克笔、便利贴来执行的流程。这个流程容易上手、可视化强、不需要花很多额外的经历。
- 后来推出的很多敏捷生命周期管理工具(ALM),能提供很多功能,包括图标、计算等等。但是 ALM 不好用,他们的学习难度大,用户看不明白,用户不知道怎样完成一件事。
实际项目:
- 在我过去的项目中,没有经历过原始的卡片、白板流程,基本都是用 jira 作为管理工具。确实学习难度大,会制造很多不必要的认知障碍。
思考:
- 所谓在对的时候用对的工具。如果对敏捷一无所知,从头开始的话,用白板、数字卡片、便利贴是最容易上手的。但是如果进行了一段时间,大家已经度过了最开始的认知障碍,那么再迁移到软件平台也不会有很多障碍了。
- 所谓工具的复杂、上手难,主要是在于短时间有太多新的信息呈现于用户面前,用户不知道从何入手罢了。我认为这不是工具的错,而是使用工具的人的错,例如没有配置好一个最简单的流程,没有在建立团队对流程的理解之前就推行工具。最理想的情况可能是先用白板等原始工具熟悉流程,再用配置好的软件优化流程中耗时的部分。
敏捷培训(Damon 的看法)
引自 Damon Poole, May 14, 2019,非作者观点。
The concept of Agile is simple. It is described in a mere 264 words in the Agile Manifesto. But becoming Agile is hard. If it was easy, everybody would already be doing it and there would be no need for Agile coaches.
A truism of all change initiatives is that people do what they want to do. The key to lasting change is to find problems or opportunities that people are aware of and have a desire to invest in and then help them achieve their goals, offering expertise only as requested and needed. Everything else will fail. Coaching helps people discover the blind spots and surface the underlying beliefs that keep them from moving forward. It helps people to solve their own challenges and reach their own goals rather than just prescribing a solution.
观点总结:
- 敏捷的培训是有必要的。否则敏捷宣言只是 264 个单词,大家看完不就会了吗。
- 敏捷培训的关键点是,找到一个痛点,并让大家有动力去解决它,然后只在大家遇到困难的时候提供帮助。此时提供的解决方案才能被长久地执行下去
实际项目:
- 在项目中,有一些痛点并不是所有人都能感受到的。例如沟通障碍,可能只存在于某几个人之间,此时如果我们引入敏捷的站会,可能可以解决小范围的沟通障碍,但并不一定能被所有人都认同。
思考:
- 对于痛点不够痛的人来说,引入的方法或者解决方案可能就只停留在表面。此时我认为有两种解决方法:
- 让他们感受到对应的痛。例如创造一个类似的场景,让他们体会其他人的困难,这个困难可以是估时、沟通、测试等等。
- 在实施方法的时候,对方法进行调整,例如部分人觉得站会没有任何帮助,那么就排除在外。
第七章:工匠精神
敏捷宿醉
Selling Agile processes to middle managers was an easy sell—they all wanted software to be delivered faster. “Engineering is the easy part. If we fix the process, engineering will be fixed,” managers were told. “It’s always a people problem.” And they bought it. Managers manage people, and as long as they are in charge, they are happy to have their direct reports working faster.
Managers willing to push developers to work faster are using the full transparency of the process to micromanage them.
Roadmaps and milestones are being defined by managers and forced upon development teams—developers can estimate the work, but they are pushed hard to fit their estimates into the imposed milestones. It is fairly common to see projects that have all their iterations and respective user stories already defined by management for the next 6 to 12 months. Failing to deliver all story points in a sprint means developers must work harder in the next sprint to make up for the delay. Daily standup meetings become meetings where developers must report progress to product owners and Agile coaches, detailing what they are working on and when they will be done. If the product owner thinks developers are spending too much time on things like automated tests, refactoring, or pairing, they simply tell the team to stop doing it.
This approach results in a long sequence of iterative tactical work and accumulation of technical debt.
That is what we call the Agile Hangover. After years of investment in an Agile transformation, companies realized that they still have many of the problems they had before. And Agile is being blamed for that, of course.
观点总结:
- 所谓的敏捷宿醉,就是公司在落地敏捷的过程中,只落地了敏捷的流程,但是没有落地敏捷的工程实践,也没有真正理解敏捷的目的。常见的情况包括:
- 利用敏捷的全透明精神来做微管理的途径。
- 项目的里程碑在工程师预估工作量之前就已经定下了,工程师被迫预估一个能匹配到里程碑的预估量。
- 项目未来6-12个月的迭代和用户故事已经规划好了。
- 如果无法再规定时间内交付所有的用户故事,意味着工程师还不够努力,要在下一个迭代中补上。
- 每日站会变成了工程师汇报工作进度的会议。
- 如果领导认为在重构、自动化测试上花了太多时间,会要求停止。
- 敏捷因此成为公司甩锅的对象。
实际项目:
- 我作为上一个项目的项目经理、负责人,不得不说犯了许多敏捷宿醉中的问题:
- 项目的交付时间是在合同中确定的,如果无法按时交付,则有违约惩罚。这就导致了敏捷的预估和迭代无法按照原计划进行,只能从 deadline 往回倒推每一个时间点需要完成的事情。时间在那个项目中是最重要的因素。但即使这样做,也仍然延迟了交付时间,因为一个质量不高的交付物,是无法被客户接受并使用的。
- 每日站会原本是希望成为工程师间交换进度和信息的地方,但是领导的参会使得会议的意义变了,变成了向上汇报的会议。
- 如果无法再规定时间内交付所有的用户故事,无法分辨是由于工程师不够努力还是由于预估不准确导致的。
思考:
- 在商业上,客户希望尽快交付,而在工程上,没有完成所有工作前,无法准确预估所需要的时间。这就导致了一个先有鸡还是先有蛋的问题。如果希望把敏捷落地到项目管理中,那么有几个关键点需要把握的:
- 在商业谈判时,需要对交付预留一定的时间缓冲,或者评估好可能由于延期导致的经济损失,避免做一单亏一单。
- 在项目管理中,敏捷的优势在与产品质量、客户的满意度和客户的响应速度,而劣势在于对于项目范围的把控,所以需要与客户沟通好变更流程,同时做好项目范围变更导致的商业条款的变更。 在做好这两点的基础上,可以一定程度上避免 deadline 和工程师预估的冲突。
- 如何看待工程师未完成迭代中的任务:这其实本质上是工程师绩效的评估是否与迭代挂钩。脑力劳动的绩效的评估一直都是很困难的事情,因为不是所有脑力劳动都可以直接转化为商业价值,同时一个任务的难度也不好在事前预估准确。我认为从一个透明的基础上出发,由工程师提出任务未完成的原因,是预估不准,还是遇到了其他困难,以供参考。长期迭代的情况下,每个人的预估/产出比例会达到一个平衡点,此时不难通过产出来评价一位工程师。
- 每日站会的意义:我认为这是一个快速同步信息的平台,但这个机制的最大问题在于对无效信息的过滤。很多团队成员不会认真听,因为大部分信息是与自己无关的,所以导致一个行为惯性,到了站会就只管讲,不管听。这便使得站会没有什么意义。我认为可以改进一下,每个人站会前先提交一个表格,说自己关心的事情有什么,相关的人就可以针对性讲一下。如果长期下去没有人提交关心的事情,说明团队内还没有形成透明沟通的氛围。
预期错位
Agile transformations that purely focus on process are partial transformations. While Agile coaches try to guide managers and delivery teams through the Agile processes, there is no one helping developers learn Agile technical practices and engineering. The assumption that fixing the collaboration among people would improve engineering could not be more wrong.
There is a big expectation that comes with Agile adoption: development teams should deliver production-ready software as soon as a feature is done, or at the least at the end of each iteration
Releasing software to production every two weeks requires a lot of discipline and technical skills—skills that are not commonly found in teams used to delivering software a few times per year.
It is not realistic to think that teams will develop these skills simply by creating a more collaborative environment. Teams need support in acquiring these technical skills.
观点总结:
- 只关注流程的敏捷是一个只做了一半的敏捷转变,大部分敏捷培训师只关注流程,而忽视了敏捷所需要的技术和工程能力,大家认为只要流程对了,工程能力自然而然就会了,但事实并非如此。而且工程能力的提高是需要有对应的预算的,工程师要花额外的时间进行学习和练习,但往往业务方不会给工程师这样的机会。
实际项目:
- 在过去的项目中,新人往往更能成为合格的敏捷开发者,原因其实也是新人有更多时间学习工程能力,例如单元测试、需求拆分等等。而老员工迫于过去工作效率的锚定,如果产出变少了,则会受到公司内绩效考核的苛责,就不愿意改变和尝试工作方法了。
思考:
- 敏捷的投入最大的难点在于产出无法量化。例如每位工程师投入 20% 的时间实践敏捷的工程方法,但能提供多少额外的收益,这对于业务方来说是很难理解和量化的。所以在落地敏捷之前,业务方和工程方需要对这件事达成一定的共识。
社区分裂-软件工匠精神
Over the years, developers started seeing Agile coaches as another layer of management: people telling them what to do instead of helping them to get better at what they do.
It seems that Agile and developers are moving away from each other.
To raise the bar of professional software development and re-establish some of the original Agile goals, a group of developers met in November 2008 in Chicago to create a new movement: Software Craftsmanship.
We will look at our work not as something we need to do as part of a job but as a professional service we provide. We will take ownership of our own careers, investing our own time and money to get better at what we do. These values are not only professional values—they are personal values. Craftspeople strive to do the best job they can, not because someone is paying, but based on a desire to do things well.
http://manifesto.softwarecraftsmanship.org/#/zh-cn
观点总结:
- 在过去的几年里,由于敏捷培训和公司内推广敏捷的过程中,越来越多的人只关注流程而忽视工程实践,有部分工程师就从敏捷社区中脱离了出来,组成了软件工匠精神的社区。
- 软件工匠宣言:http://manifesto.softwarecraftsmanship.org/#/zh-cn
- 软件工匠的宣言在上面的链接中可以看到,最主要的内容,就是将软件工程看作是一个精益求精、不断更新的作品,而不仅仅是为了工资而交付的一个任务。
软件工匠精神的实践方法
Software Craftsmanship does not have practices. Rather, it promotes a perpetual search for better practices and ways of working. Good practices are good until we discover better ones to replace them.
On the contrary, since its creation in 2008, the Software Craftsmanship community considers XP the best set of Agile development practices currently available. TDD, Refactoring, Simple Design, Continuous Integration, and Pair Programming are heavily advocated by the Software Craftsmanship community. It promotes small commits, small releases, and Continuous Delivery. It promotes modularity in software design and any type of automation that removes manual and repetitive work. And it promotes any practices that improve productivity, reduce risk, and help to produce valuable, robust, and flexible software.
观点总结:
- 软件工匠社区本身不包含实践方法,但是它推广一些社区认为好的方法,并且当有更好的方法出现时,会用新的实践替代旧的实践。
- 在2008年社区成立的时候,极限编程(XP)的实践被认为是最好的实践,包括面向测试开发,重构,简化设计,持续集成,结对编程等等。
实际项目:
- 有许多实践在我们的项目中都落地实施了,包括简化设计、持续集成等等。也确实有不少好的反馈。
落地推广实践
A common mistake in the Agile and Craftsmanship communities is to promote practices instead of the value they provide.
The problem here is that we are offering a solution before agreeing on the problem. People will not change the way they work if they do not see the value.
Agreeing first on the goals to be achieved is essential when discussing practices. The only thing that should not be acceptable is to reject a practice without providing a better alternative.
The discussion around practices should be done at the right level and with the right people. If we want to adopt practices that improve the collaboration between business and technology, people from business and technology should be involved in the discussion. If developers are discussing practices that would enable them to build systems in a better way, there is no reason to involve businesspeople. Business should only be involved when there is a significant impact in the cost or duration of the project.
观点总结:
- 一个常见的错误是推广实践的时候,目标是让别人做一件事,而不是提供给别人价值。如果不能给别人提供价值,那么其他人就不会有意愿做出改变。
- 在落地实践的时候,如果不会对业务方有重大影响的话,业务方不应该对这个过程发表意见。
实际项目:
- 在过去的项目中,我遇到的困难主要不是说服他人,而是业务上直接的时间和经济压力。由于我作为技术的负责人,在推广敏捷实践的时候,不可避免会在短期影响业务的交付速度。这时候若是没有对比,则不会看出敏捷实践对于长期质量和迭代速度的提升,也就不可避免地需要面对业务方的质疑。这大概是创业团队特有的问题吧。
思考:
- 对于有明确过去成效对比的团队,例如有明确的迭代实践,测试实践,bug 率记录的团队,可以针对提升某一个维度的价值,提供敏捷中对应的方法,从而证明该方法的有效性并推行下去。
- 对于从头开始的团队,也许独裁的方式是最好的,总要有人做第一个吃螃蟹的人,并且承担对应的责任。
- 如果技术团队所做的事情不会对业务方有影响,自然业务方不会参与进来,但是落地敏捷的一个重要变化就是把成本前置了,例如测试和修复 bug 的成本被前置到了单元测试的撰写过程中,编译和配置的 bug 处理成本被前置到了持续集成的过程中。对于业务方来说,他们的直接感知就是,虽然bug率少了,但是实现功能所需要花的时间变长了,那么也不可避免地会质疑这个流程。敏捷的推行者仍然要准备好对应的数据来阐述敏捷的工程实践所带来的好处。
全书总结
疑问解答
由于我是带着疑问来看这本书的,也就着疑问来回顾这本书。
疑问1: 为什么直观感受上敏捷没有带来效率上的提升,每个时间周期内能做完的事情或者需求还是那么多?
回答1: 敏捷的目的不是提高研发的速度。敏捷可以给项目管理提供更及时的反馈,给客户提供更多调整目标的机会,提供更有效的资源利用率,但不会直接提高需求的完成速度。同时由于敏捷前置了许多时间和机会成本,所以在外界看来,可能反而效率还会有所下降。
疑问2: 为什么项目仍然会一直 delay?
回答2: 因为没有对变更流程做好管理。敏捷的精神是接纳变更,而在过去的项目中,合同中没有针对变更的说明的流程条款。所以就出现了项目目标是定死的,但是需求是不断迭代变化的这样一个奇怪的处境。
疑问3: 每日站会的目的是什么?为什么研发在站会时都心不在焉,而且不愿意开?
回答3: 站会的目的是一个快速的信息交流通道。这个在书中并没有过多提到。我个人认为原因主要在于研发没有意识到信息交流的重要性,所以在落地这个形式的时候,研发其实并不愿意改变。
我在过去对敏捷的理解主要也是来源于敏捷培训师在 Bloomberg 时的。所以在创业公司中推行敏捷实践的时候,也是一知半解,只推行了流程,也就解释了为什么推行了敏捷但仍然有诸多问题。
后续阅读
在书中作者也提供了一些针对敏捷的参考书籍:
- Agile Project Management: Creating Innovative Products
- Extreme Programming Explained: Embrace Change
- Refactoring: Improving the Design of Existing Code