明确如何通过理解认知负荷和团队能力来帮助你做出架构风格的选择。
TLDR
-
“不要仅在单体架构和微服务架构之间选择,更重要的是根据团队能承受的最大认知负荷来设计软件。”
-
如果你的组织只有一个团队,那么应考虑调整架构以适应团队的能力。优先选择单体、紧密联系、模块化的架构。
-
如果你的组织有多个团队,可以考虑采用微服务或类似的架构,以便各团队能够独立工作。
-
认知负荷并非都相同。不同类型的认知负荷会影响团队交付高质量成果的能力。组织应该尽力减少或消除内部和外部的认知负荷,确保团队主要面对与工作直接相关的认知负荷。
-
单个团队与多团队架构的沟通边界差异很大。单个团队更适合通过代码库、文档、讨论和设计会议进行沟通。而多团队架构则更适合通过精心设计的 API(或库)来沟通,这些 API 可以简化他们各自领域的复杂性。
不要贪多嚼不烂
这篇文章的灵感来源于我正在第三次阅读的书籍《Team Topologies》中的一句话:
“不要仅在单体架构和微服务架构之间选择,更重要的是根据团队能承受的最大认知负荷来设计软件。”
我非常喜欢这句话,因为它不仅提供了一个关于选择什么样的架构的实用法则,还智慧地提醒我们不要过度野心勃勃。
因此,在选择任何类型的架构之前,你需要考虑的是,你的组织能承受多大的认知负荷来满足你想交付的产品的需求,然后进行相应的调整。
但是,如何确定认知负荷的能力呢?所有认知负荷真的都是一样的吗?让我们一起探讨这个问题……
确定认知负荷的极限
让我们探讨一下由心理学家 John Sweller 提出的三种认知负荷类型。了解这些类型将有助于我们构建更贴合用户认知能力的软件架构,并合理分配工作负荷:
1. 固有认知负荷
这是指团队在其负责领域的专业知识程度。比如,如果你的团队负责一个机器学习视觉项目 (ML vision project),但团队成员中没有人具备 AI 经验,他们最初的固有认知负荷将非常高,因为他们需要学习这一新领域。理想情况下,团队应该处理既符合他们专业知识又留有成长空间的领域,以保持工作的吸引力。适度的固有认知负荷是有益的,因为工程师喜欢提升技能,但过多则可能导致项目延误和交付高质量成果的压力。
单一团队
虽然一个团队可能跨多个功能领域并具有广泛专业知识,但这种跨领域能力是有限的。如果团队在实现目标所需的技能上存在明显差距,应考虑提供必要的培训和时间,帮助他们赶上进度。
如果你的项目需要在过多领域中具备过多专业知识,就有可能将团队变成各自专精于不同领域的个体,这样可能会降低他们作为团队合作时的成果质量。
多个团队
有多个团队意味着可以将不同领域分配给更多人,同时也提供了更多专业知识范围的选择。作为一个组织,你可能会考虑采取减少固有认知负荷的策略,例如每个团队负责不超过一个复杂领域,并提供培训或设有辅助团队,帮助其他团队在特定领域提升技能。例如,一个 SRE (Site Reliability Engineering) 团队可以帮助其他团队理解服务水平目标 (SLOs) 和一般的可观测性 (observability)。
建议
-
如果你只有一个团队可用于你的项目,而他们的专长与问题不符,可以考虑通过培训提升团队能力。
-
不要让单个团队承担太多领域的任务,以免他们变成无法协同工作和集体学习的个体。
-
拥有多个团队使你可以增加软件架构的范围,引入更多专业知识。正确匹配每个领域与相应团队,并在必要时通过培训或辅助团队来提升他们的技能。
2. 额外的认知负担
这部分涉及团队所做的一些工作,虽然它们不直接对工作成果有所贡献,却不得不去做。额外的认知负担可能因多种原因产生,很多时候这些问题不易避免或修复,从而影响到整个公司。比如,一个团队不得不处理繁琐的基础设施任务、公司流程、琐碎的杂项工作(yak shaving)、等待其他团队处理相关事务、以及公司范围内积累的技术债务,这些都属于额外的认知负担,因为它们并不直接有助于成果的实现。因此,额外的认知负担是最不受欢迎的,因为它可能在实现目标的过程中造成过多的阻碍。
除了对组织造成影响外,系统架构的类型有时也会增加额外的认知负担:
单个团队
将单个团队的工作分割成多个微服务(microservices)可能会造成额外的认知负担,因为这样做会引入复杂的通信界限,可能导致团队工作的分散。通过工作进行沟通是工程沟通的最佳方式,无论是团队间还是团队内部。跨团队合作的理想通信界限是设计良好的 API(或库),但团队内部的沟通则不同。由于团队成员对自己的工作领域已经熟悉,因此团队内部不太需要抽象化,过多的抽象化反而可能导致额外的认知负担。在这种情况下,代码的清晰度、文档、设计和讨论是沟通的关键。
如果将单个团队的工作分割成多个微服务,每个都有自己的 API,这可能会大大增加团队在保持这些 API 设计良好、用户友好和文档完善方面的工作量,并可能导致团队工作在多个仓库和不必要的界限中破碎。在这种情况下,采用单一代码库中的模块化方法可能更合适,以维持团队内的一致性和专注。
多个团队
当涉及多个团队时,将架构分割成微服务可以使他们有更多的时间来实现良好设计的通信界限(即 API),这样就不再构成额外的认知负担。由于这些 API 将由其他团队使用,因此它们有两个主要优势:
-
减少了不同团队间频繁沟通以完成工作的需求。
-
这种方式让不同团队能够自主使用其它团队工作成果的抽象层。它有效减轻或消除了团队成员不必要了解每个领域细节的认知负荷,只要他们能熟练使用 API 就足够了 – 前提是这个 API 设计得既直观又易用。
在这个情况下,API 有助于组织高效运作,因为它减少了其他团队的认知负荷和不必要的交流,帮助每个团队更快投入工作。
然而,如果你将不同领域的工作分散到多个团队,并且沟通界限没有通过精心设计的 API 或其他自助工具明确划分,你会发现团队之间需要频繁沟通以理解彼此的工作领域。这种情况远非理想,并且会产生大量不必要的认知负荷。
建议
-
确保减轻或理想情况下消除所有不必要的认知负荷,这需要工程团队和领导层的共同努力。这可以通过简化流程、避免琐碎无关的工作、通过 API 为其他团队提供领域抽象、设计不产生冗余沟通渠道的架构等方式来实现。如果目前无法减少或消除这种认知负荷,就应在分配团队任务时考虑这一因素。过多的认知负荷会限制团队的工作量和潜在质量,甚至可能导致团队成员感到疲惫。
-
一个团队负责多个微服务可能会带来沟通界限的额外工作和团队内部工作的分散。与此相反,或许更好的方法是先在一个模块化的整体架构上工作,必要时再将其拆分。
-
团队之间的沟通应主要依靠自助工具,例如 API、库、命令行界面或其他有效的方法。过多的沟通可能会导致摩擦,并在许多团队不必要地相互交流时阻碍工作流程。
3. 关于认知负荷的考虑
“相关认知负荷”指的是在解决与团队工作领域相关的问题时产生的心智负担。这种负荷能促进团队进入高效的“流状态 (flow state)”,增强开发者的幸福感,并提高成果的质量。只要团队的目标不过于密集和繁重,这种认知负荷通常是积极的。减少无关的内在和外在工作量,可以让团队更专注于核心任务。
对于单一团队
如果你只有一个团队,建议在分配任务前先缩减架构设计的范围。要考虑到团队需要处理的额外认知负荷。要知道,单个团队负责复杂的微服务架构本身就会增加额外的负担,尤其是在糟糕的工具、技术债务或公司流程带来的阻碍下更是如此。
过度拉伸团队的能力,可能导致团队成员疲劳甚至无法提供高质量的成果。最好根据团队的能力调整目标,确保安全且有效的交付。随着需求的增长,可以逐步扩大团队的能力。例如,团队可以首先构建模块化的单体应用,便于未来分割和扩展。
对于多个团队
如果你有多个团队,可以考虑将架构划分为微服务或类似结构,让各个团队独立地在自己的专业领域内工作。这样比大家共同在一个巨大的单体应用或共享代码库中工作更有效,可以减少持续的沟通压力。
当多个团队合作交付软件时,确保团队的组织结构与软件架构相匹配,并倾向于使用设计良好的 API 作为团队间的沟通方式。这样可以简化团队所需处理的领域复杂性,并减少整个组织交付工作所需的交流。
建议
-
对于单个团队,推荐采用模块化的单体架构。设计软件以匹配团队的工作能力,确保成果的高质量。考虑内在和外在的认知负荷,因为它们会影响团队处理核心任务的能力。
-
对于有多个团队且面临复杂需求的情况,推荐使用微服务架构或其他有利于团队通过设计良好的 API 进行沟通和领域抽象的架构。避免给每个团队分配超过一个复杂领域的任务。
结论
正如我们在设计组织结构图时绝不可忽视技术团队的意见,以确保其与架构设计相符合,我们在决定建筑风格时也应充分考虑团队的承载能力和工程师面临的各种认知挑战。
了解这些因素后,领导层和工程团队就能够制定出更高效的建筑设计方案,并采取措施来减少或消除那些非必要的认知负担,同时帮助工程师应对必要的认知挑战。
关于团队间沟通的深入讨论虽然重要,但它足以成为未来某篇文章的主题。
关于我
Fernando Villalba 现任 OpsLevel 的开发者关系代表,他在 IT 领域拥有逾十年的丰富经验。他的职业生涯始于 IT 支持(“试过重启了吗?”),后转为系统管理员(“绝对不要随意重启!”),再进入 DevOps 领域(“推翻重建!”)。他曾为多家市值数十亿美元的公司担任顾问,帮助他们在 DevOps 过程中发挥最大潜力。如今,他对平台工程、开发者门户和开发体验(DevEx)充满热情,并认为这是软件交付未来最闪耀的方向。
在 LinkedIn 或 Twitter 上关注 Fernando Villalba。