死亡,孤单的感觉,同时,是对生命的疯狂渴望……您可能会认为我们决定举办有关表现主义的演讲,让您沉浸在蒙克的作品中。 但是没有 当您看到技术债务将很快将您的公司推向危机的深渊时,您正在经历所有这些阶段。

八年来,Dodo Pizza IT团队已从为一个国家/地区服务的2名开发人员成长为为12个国家/地区服务的80人。 三年前,我加入Dodo Pizza,担任首席敏捷官,并开始帮助团队创建流程和实施工程实践。 通常,这些实现速度太慢。 另外,发现当多个团队使用同一产品时,很难使他们维护高质量的代码。
我们追求业务功能的开发,将代码的技术完善推迟到以后。 所以我们被困了。 巨大的技术债务使我们over起了拳头,但并没有压倒它,只是在我们的指尖挥霍下,我们的公司就陷入了危机的深渊。 在2018年,营销团队发起了大规模的广告活动,我们无法承受重负。 丢脸,丢脸,丢脸。 但是在危机期间,我们意识到我们可以提高工作效率很多倍。 这场危机迫使我们迅速实施最著名的工程实践并革新了流程。
背景知识
渡渡鸟披萨(Dodo Pizza)是一家出售披萨的机器人公司 。 我们的业务基于Dodo IS平台,该平台管理所有业务流程:接收订单,制作比萨饼,管理库存,管理人员(管理)等等。 在短短的8年中,我们已经从为一个比萨饼店提供服务的2个开发人员成长为在12个国家/地区为498个比萨饼店提供服务的80多个开发人员。
三年前,Dodo IS是一个包含100万行代码的整体。 单元测试的内容很少,根本没有API / UI测试。 代码本身的质量令人失望。 每个人都知道这一点,或者至少是猜测。 为了实现更美好的未来,我们将整体设备分成了十几个服务,并重写了系统中最令人讨厌的部分。 我们甚至绘制了“未来”架构的示意图,但是坦率地说,它并没有做任何事情来使其更接近它。
团队越成长,缺乏清晰的流程和工程实践就会给我们带来更多的痛苦。 由于六个开发团队同时在不同分支中进行更改,因此发布变得越来越多。 当团队将更改合并到一个分支中时,我们有时会花费多达4个小时来解决合并冲突。 没有自动回归测试,对于每个版本,我们在人工回归上花费了越来越多的时间。
狗屎发生
2018年,营销团队启动了首个联邦电视广告活动,预算为1亿卢布。 对于渡渡鸟披萨来说,这是一个了不起的事件。 IT团队也为竞选做好了充分的准备。 我们已经自动化并简化了部署-现在只需在TeamCity中单击一个按钮,便可以在12个国家/地区部署整体。 使用性能测试,我们进行了漏洞分析。 我们尽了最大努力,但无论如何还是搞砸了。
广告活动非常了不起。 我们每分钟收到100到300份订单。 那是个好消息。 坏消息是:渡渡鸟IS无法承受如此重的负荷而死。 我们达到了垂直扩展的极限,无法再处理订单。 系统每3小时重启一次。 每分钟的停机时间造成我们成千上万卢布的损失,这还不包括生气的顾客所造成的尊重。
三年前到达Dodo Pizza时,我立即开始实施工程实践。 大多数团队很快就采用了结对编程,单元测试和DDD。 但是,并非一切都那么简单。 我必须克服开发人员,产品和支持团队的阻力。
与工程实践的想法不同,起初并不是每个人都支持功能团队的想法。 开发人员习惯于以专注于一个组件的团队编写最佳代码。 尚不清楚如何将业务功能的快速发展与早就应该进行的复杂系统大规模重构相结合。 此外,这种无休止的错误源源不断地引起人们的关注……我们每周发布产品不超过一次,并且每次发布都花费了很多时间,它需要大量的手动回归和对UI测试的支持。 我试图修复它,但是过程更改太慢且分散。
兴衰的故事
初始状态:整体架构
为了追求业务功能的发展速度,我们并不总是通过技术解决方案来进行思考。 受缺乏经验的影响。 我们有一个带有一个数据库的整体应用程序,该数据库在一个地方包含所有组件的所有数据。 跟踪器,会计,网站,登陆页面的API-系统的所有组件只能使用一个数据库,这是一个瓶颈。
真实的故事
整体架构很容易入手,因为它很简单。 但是它不能承受高负载,这是唯一的故障点。 一旦我们所有在俄罗斯的餐馆都因博客帖子而停止接受订单。 怎么会这样
我们的首席执行官Fedor在他的博客上发布了一条帖子。 这篇文章很快获得欢迎。 Fedor的博客网站上有一个计数器,显示我们网络中的比萨店数量以及所有比萨店的总收入。 每当有人阅读Fedor的博客时,网络服务器都会向主数据库发送请求以计算收入。 这些请求使数据库超负荷,以至于它停止处理来自餐厅收银台的请求。 我们很快解决了问题,但这是我们的体系结构无法满足业务需求并应重新设计的众多迹象之一。 但是,我们继续忽略这些迹象。
2017年初崩溃
2月14日。 对于2月14日恭喜的人,我们制作了一个特别的披萨-心形的意大利辣香肠。 我永远记得2017年2月14日,因为在这一天,所有比萨店都在满负荷工作时,Dodo IS开始倒塌。 每个比萨店都有4到5片用于生产管理的药片:比萨饼制造商以什么顺序将面团压成卷,放入配料,烘烤或将其发送出去。 当时,比萨店的数量达到150多家,每片每分钟更新一次。 所有这些查询在数据库上造成了巨大的负担,以致它无法承受并开始失败。 Dodo IS在销售高峰期间去世。 但是即将到来的假期很忙:2月23日,3月8日,5月1日和9日。 在这些假期中,我们预计订单将进一步增长。
你死的那一天。 了解了我们的增长计划和我们可以承受的负载极限后,我们发现了可以存活多长时间。 预计世界末日的估计日期大约为六个月:2017年8月至9月。知道您的死亡日期,生活如何?
停止功能开发一年。 我们必须与首席执行官Fedor一起做出艰难的决定。 也许是公司历史上最困难的决定之一。 在接下来的一年中,我们仅做了一项业务功能。 其余时间,团队还清了技术债务。 这笔债务使我们付出了沉重的代价-仅开发商的工资就超过了1亿卢布。
一年后有所改善
一年来,我们取得了显着的增长:
- 我们将部署过程自动化并加速到4-5小时
- 最终,我们开始看到了巨石:将跟踪器和电视面板移到具有其自己的数据库的单独服务中
- 我们开始将交付的收银台分开-这是造成高负荷的第二个要素
- 重写了用户和设备认证系统
看来我们可以为自己感到骄傲。 但是,摆在我们面前的是巨大的失望。
联邦广告战期间失败。 第二次信任危机
技术债务很容易积累,但很难偿还。 您不太可能事先知道要花多少钱。
尽管我们整整一年都在为技术积压而苦苦挣扎,但我们还没有准备好进行大规模的营销活动,因此又重新陷入了业务困境。 一滴一滴地赢得的信任消失了。
在联邦营销运动的重压下,我们再次躺下。 系统再次崩溃,每3小时重新启动一次。 我们的生意损失了几千万卢布。

