模块化架构能提升软件交付效率吗答案是肯定的但前提是不能只把它当作一项单纯的技术改造。本文讲述了一家大型企业如何通过向模块化架构转型缓解移动应用开发在业务增长过程中暴露出的多重问题。他们最终发现模块化并不只是架构层面的解决方案。它的影响远远超出代码结构本身还会延伸到业务沟通、团队组织方式以及开发者体验等方面。只有同时关注这些因素模块化架构才能真正释放价值。通过这种系统性改造该企业显著提升了移动应用的交付表现。本文将说明移动应用扩展问题、技术架构与团队结构之间的直接关系。在过往与大型企业合作的实践中我们发现不同组织在扩展移动业务时会遇到各不相同的问题和诉求。但在大型企业的移动应用开发中以下两个问题尤为常见面向不同市场的应用推出新功能所需时间越来越长由于内部各市场应用之间缺乏兼容性与复用能力导致功能差异不断扩大。本文记录了某客户在解决这些问题时经历的模块化架构转型过程。这个案例表明很多时候组织选择的方案本身并非错误问题在于它们没有理解这些方案之间的内在联系。因此即使采用了看似正确的做法也未能获得预期收益。在这个案例中该组织通过让团队拓扑与模块化架构相匹配并持续投资开发者体验最终实现了平均交付周期缩短 60%、开发成本降低 18 倍、团队启动成本降低 80%。识别移动应用交付效率下降的信号即便出发点良好软件质量和交付表现也常常会随着时间推移而下降。功能发布时间变长服务中断更严重恢复时间更久这些都会让产品和开发团队感到挫败。其中一部分原因确实来自代码本身及其维护方式。然而如果把问题完全归咎于代码质量就过于简单化了。实际上这是一个多因素共同作用的结果。随着时间推移产品决策、组织沟通结构、技术债务以及僵化的架构会相互影响最终导致交付效率下降。本文讨论的这家公司是一家规模较大的零售企业。它的移动应用在推出新功能时所需时间正在逐渐拉长。起初该组织正确地意识到问题来自应用规模扩大后复杂度不断上升现有开发团队越来越难在保持已有功能一致性的同时继续快速添加新功能。于是他们最初的应对方式是“增加开发人员”。在一定阶段这确实起到了一些作用。但很快他们发现增加人手也带来了新的问题沟通压力显著上升技术负责人开始承担越来越重的协调负担。海外某些互联网公司曾提出“两张披萨团队”原则即一个团队的规模应该小到两张披萨就能喂饱。其背后的逻辑是限制团队规模可以避免团队把过多时间花在沟通协调上而不是实际创造价值上。这个理念本身很有道理也在一些企业中取得过成效。然而当组织面对一个已经过于庞大的既有团队时往往会机械地照搬这种做法试图通过拆分团队来减轻负担。但如果只拆团队而不调整系统边界、责任边界和协作方式问题反而可能更加严重。通过限制认知负荷提升团队效率这家公司也遇到了类似情况。它曾经规模较小业务也持续增长但随着功能、职责和团队成员数量不断增加组织逐渐无法维持过去的交付速度。面对迫近的功能交付期限以及即将进入的多个品牌市场他们采取的措施是将原有团队拆分为多个规模更小、彼此相关的子团队。每个团队独立运作分别负责一个市场尽管这些市场中的客户旅程非常相似。但事实证明这种做法让情况变得更糟。团队拆分只是把沟通负担从技术领导层转移到了实际交付团队身上却没有真正降低团队需要理解和处理的上下文复杂度。当我们意识到沟通与协调正在占用价值创造者越来越多的时间时最初的建议是采用“限制认知负荷”的思路。也就是说团队应该围绕各自能够承担的复杂领域进行组织而不是让每个团队都面对整个系统的复杂度。软件内部的领域边界可以用来组织前面提到的小规模团队。这样一来每个团队的工作负担会明显降低团队目标更清晰使命感更强沟通和上下文切换也能围绕共同目标得到简化。从理论上看这似乎是解决问题的理想方案。但如果孤立地看待它也可能产生误导。只有当应用的领域边界被清晰定义并且在代码中始终得到遵守时限制认知负荷的优势才能真正发挥出来。领域驱动设计与限界上下文治理领域驱动设计Domain-Driven DesignDDD有助于将复杂业务逻辑划分为更易管理的部分并为每个部分定义统一语言和模型。然而将应用拆分成多个领域只是持续治理过程的一部分。严格管理限界上下文与定义领域本身同样重要。在检查客户应用代码时我们发现了一个常见问题组织最初投入了大量精力来正确定义和组织领域职责但随着应用持续增长这种规范逐渐被削弱。来自业务和技术相关方的反馈表明为了满足紧急产品需求团队不断走捷径已经成为常态。这反过来导致技术债务持续累积并进一步拖慢价值交付速度。随着代码发布变得更加困难、问题调试成本不断增加应用的关键交付指标也呈现出明显下降趋势。通过常用代码分析工具我们发现了更多限界上下文管理不善的信号。代码库已经变得高度耦合且缺乏内聚性。高度耦合的代码很难在不影响系统其他部分的情况下修改低内聚性的代码则承担了许多与自身职责不一致的关注点使人难以理解其真正用途。随着客户应用中每个领域的复杂度不断提升这两个问题也随时间进一步加剧。另一些信号则与认知负荷有关。应用中各领域之间边界不清或依赖关系混乱意味着对某个领域的修改很可能无意中影响其他领域。我们注意到正因如此开发团队必须掌握多个领域的知识才能解决任何可能出现的问题。这显著增加了他们的认知负荷。对该组织而言严格控制每个限界上下文是确保知识与责任归属一致的重要一步。这既限制了任何变更的“影响半径”也限制了完成变更所需的工作量和知识范围。此外加强对技术债务累积与偿还的控制也有助于确保任何短期的“领域边界侵蚀”在扩大之前被识别、拒绝或纠正。该组织的移动应用还缺少另一项重要能力选择性复用。如前所述当时企业内部已经存在多个成熟的品牌市场应用。这些应用之间功能一致性较低同时由于各市场都希望保持一定独立性也很难将它们整合为一个统一移动应用。系统内部的紧密耦合降低了现有功能在其他市场中复用的能力。仅仅为了在另一个市场复用某个领域功能就必须迁移现有移动应用的大量内容这带来了高昂的集成成本和持续维护成本。通过适当管理领域限界上下文组织减少了对其他领域的直接依赖迈出了实现模块化的第一步。但很快我们发现这还远远不够。超越单个应用的模块化领域场景一边界清晰的单体以单个应用中的功能请求为例功能请求会交给负责相关领域的应用团队。由于限界上下文受到严格保护变更的影响范围会被限制在该领域内部。也就是说功能可以独立构建、测试甚至部署而无需修改应用的其他部分。这会加快产品上市速度并允许多个功能在隔离环境中并行开发。看起来非常理想。确实在单一市场环境下这种方法效果很好。然而当我们试图解决第二个扩展问题也就是由于缺乏复用能力而导致的市场功能差异时问题就开始出现了。场景二下一个市场机会该组织推进领域模块化的下一步是将“边界清晰的单体”中的部分功能迁移到其他现有市场应用中从而快速节省开发成本。这需要创建一个通用框架。这个框架允许功能或领域在原始应用之外被其他移动应用复用。为了更清楚地说明这一做法我们以两个市场应用为例一个服务于英国市场另一个是服务于美国市场的新应用。美国应用团队决定除了美国市场特有的领域之外还希望在自己的应用中使用“积分”和“结账”这两个领域于是他们将这些领域导入自己的应用。对公司而言这似乎意味着与过去在不同市场重复开发同类领域功能相比市场团队的开发成本可以降低一个数量级。但故事并没有就此结束。在急于推动模块化的过程中组织忽略了既有沟通结构而这些结构最终决定了工作的优先级。继续前面的例子美国团队在自己的市场中使用这些领域后希望为其中一个导入领域添加新功能。由于他们并不拥有该领域也不了解其完整上下文于是他们联系英国应用团队并提交了功能请求。英国团队接受了这个请求也认为它“听起来不错”但他们目前正在处理英国市场相关方提出的需求因此无法明确什么时候才能开始这项工作。我们发现领域功能优先级上的利益冲突限制了共享功能消费者能够获得的复用价值。当市场团队因为导入领域迟迟没有进展而感到沮丧时这一点尤其明显。我们曾提出过一些解决方案。例如消费者团队也许可以创建自己的领域版本并围绕该版本组建团队。但正如我们所知为了添加少量功能而学习并拥有整个领域是低效的。而且分支版本会给未来升级、共享以及跨市场功能一致性带来问题。另一个方案是通过拉取请求进行贡献。然而这会给贡献团队带来额外认知负担他们被迫在第二个代码库中工作同时仍然依赖主领域团队提供跨团队贡献支持。例如我们无法确定领域团队是否有足够时间在完成自身市场功能开发之外再提供架构指导或代码审查。场景三与市场无关的领域显然问题出在团队组织方式上。康威定律指出组织会设计出与自身沟通结构相匹配的系统。前面的例子描述了这样一种情况从技术角度看功能已经模块化但从所有权角度看它仍然是单体式的——“积分系统最初是为英国应用开发的所以它属于英国团队”。针对这种情况一种可能的应对方式是采用“反向康威策略”。该策略强调主动改变开发团队结构使其能够促成期望中的技术架构。在后续实践中我们基于前面的场景调整了团队结构使其与模块化架构保持一致。各个领域不再隶属于某个特定移动应用而是成为由独立开发团队负责的产品能力。调整之后应用团队之间的关系发生了变化他们不再依赖其他市场团队来提供功能。取而代之的是一种更适合用“消费者”和“提供者”描述的新关系。领域团队向市场应用提供功能市场应用使用这些功能并反馈新的功能需求从而推动领域产品持续演进。这次重组相较之前最大的优势是明确了关注点。此前我们曾描述过当一个市场要求修改另一个市场所拥有的领域时就会出现利益冲突。将领域从其所属市场中分离出来后团队关注点也随之变化不再只是为了某个市场的局部利益构建功能而是更全面地构建能够满足领域用户需求的能力。成功的衡量标准也随之变化。它不仅包括市场采用情况还包括最终用户反馈。任何新功能的评估都应基于它能否为领域及其用户整体带来价值。关注开发者体验支撑模块化架构落地至此该组织已经拥有了一种支持跨市场组件模块化的团队拓扑。各个自主团队被分配到相应领域并负责这些领域的持续开发。市场应用则被简化为配置容器。从概念上看这一切都说得通。我们可以轻松画出反馈如何从消费者流向提供者的流程图也可以提出一些高层次的理想假设例如“所有领域都可以独立开发和部署”或者“消费者只需要引入任何想要复用的领域就能构建自己的应用”。然而在实践中我们发现这些都是难以解决的技术问题。例如如何在多个独立领域团队之间保持用户体验和品牌一致性当你只负责整个应用的一部分时如何进行移动应用开发如何确保领域易于发现、易于测试并且能够跨市场兼容这些问题并非无法解决但它们会带来沉重的认知负担。而在当时的组织结构中并没有明确的负责人。因此我们设立了新的负责人。用平台领域解决模块化架构的核心问题我们将新的领域归类为“平台”。“平台”本质上是一个覆盖范围很广的概念。我们用它来描述那些能够帮助团队在既定架构下独立交付的工具、能力和指导。新的平台领域团队延续了前面建立的提供者 / 消费者关系并负责提升团队在平台内构建应用和领域时的开发者体验。在这类转型中研发过程的可视化和数据流转同样关键。企业通常需要一套贯穿目标、反馈、需求、计划、开发、测试、发布与知识沉淀的研发管理体系例如 PingCode 这类智能化研发管理工具就可以帮助团队把模块化架构下的需求流转、项目协作、测试发布和经验沉淀串联起来让研发管理更加自动化、数据化和智能化。我们的假设是更好的开发者体验将有助于推动新架构被更广泛地采用。但“开发者体验”Developer ExperienceDX是一个相当宽泛的概念。因此我们认为有必要明确新团队需要具备哪些能力才能真正提供良好的开发者体验。我们将开发者体验细化为一系列必要能力。首要能力是高效的启动流程。任何通用框架都不可避免地存在学习曲线。良好的开发者体验目标就是尽可能降低这条学习曲线的陡峭程度。合理的默认设置和入门套件是一种非强制性的方式可以减少用户上手时的阻力。以下是我们为平台领域定义的一些承诺你只需一条命令就可以快速生成一个新的领域其中包含所有相关移动依赖、通用 UI/UX、遥测能力和 CI/CD 基础设施。你可以独立构建、测试并运行自己的领域。你的领域被打包进应用运行时应当与独立运行时保持一致。请注意这些承诺描述的是开发者生产力平台中的自助服务体验。因此我们认为一个高效的开发者平台应该让专注于最终用户功能的团队聚焦于自身使命而不是被看似无穷无尽的低效流程消耗。我们为平台领域确定的第二项必要能力是“技术架构即服务”。在组织内部架构职能同样会受到康威定律的影响导致架构决策责任集中在一个独立部门中并与真正需要指导的团队脱节。我们的自主团队虽然能够做出自己的决策但往往仍然需要一定程度的技术指导以便在原则、模式和组织治理方面保持一致。当我们把这些需求扩展为按需服务时就形成了如下模式我们提供的最佳实践会附带可直接使用的示例或可执行的实际步骤。我们会持续掌握每个应用对领域的使用情况并在需要时协调跨领域协作。通往生产环境的路径应当清晰、可见且正确。我们会与你们共同协作。请注意这些承诺体现的是一种服务型领导与团队之间的关系。它承认每个人都对架构负有责任。这与一些组织中常见的命令与控制式架构治理策略截然不同。关于平台领域还有最后一点值得回顾而且它与前面的例子密切相关。根据我们的经验一个成功的平台团队必须深入理解客户需求。在海外某些制造企业的精益实践中有一个理念大致可以理解为“亲临现场、亲自观察”。它强调只有亲自到问题发生的地方才能真正理解问题并找到解决方案。我们认识到一个致力于提升开发者体验的团队必须能够设身处地理解使用其产品的开发者才能真正理解他们的需求。最初组建平台团队时我们并没有给予这一原则足够重视结果导致各独立团队各自为政。最终出现了重复建设、系统不兼容以及对架构缺乏信任等问题而这些问题都需要花费时间来纠正。模块化架构转型带来的结果我们已经讲述了如何对移动应用进行模块化改造。那么随着时间推移这种改造效果如何获取实证数据并不容易。根据我们的经验在同一组织内同时拥有一个旧版应用和一个采用新架构的应用并且这两个应用使用相同领域、各自又具备独立交付指标这种情况并不常见。不过幸运的是在这个案例中该组织规模足够大可以一次只改造一个应用。为了得出这些结果我们比较了两个功能相似的零售应用。一个是高耦合、低内聚的旧版应用尽管它的开发团队高效且成熟我们称之为“旧版单体应用”。另一个应用则是前文描述的模块化重构实践成果它拥有定义清晰、管理有序的限界上下文并由较新的独立领域团队支持我们称之为“限界上下文应用”。这里交付周期是一个很好的衡量指标因为它代表代码变更所需的时间并且不包括将应用推送到应用商店所需的时间。后者是一个时长可变的过程与应用架构类型无关。移动应用类型交付周期旧版单体应用17 天限界上下文应用平均值10.3 天即使对第二个应用中所有领域团队的交付周期取平均值也可以看到与由更成熟团队开发的旧版应用相比新架构下的交付周期仍然显著缩短。第二个比较关注的是选择性复用能力或者更准确地说是缺乏这种能力所带来的成本。在这个场景中我们考察了组织内的两款移动应用。其中一款应用需要现有领域功能但没有复用选择只能自行开发另一款应用则采用模块化设计能够即插即用已有领域功能。我们忽略了上线流程中的常规步骤因为它们不会影响这里的衡量指标。相反我们专注于开发团队可控的部分并衡量由一对开发人员与一名全职设计师合作完成的开发流程从预生产阶段的“产品验收”到最终开发完成。集成类型平均开发时间非模块化90 天模块化5 天以上差异显著的数据表明在存在明确业务需求的场景中模块化架构具有强大的价值。顺便说一句我们排除在外的外部因素同样值得关注。优化开发绩效往往会暴露整体流程中的其他瓶颈。例如如果发布一个版本需要 6 个月而审批流程需要 1 个月那么审批在整个流程中的占比相对较小。但如果开发周期可以缩短到 5 天而审批仍然需要 1 个月那么合规审批就可能成为下一个需要优化的瓶颈。上述结果没有体现的另一项优势是围绕特定领域组建的团队对集成活动产生的影响。我们发现自主领域团队会自然而然地将自己的成员嵌入市场应用团队以加快集成进程。我们认为这源于领域团队关注点的转变领域产品的成功取决于它被市场采用的程度。我们发现影响采用率的因素可以理解为两个同心反馈回路。外层回路是领域消费者也就是应用容器的良好集成体验。这是一个以开发者为中心的反馈回路衡量标准是消费者能否轻松地将某个领域配置并集成到整体品牌产品中。内层回路是良好的最终用户体验即消费者所服务的市场客户是否接受完整流程其中包括被集成进来的领域。糟糕的消费者体验会影响采用率并最终可能导致领域团队与真实用户脱节。我们发现那些与消费者团队紧密合作并且能够直接接触最终用户的领域团队拥有最快的反馈循环因此也最容易取得成功。最后还值得提到平台领域带来的一个对比。开发一项新的领域功能非常耗时也会增加整体功能开发成本。正如前文所述平台团队的目标是通过识别并优化流程中的痛点来缩短开发时间从而提升开发者体验。当我们把这一模型应用到模块化架构中的领域团队时发现每个团队的启动成本降低了 80% 以上。原本预计需要一周才能完成的工作两个人只用一个下午就能完成。模块化架构的局限性现在你应该已经比较清楚地看到了移动端模块化架构的优势。但在对摇摇欲坠的单体应用进行大规模改造之前务必记住这些方法的局限性。首先也是最重要的一点这种架构转型需要长期投入大量时间和精力。它只应当用于解决与产品上市速度相关的重大业务问题。其次赋予领域团队自主权既可能带来好处也可能带来挑战。平台团队可以提供合理默认设置作为通用实现但最终选择权仍然在各个团队手中。当然如果领域团队希望自己的能力被市场接受那么在平台要求方面达成共识例如统一 UI/UX对他们而言是有利的。然而要管理来自相似内部依赖或多种设计模式所造成的系统膨胀并不容易。如果忽视这个问题任由整个应用不受控制地增长最终会导致糟糕的用户体验。我们再次发现对技术领导力的投入加上强有力的护栏和指导原则可以通过架构与设计监督、指导以及最重要的沟通来缓解这一问题。总结模块化架构需要与团队结构共同演进综上所述本文开头指出了采用多应用策略的组织中常见的两个重大交付问题新功能上线时间不断延长以及内部相似应用之间的功能差异持续扩大。我们论证了解决这些问题的关键并不在于围绕技术架构、团队结构或技术债务制定某一个单一策略而在于让这些方面协同演进形成一套综合策略。首先我们展示了如何通过演进团队结构来支持所需的模块化与领域中心架构从而降低认知负荷和上下文负担同时赋予团队独立开发的自主权。接着我们展示了如何自然地将团队和领域提升到与原始应用或市场无关的层面以及这一转变如何缓解应用单体架构中固有的康威定律影响。我们还观察到这种转变会自然形成消费者 / 提供者关系。最后一个同步转变是识别并投资“平台”领域用以解决团队与领域解耦后产生的核心问题。综合以上因素我们成功将市场应用中所有模块化领域的平均交付周期缩短了 60%。此外与从零开始编写相比将模块化领域集成到市场应用中使开发成本降低了 18 倍。更重要的是由于新领域启动成本降低了 80%并且有平台团队持续提供支持我们对工程效率的投资让模块化架构真正得以发挥作用。对这位客户而言这些节省意味着他们能够抓住过去因投资回报率过低而被认为不值得投入的市场机会。而在过去多年里这些机会一直被竞争对手占据。关键在于在合适条件下与团队结构紧密匹配的模块化架构能够为组织带来巨大收益。虽然该组织在合作期间取得了显著成果但这些成果仍然属于具体案例。在采取行动之前务必花时间理解自身所处的环境寻找相关信号和反模式。此外切勿低估构建这类生态系统所需的前期投入和持续努力。草率行动很可能会制造更多问题。但是只要你接受自身情况的独特性抵制“照搬照抄”的诱惑并持续关注同理心、自主性以及能够支撑架构的沟通渠道那么你完全有理由复制这个案例中的成功经验。