本文的翻译是专门为“ DevOps实践和工具”课程的学生准备的。
本文讨论了软件开发中代码结构和组织结构之间的关系。 我将讨论为什么软件和团队无法轻松扩展,我们在自然界和Internet上可以学到什么教训,并说明如何减少软件和团队的连接性以克服扩展问题。
本文基于我在大型软件系统开发方面20年的经验以及
《加速:精益软件和DevOps的科学:建立和扩展高性能技术组织》 (Nicole Forsgren,Jez Humble和Gene Kim)一书的印象。研究证据来支持我在这里的大部分主张。 强烈建议您阅读这本书。

软件和命令无法缩放
通常,第一版(可能由一两个人编写)非常简单。 它的功能可能有限,但是可以快速编写并满足客户要求。 在此阶段与客户的交互非常好,因为客户通常与开发人员直接联系。 任何错误都可以快速修复,可以轻松添加新功能。 片刻之后,速度变慢。 2.0版花费的时间比预期的要长。 修复错误更加困难,并且提供了新功能,但并非如此简单。 这样做的自然答案是向团队中增加新的开发人员。 尽管似乎团队中每增加一名员工都会降低生产力。 感觉随着软件复杂性的增加,它会萎缩。 在极端情况下,组织可能会发现他们使用的程序的支持非常昂贵,几乎不可能进行更改。 问题是您无需为此付出任何“错误”。 非常普遍,可以说这是软件的“自然”属性。
为什么会这样呢? 有两个原因:与代码和团队相关的原因。 代码和命令都无法很好地扩展。
随着代码库的增长,一个人越来越难以理解它。 一个人有固定的认知界限。 而且,尽管一个人可以牢记一个小系统的细节,但是直到它超出其认知范围为止。 一旦团队发展到五人或更多,一个人几乎不可能意识到系统的所有部分是如何工作的。 当没有人了解整个系统时,恐惧就会出现。 在大型的,紧密耦合的系统中,很难理解任何重大更改的效果,因为结果没有本地化。 为了最大程度地减少更改的影响,开发人员开始使用变通办法和代码重复,而不是识别通用功能,而是创建抽象和概括。 这使系统更加复杂,加剧了这些负面趋势。 开发人员不再对他们不了解的代码负责,也不愿进行重构。 技术债务正在增加。 当最优秀的开发人员离开后,他们可以轻松地在其他地方找到工作时,这也会使工作变得令人不愉快和不满意,并激发“人才流失”。
团队也没有规模。 随着团队的成长,沟通变得更加复杂。 一个简单的公式起作用:
c = n(n-1)/2
(其中n是人数,c是团队成员之间可能的联系数量)随着团队的成长,她对沟通和协调的需求成倍增长。 如果超过某个团队,一个团队很难保持完整的结构,并且人类自然的社会倾向会分成较小的小组,这将导致非正式小组的形成,即使管理层不参加也是如此。 与同事的交流变得更加困难,并且自然会被新的领导者和自上而下的交流所取代。 团队成员从系统中的同伴转变为常规生产工人。 动机受挫,由于
责任分散的
影响,没有主人翁感。
管理层通常在此阶段进行干预,并正式着手建立新的团队和管理结构。 但是,正式或非正式都没有关系,大型组织很难保持动力和兴趣。
通常,经验不足的开发人员和管理不善归咎于这些扩展病理。 但这是不公平的。 扩展问题是软件不断增长和发展的“自然”特性。 如果您没有在早期阶段发现问题,不了解偏差点并且不花任何精力来解决问题,通常会发生这种情况。 软件开发团队不断建立,世界上软件的数量不断增长,并且大多数软件相对较小。 因此,通常,由没有大规模开发经验的团队创建成功且正在开发的产品。 期望开发人员认识到拐点并了解规模问题开始显现时该怎么办是不现实的。
自然扩展课程
我最近读了
杰弗里·韦斯特(Geoffrey West)的优秀著作
《规模》 。 它讨论了生物和社会经济系统中的规模数学。 他的论点是,所有大型复杂系统都遵守规模的基本定律。 这是一本引人入胜的书,我强烈推荐。 在本文中,我想着重谈谈他的观点,即许多生物和社会系统的扩展都非常好。 看哺乳动物的身体。 所有哺乳动物都具有相同的细胞类型,骨骼结构,神经和循环系统。 但是,鼠标和蓝鲸之间的大小差异约为10 ^ 7。 大自然如何对大小不同的生物使用相同的材料和结构? 答案似乎是进化发现了分形分支结构。 看那棵树。 它的每个部分看起来像一棵小树。 哺乳动物的循环系统和神经系统也是如此,它们是分支形的分形网络,肺或血管的一小部分看起来像整个系统的较小部分。

