几十年前,开源软件使我们能够让世界上的任何人都可以为公共项目的代码库做出贡献。贡献者可能在世界的不同角落,在截然不同的时区,甚至不知道彼此的名字。项目的贡献者提出改进想法,做出变更,并提出拉取请求(PR)。然后,项目的所有者可以审查变更,并在合适的时候,决定他们是否愿意集成该提议的变更。
许多年后,拉取请求和异步工作方式成为产品开发团队中开发人员审查彼此工作的主要方式。但是,我们必须非常谨慎地采用来自上下文的解决方案,这些解决方案并不一定能优化产品开发团队在日常工作中所做的相同工作。
本文深入探讨异步代码审查过程的吞吐量和质量,这是产品开发团队非常重要的优化维度。它还解释了为什么共创(co-creation)模式——结对(Pair)和 Mob 编程——作为一种替代工作方式能够对这两个维度进行优化,而不需要在它们之间进行权衡。
异步代码审查
在我有机会与之合作或观察的大多数团队中,开发人员都是单独处理自己的工作项。起初,这听起来像是一个明智的想法,但我们常常忘记我们与团队中其他人的融合程度。毕竟,我们不是无缘无故就会同属一个团队的,对吧?代码审查就是这些集成点之一,开发人员试图使用代码审查作为构建质量和获得人工判断的手段,将工作向下游推进,直到最终投入到生产环境中。
它的工作方式是,一旦开发人员认为他们已经完成了编码,他们就会邀请团队其他成员来审查他们的工作。现在,这通常是通过提交拉取请求并邀请他人进行审查来完成的。但是,由于审查人员忙于他们自己的工作项及团队所产生的其他大量事情,他们往往无法立即做出响应。因此,当作者在等待审查时,他们也希望能让自己更有效率,因此他们会开始做其他事情,而不是在等待审查。
图 1:基于 PR 的异步代码审查
最终,当审查人员有空并提供了关于该 PR 的反馈和/或要求更改时,PR 的作者却不在了,因为他们正忙于其他事情。这种延迟的“乒乓”(Ping-Pong)沟通方式可能会持续几天/几周和几次迭代,直到作者和审查人员达成一个他们都满意的解决方案,并将其合并到主干分支中。
异步代码审查研究
在我的职业生涯我有机会指导和建议的团队中,有相当一部分人都对尝试不同于异步代码审查的工作方式感到好奇。他们不确定的是,他们目前的表现如何,以及什么样的指标可以帮助他们理解这一点。
此外,由于有过极限编程(XP)、精益和约束理论的背景,我很好奇在异步代码审查领域看到的一些指标,所以我决定做一项研究。它一开始时很小,但后来变得相当广泛了,我分析了 40000 多个 PR,它们来自 40 多个非常活跃的产品开发团队的代码库,这些团队都在执行基于 PR 的异步代码审查。
在研究过程中,我突然想到了一些系统性的见解。从个人和轶事的经验来看,其中一些是我期望看到的,但有些是意料之外的。
大的拉取请求抑制了构建质量的能力
PR 越大,越有可能患上所谓的“LGTM 综合征”。如果 PR 很大,审查人员就没有那么大的动力来提高质量。他们花了很长时间来审查,来与作者反复讨论交流,拖了几天/几周的时间,而交付的压力也越来越大。在工作到达审查人员手中时,已经太晚了,也很难纠正。他们往往倾向于放弃指导工作的能力,只评论“LGTM”(我觉得不错),并批准 PR,希望能在之后提高质量。当然,之后提高质量这种情况很少发生。
即使是审查人员想要投入时间、精力和耐心来审查大的 PR,如果作者在征求反馈之前做了很多更改,如果他们在某一点上走错了方向(这种可能性会随着工作量的增加而增加),那么从情感上来说,脱离他们所采用的解决方案是非常痛苦的。沉没成本谬论开始出现,并且很难抵消。
所有这些要点都是我们在整个行业中分享过的经验,但从数据中看到这些还是很有趣。
在这里,我们有一个散点图,其中每个点代表一个合并的 PR。在 X 轴上,我们以更改的代码行数作为 PR 的大小规模,在 Y 轴上,可以看到每个规模的参与度(每 100 行代码的评论数)。这个数据集只是一个例子,但需要强调的是,这种行为在所有其他分析的数据集中都可以看到。
图 2:每个规模的参与度散点图
随着 PR 规模的增加,我们会看到每个规模的参与度变得越来越低。我们有一个基于反馈和邀请人工判断的过程来帮助我们构建质量,但如果系统激励限制了我们获得反馈的能力,这也意味着我们不太可能构建质量。因此,我们最终引入了延迟,代价是无法提高质量。要我说,这是两败俱伤。
为什么大的 PR 会影响我们构建质量的能力,还有其他原因,这些原因不在研究范围内,但在这里却值得一提。
随着反馈的延迟,上下文往往会衰减,这意味着审查人员更可能难以理解作者决策背后的推理和背景。这使得审查人员不太可能对工作质量做出贡献。
因为它们将一系列的更改捆绑在了一起,所以大的 PR 更有可能在生产环境中造成问题,这意味着它们更有可能导致大量的返工。根据我的经验,返工的可能性会随着一次引入的变更数量呈指数级增长。
当生产环境中出现问题时,我们还需要花费更长的时间来排查问题并找出导致问题的根源,犹如大海捞针。上下文的丢失,作为同时引入太多更改的次级效应,也是导致故障排除时间更长的另一个原因。
小型拉取请求的好处
自从我们的行业了解了精益小批量的价值以来,已经有很长一段时间了。较小的 PR 花费更少的时间来编写,这意味着我们可以更快地得到反馈,并且如果我们走错了方向,我们也可以更早地发现。相比于要在日程安排中花几个小时来审查一份大的 PR,审查人员更容易抽出 10 分钟的时间来审查一个小的 PR。这使得 PR 更有可能得到更快的审查。
此外,由于审查人员能更快地收到反馈邀请,我们可以看到较小的 PR 比较大的 PR 参与度要更高。当他们能够尽早提供反馈时,审查人员就会有一种能够为质量做出贡献的感觉。小 PR 的部署风险也比大 PR 的低,因为较小的更改可能出错的情况也更少。
此外,如果出现问题,更容易确定导致问题的更改,这意味着我们能够更快地发现并解决故障。所有这些都对 DORA 的四个关键指标做出了积极的贡献:
部署频率——组织成功发布到生产环境的频率
变更的交付周期——从提交到投入生产所需的时间
变更失败率——在生产中导致失败的部署的百分比
恢复服务的时间——组织从生产故障中恢复所需的时间
异步审查中小型拉取请求的吞吐量较低
这项研究中一个令人惊讶的发现是我没有预料到的,并且在所有的数据集中它都存在,那就是围绕每个规模 PR 等待时间的可视化。
PR 等待或排队时间表示 PR 在队列中所花费的时间,未被处理,等待某人的注意;例如,等待审查人员的审查,等待作者回复评论,或根据审查人员的要求进行更改,批准后等待合并,等等。
图 3:按大小规模列出的每个规模的等待时间
正如我们从这个散点图中看到的,当我们减少 PR 的规模时,团队进行异步代码审查会导致每个 PR 规模的等待时间呈指数级增长。当我们使 PR 变小时,这种指数级增长的等待时间也会转化为呈指数级增长的每个规模代码审查的感知成本。
每个规模的等待时间在较小的 PR 规模上占主导地位的原因之一是,在较小的 PR 上每个规模的参与度更高,正如我们在每个规模的参与度散点图上看到的那样。随着我们减小 PR 的规模,异步沟通产生的延迟和延迟成本呈指数级增长。
需要牢记的一件重要的事情是,随着我们每个 PR 规模等待时间的增加,我们每次 PR 也都会产生更多的浪费,从而导致我们工作系统中产生更多的累积浪费。因此,随着我们不断缩小 PR 规模,我们在工作系统中推动变更的能力也受到了指数级的限制。
这一点也得到了平均 PR 流动效率的支持。
流动效率度量指标表示花费在项目上的时间占项目交付周期的百分比。
流动效率越低,系统中的浪费就越多,流程的效率就越低,反之亦然。
图 4:不同规模的平均流动效率
正如你所看到的,当我们减小 PR 的规模时,某一点的流动效率急剧下降。这意味着,如果我们将相同数量的代码拆分为多个较小的 PR,与在一个较大的 PR 中执行时相比,我们需要更长的累积交付周期才能将其推送到系统中。随着流程中等待时间的增加,流动效率的分母增加,导致流动效率下降,交付周期增加,吞吐量下降。
因此,通过异步工作方式,我们不得不在损失质量(大的 PR)和损失吞吐量(小的 PR)之间进行权衡。
有趣的是,当团队将 PR 规模缩小到超过等待时间开始主导 PR 交付周期的程度时,他团队就会直观地感受到这种痛苦。
系统中的库存会膨胀,直到与交易成本匹配
在精益制造中,有一个称为批量交易成本的概念描述了将一批工作发送到下一加工阶段的成本。在知识工作中,这种成本可以是实际成本(例如美元价值)和/或感知成本,并且可能有多种因素影响它。这个概念之所以非常重要是原因,一个加工阶段的交易成本越高,我们在该阶段前堆积的库存就会越多,以补偿转移批次的成本。
这里有一个来自现实世界的例子。如果电子商务网站的运费是 3 美元,那么你通常不会订购 1 美元的商品,对吧?在订购之前,你通常会将其与购物篮中的其他一些物品一起进行批处理。另一方面,当运费非常低甚至免费时(想想亚马逊的 Prime),订购低价商品在经济上就会变得合理了。
此外,与在订购前分批处理购物篮中的商品相比,你将在需要时准确地订购商品,而不是仅在等到购物篮中的价值高到足以弥合运费时才订购。这意味着物品也将更快地到达,一个接一个地,而不是等到批次中的最后一个到达时才一起到达。商品的流动增加了。
这里适用于产品开发的一个普遍观点是,任何为了尽快将产品推出市场的努力都必须涉及降低系统中的交易成本,否则,我们将开始在整个工作系统中对库存进行批处理。这反过来又会延迟交付、反馈和我们从客户和生产系统中获得的学习,这意味着我们的学习节奏会减慢。一旦我们的学习节奏减慢,我们就会变得厌恶风险,并倾向于采用更保守的解决方案,因为系统发出的信号表明,学习成本很高。这就是我们工作体系的经济性抑制我们创新能力的方式,因为尝试风险更大的想法在经济上变得不那么可行。如果系统的激励结构强烈反对,那么仅仅要求人们更加规避风险和创新是没有意义的。我们看到的行为是由系统控制的,所以如果我们想看到不同的行为,我们需要在系统上做工作。
现在,当我们谈论交易成本时,系统中的延迟也是其中的一种,因此会激励参与者增加批处理的规模来补偿它。
如果你最喜欢的网上服装店送货需要一周的时间,而你想在决定保留哪一件衣服之前先试穿多件衣服,你可能会订购你正在考虑的所有选项和尺码。相反,如果是当日送达,你可能会订购更少的商品,可能只订购一件,试试看是否合适,如果不合适,再订购下一件。
运行缓慢的测试套件也会发生同样的情况。如果运行测试需要 20 分钟,我不会在每行代码更改后都运行它们。如此频繁地产生那么多开销没有任何经济意义,所以我将减少测试的次数,这意味着在得到反馈之前对系统进行了更多的更改。这让我退回到更大的批次,正如前面提到的,这带来了一系列我们想要避免的问题。
在异步代码审查的世界中,如果我花 10 分钟做一个更改,花 2 小时才能获得审查,那么这个更改的等待/工作时间比是 120/10=12。换句话说,我们的流动效率只有 7.7%,而工作等待的时间是其交付周期的 92.3%!该系统显示代码审查的成本很高,这激励了系统中的参与者减少请求的频率,这意味着在请求之前进行更多的更改,这就意味着回到了更大的 PR 中。一个昂贵的流程永远不会激励进行小的变更,这意味着小步重构和增量开发变得不太可能。因此,在流程中具有较低延迟和较低等待/工作时间比的团队,通过启用随着时间推移不断进行的小变更流程,更有可能保持代码库的健康,并保持其对更改的响应。
换一种说法,如果流程中存在延迟(这是异步工作方式所固有的),我总能找到一个足够小的批处理规模,但流动效率非常差,因此使用这么小的批处理规模没有任何经济意义。这反过来又激励我们回到更大的批次。
虽然你可能忽视了经济学,但它不会忽视你。——Don Reinertsen
延迟和异步工作方式的另一个问题是,它们使人们更有可能引入更多的东西,增加在制品(WIP)库存和上下文的切换。我们在“图 1——基于 PR 的异步代码审查”中看到了 Ema 和 Luka 的情况。当 Ema 等待 Luka 审查时,她认为自己可以开始做其他事情了。根据 Little 定律,平均周期时间与平均在制品成正比,与平均吞吐量成反比。这意味着,像 Ema 在等待时所做的那样,投入更多的工作会增加延迟,从而使周期时间增加,吞吐量下降。
当我们单独工作并异步审查代码时,WIP 通常比我们想象的要高得多。如果我们有 4 个人在一个团队中,并且他们单独工作,我们可能会认为我们有 4 件事情在进行中。但当系统出现延迟时,我们依赖于从其他人那里获得反馈,就像我们在代码审查中所做的那样,很可能我们最终会得到至少两倍的 WIP。Ema 在等待时会做更多工作,这种情况也会发生在团队其他人身上,因为他们也需要等待各自的 PR 审查。因此,我们最终完成了 8 件事。根据我的经验,看到团队的 WIP 数量是团队人数的几倍并不奇怪。
图 5:高 WIP 数量导致更多 WIP 数量的因果循环图
与此同时,具有讽刺意味的是,如果你要问 Ema 和团队中的其他人,他们可能会说他们在这段时间里感觉很有效率。系统思考最重要的教训之一是,系统往往会恶化,尽管我们努力在改进它们。最直观的解决方案往往与那些有助于将系统转向更理想状态的解决方案相去甚远。
这里的一个普遍观点是,高 WIP 的二级效应是它会自我强化。我们在系统中拥有的 WIP 越多,响应就越慢,等待时间和延迟就越长,这反过来又激励了更高的 WIP,因为人们在需要等待的时候拉进了更多的东西。当人类面临延迟时,他们很擅长堆积库存和增加 WIP。
共创模式
我所做的研究得出的结论是,为了在我们减少 PR 的平均大小规模时不以指数的方式损失吞吐量,作者和审查人员需要以指数的方式更快地响应对方的请求。这最终导致了我们采用同步、连续的代码审查和共创建模式。
共创(Co-creation)模式、结对(Pair)和 Mob 编程是我们在同一时间一起处理同一件事的工作方式。我们一起开始,一起工作,一起完成。结对编程【1】是一种技术,两个开发人员在同一件事情上工作,而 Mob 编程【2】更专注于在会话中掌握将功能交付给客户所需的所有技能。根据手头工作的特性,这可能不仅涉及开发人员,还会涉及其他技能(设计、产品、内容……)。
这个想法是让人们去解决问题,而不是把问题转移到人身上;后者涉及到问题拆分,并给每个人一个问题的部分,让他们单独解决,然后尝试重新组装整个问题。当我们蜂拥而至地处理问题时,作为副产品,我们在交互过程中减少了延迟,这意味着将工作交付给客户的时间更短了。想想看:当生产出现中断时,我们该如何处理?通常,所有需要解决问题的人都会接到电话,然后共同努力解决问题。
我们这样做的原因是我们希望尽快解决问题,这样我们就可以缩短恢复时间,从而将影响降至最低。但重要的一点是,我们可以使用相同的工作方式来最大限度地缩短交付周期。这反过来又加快了学习节奏,帮助我们更快地消除那些不起作用的解决方案,从而最大限度地提高团队的价值。
约束理论的创始人 Eli Goldratt 对紧急情况是一个很好的学习机会有很多话要说。在紧急情况下使用的规则违反了我们的标准规则,挑战了毫无疑问的假设,但我们很少问自己,我们的“特殊规则”是否真的应该成为我们的标准规则。
此外,作为共创的副产品,我们获得的激励结构也与典型的“你烧,我刮”方法非常不同。我们没有“作者和审查者”的基调,而是让人们一起建设并负责使之运行起来。
……我们的制作和检查系统,如果适用于制作吐司,它会表达:“你烧,我刮。”——W. Edwards Deming
我听到的支持 PR 和异步代码审查的一个典型论点是:“代码应该由没有参与构建流程的人来审查”。但是,根据我的经验,延迟和脱离上下文的审查实际上是这个流程的缺点,而不是优点。
如果提供了脱离上下文且延迟审查的人同时编写了代码,那么是什么保证了他们不会提供相同或更好的反馈呢?这是一件很难甚至是不可能衡量的事情,但根据我的经验,更多的上下文、更少的流程延迟和更快的沟通有助于提高质量和更及时、更便宜地整合反馈。我猜这也是我观察到的共创团队返工至少少了一个数量级的原因,其中包括生产中的缺陷和问题更少。
吞吐量和质量两个都要
我知道这听起来像乌托邦,但实际上我们可以鱼与熊掌兼得。我们可以同时拥有高吞吐量和高质量。这也不是第一次发现这是可能的,因为 DORA 研究表明稳定性和吞吐量之间存在“与”(AND)而非“或”(OR)的关系。我们要么有吞吐量和稳定性,要么两者都没有。
共创模式改变系统经济性的方式是,通过组队(Pair)和 Mob 编程,审查延迟和等待时间在设计上基本上是不存在的。当有人物理或虚拟地坐在我旁边,做着和我一样的事情时,他们能够对我在代码中所做的每一个原子更改进行持续的代码审查,反之亦然。该流程本身保证了参与者的可用性,这是必要的,以便立即进行代码审查,从而不会因 PR 较小而损失吞吐量。
图 6:减少交易成本驱动更小的最佳批处理规模
特色动画:Kelly Albrecht
实际上,用精益的术语来说,我们能够最大限度地降低交易成本,因为我们将代码审查的成本降到了最低,实现了更小的批次,并增加了系统的流动。PR 的规模实际上变成了一个最小的、原子性的更改,甚至可能低至一行代码。
当我们有了即时可用性和免费的代码审查成本时,我能够得到更及时、更频繁和更丰富的反馈(口头的、即时的和来自上下文的)。这对于提高质量至关重要,但作为副产品,它也减少了返工量。原因是,当我们走错了方向时,我们避免了长时间的偏离,因为路线修正发生得更快,这会导致更多的时间用于增值工作,从而提高生产率。我们达到了质量保证速度的状态。
另一个经常被忽视的优势是,一起工作不仅可以最大限度地缩短等待时间。通常,它还减少了处理/工作时间,因为其他人通常知道如何以更快的方式完成某件事,这意味着处理时间也会减少。这反过来又转化为更短的交付周期和更高的吞吐量。
当我们通过持续的代码审查实现快速的路线修正时,我们也倾向于抵消沉没成本谬误,并爱上解决方案。我唯一要失去的就是我刚刚做的一个最小的变更。与不得不放弃一周的努力相比,我可以更好地处理这个问题。因此,我们更可能提高质量。
除此之外,与异步代码审查相反,作为同时处理同一件事情的副产品,我们减少了在制品,这加快了系统中的工作流程。如前所述,需要集成的异步工作使我们倾向于引入更多的工作项,这使事情变得更糟。在一个 4 人团队的情况下,当他们单独工作时,他们很容易得到两倍的 WIP。在结对编程的情况下,他们的 WIP 为 2,少了 4 倍!使用 Mob 编程,WIP 就更少了。这是一个大幅减少 WIP 的机会,这也是不容忽视的。
常见的误解
说了这么多,我不认为每个人都应该一直做 Pair/Mob 编程——这是我从怀疑这些做法的人那里听到的一个常见误解。
重点是,我认为,当涉及到工作方式时,我们作为一个行业存在错误的默认设置,大多数时候每个人都是单独工作的。大多数团队以 N 个 1 人团队方式运作,而不是 N 人 1 个团队的方式。
疫情似乎也促成了这一点。从一开始,随着整个行业的远程化,出于某种原因,我们在远程工作和异步工作之间画上了等号。这两个想法是相互正交的。我们既可以远程工作,也可以共创,因此我们既保持了上述共同工作的好处,同时还具有在家工作的灵活性。
我经常被问到的一个问题是:“共创如何允许我们使用在异步工作中所获得的各个时间表的灵活性呢?”有一些团队想要尝试结对编程,但他们遇到了个人日程安排中出现延误的问题,并且在需要时无法找到结对伙伴。这是一个重要的十字路口,在这里,团队通常会走错方向,走向异步。此时的异步需要是对某些事情的反馈。这是关于给定时间表的低流动弹性的反馈。我们可以考虑通过让更多人参与会话来提高团队的弹性,而不是采用异步方式。这就允许了更多的时间表重叠,同时保持了较高的流动效率,并使事情更快地走出大门。Mob 编程尤其提供了这种弹性,人们可以根据需要退出并回来。并不是每个人都需要一直在那里。这也不是我们想要的。
现在,如果你有一个团队,其团队成员位于非常遥远的时区,并且在工作日团队成员之间没有太多的重叠,我会质疑组建该团队的决定,而不是跳到异步的马车上。撇开这个话题不说,我都希望一个团队是由工作时间足够重叠的团队成员组成。“足够”的定义可能有所不同,但根据我的经验,至少 5 小时的重叠时间是一个很好的目标。
有趣的是,它在实践中的表现方式是,个人日程安排的灵活性加上团队的高度弹性实际上是一种优势。通常,与在办公室工作一样,有些人喜欢早点开始新的一天,有些人则喜欢晚点开始。尽早开始工作的人已开始工作,然后其他人加入,然后晚结束工作的人结束一天的工作。由于我们在一天中工作了更长的时间,因此我们可能会更快地完成这项工作,同时人们保持了灵活的个人时间表。这可能是一个双赢的局面。
不幸的是,在这个世界上,大多数人都只有单独工作的经验,学习合作是一项需要时间和耐心才能掌握的新技能。我记得我参加过 Woody Zuill 关于“Mob 编程”的研讨会。在为期三天的研讨会中,他花了第一天整整一天的时间来让人们练习一起工作,及时做出贡献,并用善意、体贴和尊重的态度对待彼此。这些原则是合作的基本规则。老实说,当时花这么多时间在这个话题上我觉得有点多余。但多年来,随着我开始观察并与越来越多试图共创的团队合作时,我明白了为什么专注于学习这些原则和技能是如此重要。
对于那些想要踏上共创之旅的团队来说,进行适当的指导和辅导是非常重要的,尤其是如果团队中没有人有过共创的经验。否则,团队可能会在评估一种技术时,认为他们正在进行结对或 Mod 编程,而实际上,他们正在做一些非常不同的事情。人们劫持键盘、个人主导对话、过长或根本不存在的轮换、人们被孤立或心不在焉等等,这些都不是共创理念的组成部分,然而,这也是我经常看到团队说“这不适合我们”的原因。他们是对的。但是,首先,我们需要确保我们正在评估的技术是我们认为我们正在评估的。花时间学习更多关于这些实践的知识并获得适当的支持可以帮助我们做到这一点。
另一个关键点是,一起工作可以非常快地解决团队中的潜在问题。当我们单独工作时,按照设计,人与人之间没有太多的互动,因此潜在的问题往往不那么明显,而且延迟时间更长。一旦团队合作困难的问题变得明显,人们往往会倾向于认为“共创不适合我们”。情况可能是这样,但前提是解决团队中出现的特定技术问题不是我们所追求的。该技术只是潜在团队动态的一面镜子。我们可以选择如何处理反馈,但最终,我们不能将没有反馈的问题归咎于技术。
然而,合作不应该强加于任何人。毕竟,你可能会试一试,发现它真的不是你的菜。每个人都应该努力寻找最能满足自己需求的环境。希望这能让我们更接近一个让更多人在工作中找到快乐的状态。
总结
在异步代码审查中减少 PR 大小规模只能让你走到这一步。在某种程度上,较小的 PR 规模在经济上是不可行的,我们必须在吞吐量和质量之间做出权衡。从异步代码审查转移到结对代码审查,再到一起工作(Pair/Mob 编程),我们行业中的许多团队都可以从中受益。
还有很多其他好处【3】,团队可能会考虑尝试一下,根据我的经验,这是一种工作方式,它为我有机会与之合作的团队带来了如此多的乐趣和生产力,我相信这是一种能力,能为采用团队和公司提供竞争优势。
参考文献
作者介绍:
Dragan Stepanović常驻柏林,作为首席工程师,他帮助公司发展他们的工程文化,克服瓶颈,并最大限度地发挥价值。他正在寻找更好的工作方式,探索光谱的两端,并帮助团队和组织尝试反直觉的想法,这些想法最初没有多大意义,但令人惊讶的是,这些想法完全相反。他喜欢无休止地讨论极限编程、约束理论、系统思考、精益和社会情感技术主题。
原文链接:
https://www.infoq.com/articles/co-creation-patterns-software-development/
相关阅读:
Meta 提出代码审查新方案:杜绝代码 Bug,日均代码审查总量增长 17%
活动推荐:
2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。
评论