由于这场危机,我们了解到,在极端条件下,我们可以提高工作效率很多倍。 我们每天被释放20次。 所有人都作为一个团队工作,专注于一个目标。 在这两个危机周中,我们做了害怕甚至更早开始的工作,认为这将需要数月的工作。 异步接收订单,禁用订单,进行压力测试,清除日志-这只是我们所做工作的一小部分。 我们希望继续有效地工作,但又不会加班和加压力。
经验教训
回顾之后,我们完全重组了我们的流程。 我们以LeSS为基础,并以工程实践作为补充。 在接下来的几个月中,我们在引入工程实践方面取得了突破。 基于LeSS,我们已经实现并继续使用:
- 单品积压
- 完全跨功能和跨组件的命令
- 配对和暴民编程
- 真正的持续集成(CI)-将代码与一个分支中的12个团队集成
- 与分支机构的简化工作(基于中继的开发)
- 频繁发布:持续部署微服务,每日发布整体
- 拒绝单独的质量检查团队,质量检查专家是开发团队的一部分
危机后我们选择的6种做法:
1.聚焦的力量。 在危机之前,每个团队都承担着自己的债务,并专门从事其领域。 在危机期间,这些团队没有特定的任务;他们有一个艰巨的目标。 例如,无论如何,移动应用程序和API必须每分钟处理300个订单。 团队以目标为目标,并独立思考如何实现目标。 团队本身会制定假设,并在产品上快速对其进行检验。 团队不想成为简单的编码人员,他们想解决问题。
专注的力量体现在复杂的任务中。 例如,在危机期间,尽管我们没有经验,但我们进行了压力测试。 我们还使接收订单的逻辑异步。 我们考虑了很长时间并进行了交谈,在我们看来,这是一项非常艰巨的任务,可能会花费很多时间。 但是事实证明,如果不分心并且完全专注于问题,团队将有能力在2周内完成此任务。
2.内部黑客马拉松。 我们进行了500次错误黑客马拉松。 所有团队一起清除了日志,并消除了该站点和API中500个错误的原因。 目的是保持原木清洁。 清除日志后,可以清楚看到新错误,您可以轻松设置警报阈值。
黑客马拉松的另一个例子是错误。 以前,我们有大量的错误积压,其中一些问题在那里呆了很多年。 他们似乎永无止境。 每天都有新的出现。 我们将错误和通常的积压工作结合在一起。
#Zerobugs政策政策。- 如果该错误已在积压中超过3个月,则将其删除。 他在那里躺了好久,没有人死。
- 评估其余错误给客户带来的痛苦。 只保留那些使大量用户难以生存的错误。
- 安排内部黑客马拉松来解决错误。 我们做了几次冲刺。 每个冲刺,每个团队都犯了几个错误,并纠正了它们。 经过2-3个冲刺之后,我们积压下来了。 现在,您可以输入#zerobugspolicy。
- #zerobugspolicy。 如果该错误进入待办事项列表,则肯定会得到解决。 积压中的任何错误的优先级均高于其他任何积压元素。 但是为了进入待办事项列表,该错误必须很严重。 它会造成无法弥补的损害,或者会影响大量用户。
3.从项目团队到稳定的团队。 项目团队有一个有趣的故事。 在危机期间,我们组成了最有资格完成任务的专家团队。 危机结束后,车队决定继续这种做法。 尽管我根本不喜欢这个主意,但我们还是尝试了。 在短短2周内(一次冲刺),在下一次回顾中,团队放弃了这种做法(这一决定让我很高兴)。 如果团队缺乏某些技能,他们可以逐渐学习。 但是团队合作精神,支持和互助需要很长时间才能完成,需要几个月的时间。 短期项目团队一直处于编队和猛攻阶段。 您可以忍受几个星期,但是您将无法一直这样工作。
4.没有手动回归。 我们设定了摆脱手动回归的目标。 我们花了1.5年才达到目标。 但是拥有一个长期的宏伟目标会使您思考实现该目标的步骤。
我们分三步完成了。- 关键路径自动化。
2017年6月,我们成立了质量检查小组。 该团队的任务是自动化Dodo IS最关键功能的回归-订单的接收和生产。 在接下来的6个月中,一个由4人组成的新的质量检查小组通过自动测试涵盖了所有关键系统功能。 功能团队开发人员积极帮助质量检查团队。 我们在一起共同编写了一种美丽且易于理解的领域语言(DSL),甚至客户也能理解。 与端到端测试并行,开发人员使用单元测试对代码进行加权。 使用TDD重新设计了一些新组件。 之后,我们解散了质量检查小组。 质量检查团队的前成员加入了致力于业务功能的团队,以将开发和支持自动测试的经验传递给团队。 - 阴影模式。
经过自动测试,在5个发行版中,我们以影子模式进行了手动回归。 团队仅依靠自动测试,但是当团队确定可以发布时,我们启动了手动回归以检查我们的自动测试是否遗漏了任何错误。 我们跟踪了手动发现但自动测试未发现的错误。 在发布5个版本之后,我们分析了数据并决定我们可以信任我们的自动测试。 没有遗漏任何重大错误。 - 拒绝手动回归。
当我们有足够的测试开始信任它们时,我们就完全放弃了手动测试。 我们编写的测试越多,我们就越信任它们。 但这只是在我们开始自动化回归测试1.5年后才发生。
5.压力测试是回归的一部分。 在危机期间,我们编写了压力测试。 对我们而言,这是全新的体验。 但是,仅用了2周的时间,我们就可以使用Visual Studio工具创建一些东西。 我们使用它们,包括在服务器上生成人为负载,以发现性能限制。 例如,如果产品上的有机负荷为100个订单/分钟,则使用我们的测试又增加了50个订单/分钟,以查看系统是否能够处理增加的负荷。
次年,我们与经验丰富的PerformanceLab团队重新编写了压力测试。 今天,这些测试每周运行一次,并向开发团队提供快速反馈。
6.工程实践。 我们所有的团队都使用结对编程。 我认为结对编程是最简单但功能最强大的实践之一。 如果您不知道从什么工程实践入手,建议您进行配对编程。
结果
对我们来说,主要的结果是重组。 我们醒来并开始行动。 这场危机使我们看到了最大的潜力。 我们看到,我们可以更高效地工作许多次,并迅速实现我们的目标。 但是为此,有必要改变通常的工作方式。 我们不再害怕大胆的实验。
过去一年的这些实验的结果是,我们大大提高了Dodo IS的质量和稳定性。 如果在2018年春假期间我们的披萨店由于Dodo IS而无法工作,那么在2019年,披萨店的数量从300家增加到498家,Dodo IS完美无缺。 在第二次市场营销活动和春季假期期间,我们在新的销售高峰中从容应对。
这是很长一段时间以来的第一次,我们对系统的质量充满信心,并有能力在晚上睡个好觉。 这是不断使用工程方法并专注于技术卓越的结果。
经营成果
如果工程实践对您的业务没有好处,则不需要它们本身。 通过专注于技术卓越,我们提高了代码质量,并以可预测的速度开发了业务功能。 发布已成为我们的常见事件。
团队结果
今天,我们使用多种工程方法:
- 完全跨功能和跨组件的命令
- 配对/暴徒编程
- 持续集成-将12个命令连续集成到一个分支中
- 主题专家团队
- 没有独立的质量检查团队,质量检查专家是开发团队的一部分
- 用自动测试代替手动回归
- 无错误政策(#Zerobugspolicy)
- 停止生产线作为驱动程序以加速部署
我们学到了什么
我希望危机不会发生。 作为开发人员,我个人负有累积过多的技术债务并无法预见后果的个人责任。
- 工程实践可保护企业免受危机影响
- 不要积累技术债务。 可能为时已晚,成本太高
- 进化的变化要比革命的时间长几倍
- 危机并不总是一件坏事。 利用危机革新流程
- 但是,需要事先进行长时间的进化训练。
- 不要盲目应用您喜欢的所有方法。 一些方法正在等待中,当他到达时,团队将在没有阻力的情况下使用它们。 等待正确的时刻
- 随着时间的流逝,团队本身开始制定重要的决策并执行它们。 给他们一个有利的环境去尝试,让他们失败并从错误中学习
技术债务使我们陷入了可怕的危机。 我很高兴我们的团队发现使用这种僵局作为增长点的实力。 在我们自己的皮肤上,我们意识到危机时期可以并且应该用于大规模的组织和流程变更。 所以永远不要放弃,因为即使在最困难的情况下也有壮举的余地。
致谢
我要对所有在从危机到LeSS转型的过程中为我提供帮助的人们表示由衷的感谢。 我不断感受到您的支持。非常感谢我们的首席执行官Fedor Ovchinnikov的信任。 您是一家拥有真正灵活文化的公司的真正领导者。非常感谢产品负责人Dmitry Pavlov,我的老朋友和培训师。感谢Alexander Andronov和Andrey Morevsky的支持。非常感谢我们的第一个全职Scrum管理员Dasha Bayanova,他始终竭尽全力为我提供帮助和支持。 您的帮助很难被高估。特别感谢乔安娜·罗斯曼(Joanna Rothman),他在任何情况下都帮助我撰写了此报告:度假,病后康复。 乔安娜,很高兴与您合作。 您的建议,对细节的关注和辛勤工作对我很有帮助。