我们可以从自然界中汲取这些想法并将其应用于软件吗? 我认为我们可以学习重要的教训。 如果我们可以构建由小部件组成的大型系统,这些小部件本身看起来像完整的系统,则可能会包含影响大多数程序成长和发展的病态。
是否有可以成功扩展几个数量级的软件系统? 答案是显而易见的-Internet是具有数百万个节点的全球软件系统。 子网看起来和工作起来像整个Internet的较小版本。
松耦合软件的迹象
隔离大型系统中分离的,松散耦合的组件的能力是成功扩展的主要方法。 实际上,Internet是松散耦合体系结构的一个示例。 这意味着网络上的每个节点,服务或应用程序都具有以下属性:
- 使用通用的通信协议。
- 使用与其他节点的明确合同来传输数据。
- 通信不需要特定的实现技术知识。
- 版本控制和部署是独立的。
Internet是可扩展的,因为它是通过一组定义明确的协议进行通信的节点网络。 节点仅通过协议进行交互,交互的节点不应该知道协议的实现细节。 全局Internet并未部署为单个系统。 每个节点中都有其自己的版本和部署过程。 各个节点彼此独立出现和消失。 提交Internet协议是对整个系统真正重要的唯一事情。 每个节点的创建者,创建或删除的节点,版本,使用的特定技术和平台,都与整个Internet无关。 这就是我们所说的松散耦合软件。
组织松散耦合的迹象
我们可以按照相同的原则扩展团队:
- 每个子团队应该看起来像一个小型软件开发组织。
- 内部流程和团队沟通不应超出团队范围。
- 不应在团队外部讨论用于实施软件的技术和过程。
- 团队应该仅在外部问题上相互交流:共同的协议,功能,服务水平和资源。
小型开发团队比大型开发团队更有效率,因此您需要将大型团队分成几个小组。 自然和互联网的经验教训是,子组应该看起来像单个小型软件开发组织。 它们有多小? 理想情况下,从一到五个人。
重要的是每个团队看起来像一个小型独立软件开发组织。 其他组织团队的方式效果不佳。 通常有一种将大型团队划分为职能部门的诱惑。 因此,我们有一个架构师团队,一个开发团队,一个DBA团队,一个测试人员团队,一个部署团队和一个支持团队,但这并不能解决我们上面讨论的任何扩展问题。 如果您想避免瀑布式的项目管理,则所有团队都应参与功能的开发,并且通常应迭代进行。
这些职能团队之间的沟通障碍正成为有效及时交付的主要障碍。 团队之间紧密联系,因为他们需要共享重要的内部细节才能一起工作。 此外,不同团队的利益也不尽相同:开发人员通常会因新功能,质量测试人员和对稳定性的支持而获得奖励。 这些不同的利益可能导致冲突和不良结果。 如果开发人员从未阅读过日志,为什么还要担心它们呢? 如果测试人员对质量负责,为什么还要关心交货?
相反,我们应该组织团队以支持业务功能的松散耦合服务或逻辑功能组。 每个子命令应设计,编码,测试,部署和维护自己的软件。 这种团队的成员很可能是广泛专家,而不是狭窄专家,因为在小型团队中,有必要将这些角色分开。 他们应该关注流程的最大可能自动化:自动化测试,部署,监视。 团队必须选择自己的工具并为其系统设计体系结构。 尽管用于服务交互的协议应在组织级别确定,但用于实现它们的工具的选择应委托给团队。 这与DevOps模型非常吻合。
团队所具有的独立性水平反映了整个组织的联系水平。 理想情况下,组织应照顾软件的功能,并最终照顾团队提供的业务价值以及团队资源的成本。
在这种情况下,软件架构师将扮演重要角色。 它不应专注于团队使用的特定工具和技术,也不应该干扰服务内部架构的细节。 相反,它应该关注协议和不同服务之间的交互以及整个系统的运行状况。
康威的反律:组织结构必须为目标体系结构建模
弱的软件一致性和弱的团队一致性如何结合在一起?
康韦定律指出:
“组织设计系统限于复制该组织的通信结构的设计。”
这是基于以下观察:软件系统的体系结构将反映创建该软件系统的组织的结构。 我们可以通过翻转来“破解” Conway的法律。 组织我们的团队以反映我们期望的架构。 考虑到这一点,我们必须使松散耦合的团队与松散耦合的软件组件保持一致。 但是,这应该是一对一的关系吗? 我认为理想上是。 尽管由一个小型团队从事几个松散耦合的服务似乎很好。 我要说的是,团队扩展的拐点比软件要大,因此这种组织形式似乎可以接受。 重要的是,即使软件组件中的某些是由一个团队开发的,也应保持软件组件的独立性,各自的版本控制和部署。 如果团队规模太大,我们希望能够将其拆分,并将已开发的服务转移到不同的团队。 但是,如果服务紧密耦合或共享流程,版本控制或部署,我们将无法做到这一点。
我们必须避免多个团队在同一组件上的工作。 这是一种反模式。 从某种意义上说,这甚至比具有一个大型代码库的一个大型团队的工作还要糟糕,因为团队之间的沟通障碍会导致人们更加缺乏所有权和控制感。

创建松散耦合软件的松散耦合团队之间的交互被最小化。 再次以Internet为例。 通常,您可以使用由另一家公司提供的API,而无需与它直接进行任何通信(如果过程很简单并且有文档)。 当团队互动时,不应讨论内部团队开发和实施过程。 相反,应该讨论功能,服务级别和资源。
管理松散耦合的团队以创建松散耦合的软件应该比其他方法容易。 大型组织应专注于在功能和服务级别方面为团队提供明确的目标和要求。 资源需求应来自团队,尽管组织可以使用它们来衡量投资回报率。
松散耦合的团队开发松散耦合的软件
软件和团队之间的弱连接是建立高效组织的关键。 我的经验证实了这一点。 我曾在按职能,软件级别甚至客户分开的团队来组织工作。 我还在单一代码库的大型混乱团队中工作。 但是在所有这些情况下,上面都提到了缩放问题。 当我的团队是一个成熟的部门,独立地从事独立服务的创建,测试和部署时,最愉快的经历一直是。 但是您不必依靠我的生活故事。 加速(如上所述)具有研究证据来支持这种观点。
如果您已阅读完本材料,建议您观看有关“ DevOps生命中的一天”主题的开放式网络研讨会的录制。