记得第一次接触敏捷是我在图书馆工作期间。我的工作是从无到有建立一个新的数字化奖学金中心,有时我需要与图书馆的软件开发团队合作,构建支持项目的工具。当时开发团队有六名成员,我发现他们的工作方式与非技术人员截然不同。开会时,他们讨论的不是产品功能,而是“用户故事”(描述功能的小段文字),而且他们还会分配“故事点”来衡量完成相关任务所需的工作量。每天早上,他们会举行“站立会议”,实际上就是站着开会,据说站着是为了加快会议的速度。他们的办公空间内,白板必不可少,开发人员会移动白板上的便利贴以表示工作的完成状态。他们按照“冲刺”划分工作周期,一般一个“冲刺”为期两周,他们需要在这两周内专心完成特定任务。
在与图书馆的工作人员开会时,开发团队的负责人会使用软件报告进度,其中包括表示每个项目状态的仪表板。经理还可以向我们展示团队的“速度”图表,即开发人员完成任务的速度,以及历史数据比较和预测。
后来,我了解到这就是敏捷,一种管理软件开发的方法,这种方法在各大技术公司非常受欢迎,而且在非技术办公场所也越来越流行。老实说,敏捷给我留下了深刻的印象。其实,在日常工作中,我经常感觉很迷糊,不确定自己的工作有没有进展,或者有没有做真正有价值的工作。相比之下,开发人员似乎非常清楚自己在做什么。即便他们遇到困难也没关系,只要解决困难就可以了。他们的需求会不断变化,而两周为单位的工作周期,可以让他们迅速在各个功能之间切换,甚至可以采用新框架,而无需从头开始。
这就是敏捷的美妙之处:非常灵活,速度非常快,它要求开发人员将每项任务分解为尽可能小的单元。重点是快速发布,不断回顾,并根据需要改变方向。
我对敏捷非常感兴趣。敏捷是从哪里来的?敏捷的目标又是什么?
于是,我开始探索敏捷的历史。我发现长期以来,经理想要的软件开发过程与开发人员实际编写软件的过程之间一直存在矛盾。各大组织一次又一次地引入新的管理风格,就是希望控制软件开发面临的最大问题:超出时间与预算限制。后来,各个公司发现敏捷解决方案不仅可以让开发人员愉快地完成任务,而且还能保证开发速度。不过,最近一些迹象表明敏捷的力量正在衰退。人们正在酝酿新的方式,而且很有希望取代敏捷。
软件工程师
软件开发的危机在“软件”这个词发明之前就存在了。1954年,行业、政府和学术界的领袖们在美国底特律韦恩州立大学召开了一次会议,与会的专家表示,我们缺乏接受过一定培训的程序员。直到四年后,“软件”这个词才首次出现在统计学家 John W. Tukey 的一篇文章中,用于表示应用程序编程。到了20世纪60年代中期,美国有至少 10 万人从事程序员的工作,但据估计至少还有5万的缺口。
在编程行业刚刚起步的几十年里,大多数专家认为,编写计算机可读的代码并不是很难。毕竟系统分析师(高级架构专家)已经完成了设计程序和硬件的艰苦工作。而程序员的工作不过是将设计转化为可供计算机运行的代码。然而,事实证明这个翻译过程是一项难度很高的脑力工作。
这项工作需要强大的脑力支持,而且更大的疑问是软件开发究竟是什么样的工作,时至今日这个问题依然困扰着管理人员。在计算机诞生初期,在某些人看来,编程是(或者说应该是)纯粹的逻辑问题。毕竟,机器只能按照指令工作。因此,我们需要告诉计算机正确的运行方式,而程序员的工作就是找到这种方式。
然而,实际的编程经验表明,编程既是艺术又是科学。2019 年,Clive Thompson 在《程序员》一书中指出,最先进的编程工作都是由一群大学实验室的技术怪人完成的,他们认为自己既是工匠又是逻辑学家。软件本身是看不见摸不着的(你只能看到存储软件的介质),因此与其他工程领域相比,软件开发的工作更加抽象且神秘。其他领域都有一定的物理定律可循,但软件似乎建立在流沙之上,因为硬件的参数和能力在不断变化。
然而,电子数据处理领域(办公自动化,如考勤卡和工资单)得到了迅速发展,因此这些任务使用的机器也迅速地成了技术的最前沿。但我们需要运维团队来设计程序、准备打孔卡并将数据输入系统。老牌经理们看不惯年轻的专业团队日益壮大,也看不惯软件项目的成本和复杂性经常不可控。计算机科学家 Frederick Brooks 曾将软件项目比作狼人:这些项目刚开始的时候就像小狗一样天真无邪,但最后往往会演变成“不遵守时间计划、预算超支且有缺陷产品的怪物”。20世纪60年代后期,软件开发面临三大危机:迫切需要更多的程序员;必须提高可预测性;开发人员必须配合管理层的工作。
本着这种专业化的精神,行业领导者鼓励程序员接受“软件工程师”的概念,这个概念是在 1968 年北约软件工程会议提出的。许多组织领导都指出,软件开发的规模庞大、组织难度高,而且很难管理。那么,为什么不借鉴一些其他工程领域的方法呢?将编程工作发展成为一门科学,并建立一套有秩序、有影响力且可靠的方法。组织者希望,降低软件开发行业的管理难度,软件工程师可以学习其他学科工程师的模式,更好地融入企业文化。历史学家 Nathan Ensmenger 写道,“为了提高制造软件的效率,编程的黑魔法必须让位于科学的软件工程方法。
瀑布式软件开发
软件工程似乎的确有效。各个大学都采用了这个术语,鼓励学生在学习编程时,练习完善的工程方法,例如使用数学证明等。计算机科学家 Tony Hoare 声称,这些技术将“改变晦涩难懂且容易出错的计算机编程工艺,以满足工程专业的最高标准。”
另一方面,经理们也花费了大量心思来组织软件开发人员,并建立了多种不同的组织方法。其中一种方法是 IBM 推出的主程序员组(Chief programmer team,CPT)框架,该框架由一名主程序员负责监督一组核心专家成员的工作。还有一种流行的做法是,由多级管理者负责管理程序员,管理者们制定决策并将工作分配给麾下的程序员。
随着这些新技术的出现,程序员的管理也冒出了很多新方法,其中之一就是“瀑布式软件开发”。从理论上来说,瀑布式开发非常合理:有人为软件产品设定目标,并将生产分解为一系列步骤,必须确保当前步骤的所有工作都已完成并通过测试,才能继续下一个任务。换句话说,开发人员只需要按部就班地执行管理层定下的计划即可。
然而,充满讽刺意味的是,首次提及“瀑布”一词的文章指出这种方法不切实际,但这个名称和思想却依然流行起来了。瀑布式开发与采用这种方法的公司的层级结构非常契合,正如 Nathan Ensmenger 写道:“软件工程运动的本质是控制:控制复杂性、控制预算和日程计划,而最重要的恰恰是控制劳动力。”而这正是瀑布式开发最擅长的领域。
但不久之后,软件开发再次陷入危机。部分问题是计算机科学家的供不应求。在20世纪80年代,各个大学没有足够的师资力量来培养大量立志成为软件工程师的学生。美国计算机协会表示,“这种情况十分严重,甚至威胁到了计算机科学部门持续培养信息处理行业以及科技日新月异的社会所需的技术人才的能力。”
缺乏开发人员并不是软件行业面临的唯一难题。软件开发本身似乎也深陷泥沼。瀑布式管理承诺的严格控制管理化成了海市蜃楼。再多的文档、再多的流程、再多的程序也拯救不了软件开发的不可预测性。软件项目规模巨大、成本高昂,而且经常会失控,由于需求的不断变化,项目团队之间在细节问题上争吵不休,所有的计划都无法按时完成。管理人员使出浑身解数,想让软件开发变得更可靠、更可预测,但结果却愈演愈糟。正如计算机科学家 Jeff Offutt 所说,“20世纪60年代,程序员建造的都是‘小木屋’,而到了80年代,程序员团队建造的都是办公楼”,而到了90年代,他们建造的都是摩天大楼。然而,技术专家团队似乎无法协调他们的工作。根据技术行业顾问 Peter Varhol 的估计,20世纪90年代初期,从构思到产品问世,每个应用程序所需的开发时间平均为三年。高科技本应让各大企业更智能、更快、赚取更多利润,然而很多公司的项目都未能顺利完成。
“工程师”的头衔、层级管理结构、周详的计划和文档,所有这些都是为了给新兴的软件开发领域带来秩序和控制,但最后的结果却适得其反。瀑布并没有为软件开发人员扫清障碍,相反大量的文书工作和无休止的会议加重了他们的负担。
工程师对各种苛刻的管理怨声载道。他们只想构建软件,结果却不得不疲于应付大量文书工作。Douglas Coupland 的小说《Microserfs》(微农)以及Mike Judge的电影《上班一条虫》(Office Space)中描绘的绝望的开发人员就是那个时代的写照。
2001 年 2 月,17个中年人聚集在美国犹他州瓦萨奇山区雪鸟滑雪胜地的洛奇酒店里,为软件开发制定了一套全新的流程,这就是后来的敏捷宣言。这不是他们的第一次见面。长期以来,他们以各种形式聚集在一起讨论软件开发,最终在 2001 年的这次会议上,他们起草了敏捷宣言。这是一套价值观,在接下来的几年里,这些价值观渗入了程序员管理的方方面面,无论是初出茅庐的初创公司还是闻名世界的科技巨头都相继采用了这套管理方案。敏捷宣言本身简洁明了:
我们一直在实践中探寻更好的软件开发方法,
身体力行的同时也帮助他人。由此我们建立了如下价值观:
个体和互动 高于 流程和工具
工作的软件 高于 详尽的文档
客户合作 高于 合同谈判
响应变化 高于 遵循计划
也就是说,尽管右项有其价值,我们更重视左项的价值。
该宣言还补充了十二项附加原则,描述了工程师所面临的难题。瀑布式开发假定软件应用程序的需求是稳定的,但由于速度缓慢,而且管理僵化,因此最后的结果往往偏离管理层当初制定的计划。敏捷抛弃了这些高级路线图,转而强调即时做出决策。如此一来,软件开发人员就可以随着需求或技术的变化而改变自己的工作方式以及内容。他们可以专注于构建软件,而不必被文书工作和各种文档搞得晕头转向。此外,他们还可以摆脱无休止的会议。
这份文件十分有意思。在专业开发人员稀缺的前提下,技术专家们本应诉求更直接的物质利益,比如工会、对知识产权的拥有权等,但他们要求的却是更好的工作环境,能够让他们更出色、更高效地完成工作。正如作家 Michael Eby 指出的那样,这种反抗管理的精神与之前对工作场所不满的表现方式截然不同:技术人员要求的不是物质提升,而是建立一种基于文化、原则、假设、等级制度和道德的“新精神”。敏捷宣言抨击了官僚主义、天真以及徒劳无功的努力。开发人员并没有要求更高的报酬,他们只是希望自己能被区别对待。
对于软件开发性质的看法变化并非发生在 2001 年,而是在敏捷宣言出现之后的十年左右。开发人员和管理人员都逐渐认识到,软件开发不可能完全按照分析师给出的流程图和工作表推进。正如历史学家 Stuart Shapiro 指出的那样,软件开发的复杂性比较特殊,该领域的问题是“模糊、多变和多方面的,因此很难找到一种通用的方法。他们需要结合多种方法,并调整各自的解决方案。”这与循规蹈矩的填表和打卡完全不同。此外,随着20世纪90年代程序员数量的急剧增加,各大公司招聘了一些非计算机科学专业毕业的人才。这些年轻的程序员并没有经历过人们在七八十年代尝试将软件开发变成一门科学的努力。敏捷宣言并不是一剂良药,它更像是一支插曲,只不过是展现了软件开发人员多年来对流行的企业管理模式的不满而已。
然而,虽然敏捷有一群忠实的拥护者,但它的使命(即消除自上而下的计划与层级管理)也存在一定的风险。这意味着,管理层要或多或少地将控制权拱手让给开发人员。大多数大公司都不愿意这样做,至少在 2010 年之前是这样。不过,根据敏捷咨询公司 Planview 的统计数据,从2012年~2015年,超过50%的开发团队都认为自己是“敏捷式开发”。
毫无疑问,敏捷开发的流行在一定程度上受到了互联网高速发展的影响,互联网极大地改变了软件的发布方式。以前,软件更新的频率一般为一年一次,甚至更长。而且必须借助CD和软盘等物理介质分发,这极大地限制了新版本的发布速度。但是,如今我们可以借助高速互联网,根据公司的需要频繁地发布补丁和新功能,甚至可以高达一日多次。而敏捷正是在这种环境下孕育而生的。
Facebbok 曾有一个座右铭“快速行动,打破常规”,很好地体现了新时代的精神。这是一个考验胆量的时代,无论是软件开发还是公司CEO都要大胆创新。风险投资公司的目标是寻找“独角兽”,他们在2010年前后向科技行业投入的资金创下了新高,因为他们希望尽快看到结果。与众多创业公司展开角逐需要迅速改变,不断发布新版本,并以惊人的速度发展。风险发生了变化,如今坚持使用瀑布式开发会非常危险,而敏捷式开发则可以大幅提升速度。
同样,软件开发人员也发生了变化。在20世纪70年代和80年代,专家们将注重系统和逻辑思维的科学家视为理想的软件工作者。但多年来,这一理想未能扎根。我们透过敏捷宣言就能看出,他们的目标是致力于最高标准,快速而自信地工作,而经理们“相信他们能够顺利完成工作”。但是他们拒绝因循守旧。他们不怕快速变化的需求,相反,他们认为这是“驾驭客户需求变更的有利竞争优势”。
解放思想、打破墨守成规的思想与敏捷宣言的理念完全吻合。敏捷宣言的作者们看起来就是典型的工程师,穿着衬衫,腰里别着手机套,但敏捷宣言的起草者之一 Jim Highsmith 表示,“无政府主义者本来就不会成为更大的组织”。尤其是在早期,人们曾经就敏捷方法给传统管理范式带来的挑战展开过许多讨论。敏捷的支持者为这种与众不同感到自豪。Jim Highsmith 曾在 2001 年写道,这个框架“吓坏了传统主义者。”软件开发人员和顾问 Al Tenhundfeld 也曾表示,“敏捷是公开的、激进的、反管理的。例如,Ken Schwaber [敏捷宣言的作者] 直言不讳地表达了希望摆脱所有项目经理的目标。”
反管理,但不是反企业。人们很容易将敏捷开发人员视为20世纪60年代后期围着打孔机转悠的科技“怪人”的复兴。然而,这两种人截然不同。早期的科技“怪人”希望编程这项新技术能够投入使用。而敏捷式开发的程序员会全身心地投入项目。他们讨厌管理层的干预,因为管理层阻碍了他们实现最大的愿望,即以最高水平的专业表现迅速完成工作。就像 Aaron Sorkin 的《社交网络》中的开发人员一样,他们希望所有人都待在自己的工作区域,戴上耳机,消除一切干扰,专心致志地投入工作。
管理层的复仇
在图书馆工作期间,我一直在关注开发人员,我非常欣赏他们的团队合作和务实精神。然而,随着时间的推移,我也注意到了这些团队的一些问题。尽管他们有速度图表和严格的功能记录,但开发人员的进展似乎并没有预期的那么快。他们都在努力工作,这很明显,但他们面临一个致命的缺陷:没有人清楚项目最终应该是什么样子,或者说服务的目标是什么。虽然团队成员可以开发功能,但他们不清楚为什么要开发这些功能。也许这个问题只是我们这个项目的问题,但是影响很大。同时,我也开始怀疑敏捷方法是否有一定的局限性。
事实上,任何接触过软件开发的人都可能听说过关于敏捷的传言。尽管敏捷宣言给出了许多承诺,但人们逐渐意识到,敏捷式开发也不能完全解放开发人员。软件开发再次陷入了危机,但这一次,是敏捷危机。从普通开发人员到一些最初的宣言作者,每个人都对敏捷实践产生了担忧。很多人都谈到了“敏捷工业综合体”,即由敏捷顾问、演讲者和教练构成的网络,他们收取大量费用来帮助组织调整敏捷流程。几乎每个人都在抱怨敏捷转向了错误的方向:在过去的二十年里,敏捷偏离了最初的宣言,如今开发人员受到的限制、承担的工作量与压力更大了。
部分问题在于敏捷的灵活性。自由开发者 Jan Wischweh 称这是“没有真正的苏格兰人”的问题。凡是人们不喜欢的敏捷实践就不是敏捷。敏捷宣言的结构就决定了这个不可避免的问题:因为宣言没有规定任何具体的活动,所以我们只能衡量现行方法的精神,这一切都取决于具体的实践者。因为敏捷只是一种“思维模式”,而不是一种方法论,因此组织的特征必然会影响到敏捷的实践。另外,人们也无法批评敏捷,因为你无法将敏捷化为一组特定的方法。一位产品经理告诉我:“如果敏捷不适合你,人们会认为这是因为你的实践方法不正确,而不是因为框架本身有问题。”
尽管敏捷的定义非常灵活,但许多开发人员已经对敏捷的想法失去了信心。Wischweh 本人在向一位律师介绍站立会议时,遇到了一个从未想过的问题。一位称职的专业人士每天都需要证明自己确实在工作,而且还要精确到非常小的单位,这对她来说太荒谬了。Wischweh 开始思考敏捷实际上是在鼓励开发人员将自己视为机器中的齿轮。虽然他们没有像瀑布模型那样被埋在管理层的管控之下,但业务的优先级仍然由管理层决定。“作为开发人员和 IT 专业人士,我们喜欢将自己视为知识工作者,我们不需要解释自己的工作,也不能被商品化。但我认为敏捷在朝着完全相反的方向努力。”
宣言的作者之一 Al Tenhundfeld 指出,他们都是在职的开发人员,而最早接受敏捷宣言的是自我管理的编程团队。然而,现在有很多专业人士帮助团队实施敏捷,而敏捷会议也是由经理主导,而不是开发人员。如今的敏捷变成了自上而下的管理形式。而敏捷项目经理,通常作为“产品负责人”嵌入到团队中,他们被夹在两股势力中间:一方面需要为开发人员考虑,另一方面需要交付成果给管理层。
尽管团队受到多个方向的牵制,但仍然需要以越来越快的速度推进项目。毕竟,根据敏捷的定义,“冲刺”(sprint)本身就意味着快速。事实上,许多与我交谈过的科技工作者都表示前景堪忧。技术作家 Sarah Moir 表示,“你必须定义在这个时间段内合理地完成哪些工作,然后跑到终点;然后再重复,然后再到终点,如此反复。如果付出百分百的努力,很快就会让人觉得筋疲力尽。”
此外,还有日常站立会议、轻量级的任务以及频繁的检查,对开发人员来说,这些都是为了监控自己的工作。特别是将工作分解成一些小块,开发人员就背负起了一种责任感:他们必须完成每一项任务。而且开发人员也会感受到压力:他们必须证明自己的价值。毕竟,他们是员工,拿了公司支付的薪水。
“故事点”,用来衡量特定开发任务所涉及的工作量的抽象概念,也失去了实质性的作用。最初,开发团队引入故事点,是为了方便开发人员控制工作量和工作内容。然而,在实践中,故事点变成了评估开发人员绩效的一种方式。西雅图的软件工程师 Yvonne Lam 表示,“一旦将某些东西放入数字工具中,人们就会监控这个数字,并希望它上涨,对不对?”
然而,问题不仅在于监控,还有将这些故事点转化为时间计划的方式。John Burns 是一家平台公司的工程师,他说之前的一个公司只是简单地将故事点乘以一个共同系数,就粗略地估算出了项目所需的时间。尽管人们普遍认为故事点只是一种非正式的内部衡量标准,但管理人员还是将它们作为计划的工具。
这些抱怨的背后是对敏捷所承诺的自由的更深层次的怀疑。敏捷非常重视开发人员的创造力和独特的工作方式。但是,采用敏捷式开发,员工能够发挥出的创造力有明显的限制,特别是因为问题常常被分解成如此小块。Michael Eby 写道,“很明显,敏捷消灭了层级管理控制的许多弊端,但只是为了以更微妙的方式管控细节。”Yvonne Lam 指出,敏捷的自治在实施中具有很大变数,“虽然敏捷说你有自主权决定自己的工作方式,但有时你想要的是有权利说不。”在软件开发项目的过程中,我们需要做很多选择,比如语言、框架、结构等,但我们忽略了一点:通常重大决策都没有开发人员的参与。
在过去的几年里,这些问题变得更加重要和紧迫。我们看到科技人员改变公司业务战略的许多例子,Google 开发人员抗议公司与国防部缔结人工智能合同,游戏开发人员抗议性骚扰。这些要求超出了敏捷的职权范围,因为它们的目的不是为员工创造更好的工作条件,而是彻底改变工作的性质。
还有一个方面值得考虑,敏捷对塑造办公文化的影响。不可回避的事实是,敏捷宣言的作者是一群非常特殊的人,虽然他们的经历不同,但他们的关注点基本相同。而且这个小组最后也承认当初他们的团队多样性不足,并宣称要在敏捷联盟(一个与敏捷宣言相关的非营利组织)中加入更多的声音。
但是,根据一系列敏捷相关方法的调查,如果你在工作中面临歧视或骚扰,那么就要有所警觉了。例如,许多人都证实了“结对编程”非常有效,但这种做法的前提是两位团队成员的关系很融洽。同样,敏捷的“回顾”听起来很不错,但往往会陷入互相指责的漩涡中,一切都取决于团队的领导。GitHub 前社区安全经理 Coraline Ada Ehmke 讲述了开发人员利用代码审查的过程骚扰同事的情况。虽然我们知道,消除官僚主义、等级制度和文档记录非常好,但有时我们却需要规则的保护。
对于一些失败的科技项目,敏捷是不是充当着“助纣为虐”的角色?当看到前 Facebook 经理Frances Haugen 于 2021 年 10 月在国会作证时,我想到了这一点。如果一家公司设定的目标是提高用户参与度,那么敏捷必然会鼓励开发人员朝着这个目标努力,那么是不是说即便经理认为可以让用户发表偏激的内容,开发人员也不能据理以争?是站在道德一方,还是坚持敏捷宗旨全力以赴迅速完成工作?开发人员陷入了两难境地。
考虑到当代软件可能涉及机器学习、大型数据集或人工智能等技术,这个问题变得尤为紧迫,事实证明这些技术具有潜在的破坏性。数字理论家 Ian Bogost 认为,这种快速行动和打破常规的做法恰恰说明软件开发人员根本不是“工程师”,他指出,工程是一组具有道德和社会责任的规范。敏捷承诺没有这样的责任心,它的目标只有一个:构建产品。
敏捷擅长划分功能,将它们整齐地打包成冲刺和可交付成果。这确实是整个软件工程的发展趋势,模块化或“信息隐藏”是人类管理系统的重要方式,因为系统过于复杂,任何人都无法掌控。但是敏捷将功能转变为白板上的“用户故事”,这就有可能创造出 Yvonne Lam 所说的“否认链”:整条流水作业线上没有任何人能对团队创建的产品承担全部责任。
敏捷宣言描绘了一个迷人的画面,看似软件开发拥有了民主自由。但问题在于,实际的实施注重的只是最终结果,而不是开发人员的福祉。在工作优先级一致的情况下,敏捷宣言确实可以加强开发人员的自主权,但实际上我们会面临各种冲突,比如项目经理就经常面临两难局面:一方面是对客户的承诺,而另一方面是开发人员手头需要优先完成的工作。
一家学术机构的软件工程师 Mark Matienzo 表示,“人们希望通过流程来管理无法控制的模糊性,尤其是在一些无能为力的地方,比如一些来自高层管理人员或行政部门的突发奇想。你无法影响高层的战略方向,但敏捷却让开发人员觉得自己有一定的自主权。”他直言不讳地说,“敏捷欺骗了开发人员,让他们觉得自己拥有工作的自主权,但从劳动者的角度来看,他们根本没有什么权利。”
软件开发永远都无法达成公司期望的时间计划和各项指标。现代应用程序的复杂性使得软件开发有时显得非常神秘莫测。虽然计算机最初是军用设备,但想让编程工作完全遵从资本的优先级,却异常困难。当初软件工程未能拯救软件开发,于是企业开始寄希望于敏捷,这种思维模式赋予了开发人员一定的自主性,并希望他们全力以赴达成组织的目标。然而,正如越来越多的开发人员指出的那样,这种自主权非常有限。在企业的实践中,敏捷所推崇的方法和价值观总是以企业的需求为导向。无论办公场所多么灵活,会议多么随意,最终目标依然是组织的利润。
然而,敏捷也有一些优点。有人指出,敏捷具有促进员工团结的潜力。如果团队能够获得真正的自主权,公开分享一切,也许敏捷真的能够实现承诺。也许管理层在敏捷的助力下,成为了自己的掘墓人。也许软件开发的下一次危机就来自开发人员自己。
原文链接:https://logicmag.io/clouds/agile-and-the-long-crisis-of-software/?continueFlag=0c2f362fd425fbeef707eadd88e1a6bd
— 推荐阅读 —
《新程序员001-004》已全面上市
扫描下方二维码或点击进入立即订阅