当从单体应用转向“微”的一切——微服务、微前端,我们会发现还有很多“东西”要研发和维护。这就引出了一个问题:该由谁来负责呢?
举个简单的例子,设想一支由 6 名开发者组成的小型团队。
这支团队已经创建并支持一款移动应用、一项 Alexa 技能、三款独立的网络应用和十五个微服务。
尽管他们成功地在整个生态系统中实现了一定的标准化,但鉴于现代软件开发的本质,它只是很多而已。Python、Django、DynamoDB、S3、React、TypeScript、Tailwind、Swift 等等都一起工作,都是为了实现用户界面、API、数据持久性、集成等等。
但对于任何一位开发者而言,这都太多了。
另外,每次 Sprint 都会有不同的改进和修复需求,而且工作很少能够在代码库中平均分配。一次 Sprint 可能要求对移动应用程序进行大量的改动,而接下来的 Sprint 可能要求主要在后端工作。
那么,问题来了:怎样才能最好地部署一支团队,以适应一次接一次 Sprint 的业务需求?换言之,我们怎样才能更好进行职责分配?
比如说,我们鼓励专业化吗?像指派 Emily 处理所有的移动开发工作,让 Joe 负责网络组件这样的。除了技术栈之外,如果我们有十几个微服务,我们会不会在它们周围划分界限,例如 Javier 负责微服务 A 和 B,Anna 负责微服务 C 和 D,诸如此类?如果他们特定领域的工作在连续数次 Sprint 都很轻松后会怎样呢?能让他们有一点空闲的时间吗?
还是说,我们应该努力优化利用率,鼓励更多的全栈、跨域文化,每个开发者都做这一切……这合理吗?
影响因素
正如开发软件一样,我们在进入一个解决方案之前,应该退一步,试图弄清楚我们要解决的问题。我认为,在考虑开发者的职责和所有权时,应该考虑以下四个方面:
显而易见的是生产力。当所有条件都一样时,我们要把团队的结构安排得尽可能好,这样才能让他们完成的工作最大化。所以,优化生产力往往是为了让开发者的工作能够与自己的技术和经验保持一定的一致性。比如,Emily 在前一次 Sprint 中从事移动应用的开发,那么她将会比那些一直在后端工作的开发者更早地开发出新的特性。
我们也要重视质量问题。和上面类似,在某个特定的代码库中拥有更多实践经验的开发者,可能会以更高的质量来实现新的特性,而不是那些只在某次 Sprint 空降到团队,却不了解结构、模式或惯例的人。即使是最优秀的开发者,在不了解代码库的情况下,也会写出蹩脚的代码。
组织往往也需要降低开发者离职的风险,以及随之而去的知识。这才是问题的关键所在,而这往往与上述目标相悖。尽管将一个又一个 Sprint 开发任务指派给一个移动开发者可以将生产力和质量最大化,但是一旦这名开发者接到 Meta 招聘者的短信时,那么组织就会处于危险的境地。
最后,我们不能忽视开发者的幸福感这个看不见的因素。不过,这件事也是非常复杂的。有些人喜欢多元化和新鲜感,所以当他们在一次又一次 Sprint 被困于同一个系统时,就可能会降低生产力或者跳槽。另一些人则更愿意看到可预见的未来,并以拥有自己的领地为荣,频繁跳槽会让他们抓狂。换句话说,我们每个人都是不同的,但确保我们能够得到满足、有挑战的机会,这一点很重要。
假设这些是需要考虑的正确因素,那么关键在于,每一家组织都要根据这些要素的“权重”来确定策略。优化最重要的是什么?可能有些是时间紧迫带来了压力(如最后期限),因此生产力必须得到优化。又或者,开发者市场是如此火爆,最重要的就是让开发者感到开心,而不是什么提高生产力。也就是说,它在很大程度上取决于环境。
本文将在此探讨“如何”做,并假定组织已经了解自己将进行优化的内容,并为团队建立职责而选择一些模式。但是有哪些模式可选呢?下面是我遇到过的一些常见模式。
所有权模式
我们经常会在代码所有权的策略上做文章。有时候很默契:每个人都尊重这样的安排:Joe 负责网络的事情,Emily 负责移动开发,我负责支付微服务等等。其他时候,这也是正式的安排:管理层聘请 Joe 为网络开发者,Emily 为移动开发者等。无论哪种情况,实践中都是类似的:当新的特性或修复问题出现时,我们会根据“拥有”的东西进行划分。
这让我们(从个体角度来说)最大限度提高了生产力,并且(通常)提高了质量。但是,它也存在一定的缺陷。
首先,人们可以储存不同系统的第一手知识,如果有人“中了彩票”或“被公交车撞了”,企业就会面临巨大的风险。此外,如果开发者想要学习新事物,“所有权”有时就像一种束缚。
最后,必须指出的是,尽管个人生产力得到了提升(因为开发者很熟悉他们的代码库),但集体的生产力往往会随着所有权的增加而下降。正如上面所讨论的,由于工作负荷在每次 Sprint 并不能做到完全平衡,因此可能会造成拥有所有权的开发者出现“盛宴”和“饥荒”的情况。例如,在一次 Sprint 中,他们代码库中的工作超出了所有者能够处理的范围,这导致了很大的瓶颈(或加班到深夜!),但到了下个月就没有什么事情可做了,而这个所有者或多或少就是闲着的。
自由竞争模式
当组织感受到所有权带来的种种痛楚时,他们倾向于放弃任何策略,只是随心所欲:即自由竞争。这个模式就像它听起来一样的简单。一位经理看到那里有一堆工作,就说:“嘿,你,码农,赶紧干活吧!” 然后就这样了。
尽管这样的策略的确可以保证总体分配均衡(即 Emily 在没有移动工作的时候也不会无所事事,因为她被拉去处理 Python 服务),但这种模式可能既累人,又充满质量问题。如果我们没有与我们所从事的代码库建立长久联系,那么我们的工作就只是权宜之计,并以无知为指导。我们在短期内采用了一种古怪的修复方法,因为不知道更好的办法,或者我们并不关心——下一次 Sprint 我们就会在不同的代码库里了!正如他们所说,“谁也不会把租来的汽车洗干净。”
这种自由竞争的模式往往是由管理层推动的,他们理想化地认为我们是可替换的勤杂工(也就是传说中的全栈开发者),无论什么层级、系统或业务领域,都能够迅速、优雅而轻松地解决任何技术挑战。当然,这是无稽之谈。除了最微不足道的系统或者最出色的开发者,其他的都太复杂了,如果没有足够的时间来提高我们的能力,就不可能掌握所有的东西。
管理权模式
现在,在所有权和自由竞争这两个极端之间,存在着一种管理模式(或称监护权)。类似于所有权,开发者会在自己最擅长的领域管理特定的代码库,他们可能在这个项目中做了大部分的初始工作,他们的名字在代码中随处可见,但是他们并不是什么都要做。然而,必须在做出变更时,至少要征求他们的看法,让他们参与到生产问题的分类或者是讨论设计的变更。
比如,Emily 可以在门户网站工作量繁重的时候过去帮 Joe 一把,而在事情平息下来的时候再回到她的移动应用开发工作。换句话说,这种模式同时平衡了个人和集体的生产力。此外,由于开发者对自己工作之外的其他领域已经有了一定的了解(即可以学到一些新知识),所以这种模式在风险减轻和开发者的幸福感之间起到了很好的平衡。
管理权的重要之处在于,尽管不像所有权那样正式,但是它还是被清楚地界定和实施。该模式下至少有一些事情要做:应当有一份管理者清单,可以定义每个管理者的管理范围;GitHub(或者其他 SCM 工具)应当被配置成由管理者批准所有的拉取请求,并且管理者应当有充足的时间对其组件进行必要的“管理”。如果这方面没有特定的形式和纪律,所有的事情都会顺着滑坡滑下去,直至处于自由竞争的坑中。
接管权模式
最后,一种在大型组织中非常流行的模式可能也很重要,就是“接管权”,有少数被选中的人(通常是宇航员架构师)负责“拥有”一切。他们拥有丰富的知识、作出重大的技术决策,并设计业务逻辑和结构,但实际的具体工作由每个开发者来完成,而且往往是以自由竞争的方式进行。
这种模式在理论上非常有效。通过接管者与动手的开发者分享他们的“智慧”,为快速、高效的解决方案开辟了一条途径,实现了效率和质量的优化。有了接管者的协助,开发者可以自由出入代码库,并通过接管者来迅速进入状态。
但在实践中从未产生过这种影响。没有任何实践经验的接管者会迅速与技术现实脱节,而且不能真正帮助开发者实现某些改进或修补某些 Bug。开发者可能要耗费相同的时间去改进,同时,由于基本上将自己的自主权(和创造力)交给了那些能够指挥他们的接管者,所以他们可能会感到挫败。
作为一个曾经扮演过接管者角色的人,我认为这种模式对任何人都很糟糕,这就是为什么我尽量避免这种类型的角色。
这些只是我遇到的几种分工模式,我也很想听听你的想法和经验。
作者介绍:
Ben Northrop,毕业于卡耐基梅隆大学,自诩“老”程序员,写博客将近 20 年。2017 年,创办了 Highline Solutions,是一家专注软件架构和全栈开发的咨询公司。
原文链接:
https://bennorthrop.com/Essays/2022/code-ownership-stewardship-or-free-for-all.php
评论