跳到正文
Shopify Engineering·· 2 天前精选AI 评分82

Shopify 详解如何在 12 周内用 AI 智能体重构移动端 App

How we rebuilt the Shopify app in 12 weeks

AI 导读

30 名 Shopify 工程师在 12 周内借助 AI 智能体,将包含 300 多个界面的移动端 App 从 React Native 彻底重构成原生 Swift 和 Kotlin。

推荐理由

原文详细复盘了用智能体规模化重构大型应用的瓶颈转移与架构解法,为工程团队落地 AI 辅助开发提供了可迁移的流程参考。

正文 · AI 翻译

30 名工程师,仅用 12 周时间,就将 Shopify 应用从 React Native 彻底重构成 Swift 和 Kotlin 原生版本。这款应用拥有 300 多个界面、主屏幕与锁屏小组件、Apple Watch 配套应用、表盘功能以及 Siri 快捷指令。

大部分代码都由智能体编写。读过本系列前几篇文章的读者对此不会感到意外。真正出人意料的,是我们围绕代码周边所必须做出的大量调整。

一旦智能体开始快速输出海量代码,围绕这些代码的一切环节都变得愈发关键:架构设计、测试机制、代码审查流程、运行模拟器的机器,以及团队成员间的协同配合。

我们重构了应用的开发流程,为智能体搭建起具备快速反馈机制、清晰模式规范以及防偏离校验的工作流。

过去几周里我们分享的文章,涵盖了这套系统的几个核心模块:

本文将探讨这些模块如何协同运转,并分享我们的实践心得:怎样搭建一套既能让智能体全速奔跑,又能让工程师稳妥完成验证、审查和发布把关的工作流。

如何为智能体铺平开发道路

在正式迁移各界面之前,一小队工程师率先为智能体搭建了整套支撑体系:架构设计、配套工具链与反馈回路。

乍看之下,这种做法似乎本末倒置。既然智能体一个下午就能生成数千行代码,为什么还要提前花上几周时间做铺垫,而不是直接去写界面?

因为单纯的生成速度只能带来大量代码,带不来优质的应用。智能体周围的支撑系统必须能在输出有误时及时报错,底层架构也必须引导它写出整洁、规范且高性能的代码。如果放任不管,智能体自己是做不到这一点的。

这项工作远不止传统意义上的架构设计。我们实际上是在 AI 智能体时代,彻底重新构想移动应用的构建方式:

  • 脱离设备即可运行的业务逻辑,用于实现极速反馈回路
  • Reflex 架构配合命令行工具,能在数毫秒内加载任意界面
  • iOS 与 Android 共用同一套架构规范
  • 为每个新界面的编写提供清晰的示例代码和 Markdown 文档规范
  • 完备的代码库防护栅栏,一旦代码出现偏差即刻阻断报错

对人类工程师来说,部分架构设计可以只存在于脑海中;但对智能体而言,一切必须完全显式化。架构必须体现在文件结构、architecture.md 文档、技能定义、命名约定、状态结构、方法签名、CLI 输出、Lint 规则、测试固件以及 CI 报错信息当中。

这也彻底改变了我们构建应用的方式。我们在面向工程师设计的同时,也必须面向智能体设计——它们极度依赖可复用的模式、迅捷的反馈回路以及高度明确的错误提示。

在做这些改造之前,智能体的反馈回路和人类别无二致:编译打包、启动模拟器、跳转到目标界面、截屏查看效果、分析问题、修改代码,然后重新来过。这个流程每次迭代都要耗时数分钟,而且在需要依赖视觉导航和代码外部上下文的环节,智能体的表现往往很不理想。

架构改造完成后,智能体无需启动设备就能运行绝大部分界面逻辑。它可以在终端中直接加载 ViewModel、触发操作、检查状态,并在几毫秒内完成确定性校验。正是这种极速的反馈回路,才让后续超高速的迁移成为了可能。

我们变快,靠的不是让智能体去搞“大动作”,而是把任务切得更小、让反馈闭环转得更快。

我们如何组织重写工作

大约有 30 位工程师参与了这次重写。我们采用两人一组的协作模式,每组全权负责应用中某个业务模块在 iOS 和 Android 双端的开发。组内的两位工程师全天大部分时间都在结对工作,各自同时指挥多个智能体。智能体在夜间和周末也不会停工,所以工程师每天早上一开工,就有一长串等待审核的 PR。我们特意保持小组规模足够小。智能体赋予了每组工程师足以覆盖整个业务模块的执行力;而小组真正需要的,是明确的归属权、快速的决策以及完全同步的上下文。

在人员组织上,我们没有生硬地拆成 iOS 团队和 Android 团队,而是让每个小组端到端地对某个业务模块负责。代码的大部分实现工作由智能体完成,但架构设计、产品交互表现,以及判断代码是否达到上线标准的最终裁决权,始终掌握在工程师手中。

一致性重于平台专属架构

我们的首要原则是保持一致性。这包括架构的一致性,好让智能体提交的 PR 都遵循统一规范;也包括 Android 与 iOS 之间的一致性,确保同一界面在双端暴露相同的状态、操作和行为逻辑。不管是看 Swift 还是 Kotlin 版本,订单页面的 iOS ViewModel 和 Android ViewModel 看起来几乎完全一样。

我们特意将一致性的优先级置于平台专属架构之上。部分代码可能不如 iOS 或 Android 原生洁癖者写出来的那样“地道”,但我们欣然接受这一取舍,因为我们换来了更大的收益:

  • 每一个迁移完成的界面,都能成为下一个界面的参考范例
  • 一个 PR 即可同时包含双端的代码变更
  • 只熟悉其中一个平台的工程师,也能审核另一个平台的 PR
  • 架构规范只需制定一套,双端通用
  • 测试用例可以跨 iOS 和 Android 跑通相同的商家业务流程

这正是第一篇文章中论点能够在实践中落地的关键所在:只要第二个平台遵循相同的架构,同时开发两个平台的原生应用就绝不需要付出双倍的成本。但前提是,双端必须始终保持相同的形态。

在由智能体主导的工作流中,一致性并不是为了代码美观,而是不可或缺的基础设施。正是它,让工程师能跨平台对照实现意图,让智能体能够复用参考范式,并在审核人员人工介入前,由 CI 自动拦截代码走样。

我们会强制推行这种一致性。只要 iOS 和 Android 出现架构规范之外的分歧,CI 就会直接报错。

把智能体限制在轨道内

简而言之:绝不搞“全凭感觉随性写代码”(no vibe coding)。

我们在第一篇文章中提到过,让大语言模型一步到位搞定重写,只会堆砌出大量根本无法上线的废代码。我们的解决办法,就是设立护栏。

有了过硬的架构和恰当的校验机制,智能体就有了明确的行动指引,在那些一旦随意发挥就会增加维护成本的地方,也收紧了它们自由发挥的空间。如果缺乏这些约束,智能体写出来的代码即便能编译、能通过某个狭隘的测试,最终留给人类工程师的,也是一个谁都不想接盘的代码库。

面对智能体编写的每一次变更,系统都必须解答以下三个问题:

  1. 它是否遵循了既定架构?
  2. 它的表现是否与现有应用一致?
  3. 工程师能否在不逐行阅读海量 diff 的情况下,看懂其背后的实现意图?

系统中的不同机制分别负责解答这些问题。

第一个问题,靠架构规范、示例、代码检查规则(lint rules)和差异检测来解答;第二个问题,交给 Helix 和原有的 React Native 应用;第三个问题,则通过细化检查点、跨平台 PR 以及智能体优先审查来应对。

关键在于把规范真正落到工作流中,而不是停留在文档里。文档只负责解释为什么有这条规则,至于有没有遵守,由 CI 说了算。

智能体需要的不仅是指示,更需要一套机制,让它能发现自己哪里搞错了。

现有应用本身就是最好的需求规格说明

起初我们尝试过“规格说明驱动开发”:先给某个界面写好规格说明,扔给智能体,然后去审查结果。事实证明行不通。

规格说明几乎写完就过时。等智能体做到某个界面的第三个检查点时,为第一个检查点写的规格说明早就残缺不全甚至错漏百出了。产品里本来就有现成的行为逻辑,没人愿意再去额外维护一套平行的文字说明。

在这场技术栈迁移中,现有应用远比文档更适合当规格说明。老版 React Native 界面早就把各种状态、操作、边缘场景、空状态、加载逻辑和导航关系写得明明白白。Helix 直接读取这个参考样本,把迁移任务拆成细小的检查点,每一步都直接和原应用比对验证,而不是去对照一份容易过时的文字说明。

我们让智能体朝着现有产品逐步对齐,而不是凭空造个新产品出来。面对这种任务,一个活生生的参考样本绝对完胜纸上规格。

新功能的开发则完全不同。要是没有现成界面可以比对,之前的规则可能就派不上用场了……这正是我们接下来要啃的硬骨头。

这次迁移带来的经验更具体,但也极其受用:智能体并不需要一出手就尽善尽美。给它一个参照物、一个细小的下一步目标,再配上一套快速校验它是否更接近目标的方法,这就够了。

新的瓶颈转移到了哪里?

一旦写代码不再是整个系统里最耗时的环节,瓶颈自然就转移了。

整个行业目前还在消化“智能体驱动开发”带来的这一转变。大家现在谈论的焦点,大多还是智能体生成代码到底能有多快。但优秀的团队交付的从来不是“生成的代码”,而是经过审查、测试、集成、兼顾安全性与可维护性的软件产品。

代码生成一旦提速,下游环节的每一处制约都会被成倍放大。

这很像 杰文斯悖论:当某种资源的使用效率提升时,我们的消耗量往往会不降反升。我们碰到的正是这种情况。智能体加快了代码实现的速度,但这绝不意味着团队的工作变少了,反而意味着同样的团队规模可以承担更多工作:更多检查点、更多修复、更多条并行的迁移链路,还有更多的审查、CI 和决策……

写出来的代码已经不再是稀缺资源。真正的稀缺资源,已经变成了“决定哪些代码应该存在”,以及“把它们稳妥推进产品”。

我们把这些提升的生产力,全部重新投入到了产品路线图中。

笔记本电脑撑不住了

智能体离不开物理硬件。跑 UI 测试和视觉校验需要模拟器,代码需要编译器,另外还需要构建缓存和磁盘空间。一台笔记本跑不了几个模拟器,编译器和模拟器就会开始争抢 CPU、内存和磁盘资源。

一名工程师开三个智能体,就能把一台笔记本的性能压榨到极限。为此,我们搭建了面向智能体的远程开发环境。只有算力架构能跟得上,智能体工作流才转得起来;否则智能体跑得再快,硬件机器也会变成排队的堵点。

代码审查成了新瓶颈

智能体写代码的速度已经超过了人类审批的速度。只要几分钟就能写出的代码,可能依然要花好几天才能合并。如果人类无法切实理解、审查并落地这些变更,智能体写得再快也没有意义。

我们仍然要求每个 PR 都必须经过人工代码审查,由审查者来评估其意图、架构契合度、产品行为,以及该变更是否适合合并进数百万商家所依赖的代码库。

我们被问到最多的问题是:两个人一组的小团队,怎么可能审查比以往多出 100 倍的代码?坦白说,逐行审查根本做不到。因此,我们调整了代码审查的顺序:

  • 智能体是第一道审查关卡。在人工介入之前,每个 PR 都会先对照架构规范接受对抗性审查。在审查者投入精力关注某项变更之前,显而易见的问题必须先解决掉。
  • 我们改变了任务的粒度与形态。一个 PR 只是一个微小的检查点,而不是一整个完整页面。我们给智能体设定的约束之一,就是人类单次可阅读的 diff 大小。同一个 PR 会涵盖双端代码,审查者可以并排比对 iOS 和 Android 的实现,而不必隔上几天把同样的业务逻辑审查两遍。
  • 人类是最后的把关者。工程师不再需要逐行抠代码细节,他们的职责是把控意图、架构契合度、产品表现,以及这项变更是否适合进入数百万用户依赖的代码库。

在这次迁移构建期间,每天结束时,都会有一个智能体梳理当天留下的所有审查意见,并据此更新我们的 skills 配置和 Architecture.md。某一个 PR 上提过的一次评审意见,自此成为后续所有 PR 的通用规则。系统每天都在进步一点点,每个 PR 被要求修改的次数也随之不断下降。

代码合并成了新瓶颈

现在,我们通过智能体来处理合并队列。智能体负责 rebase 分支、解决合并冲突、排查 CI 失败原因、修复不稳定测试,协助打通 PR 落地的最后一公里。过去每位工程师手头的并行分支不多,这类琐事虽烦人但尚可应付;而在智能体不断产出更多检查点的当下,合并队列本身已经成为产品研发系统不可或缺的一部分。

既然智能体推高了 PR 的数量,你就同样需要用智能体来升级 PR 周边的基础设施,推动合并队列中的项目快速流转。否则,团队只不过是把等待时间从“写代码”挪到了“合代码”而已。

协同成了新瓶颈

任务进度的追踪也变得更加困难。工单不再是所有事情的唯一事实来源。Slack 讨论串里刚有人报了个 bug,马上就有人指派智能体去处理,还没等大家抽出空建工单,修复代码就已经提交待审了。

崩溃问题的处理流程不再必须由人工发起。我们新增了一个每 15 分钟运行一次的自愈闭环来检测新崩溃。一旦发现异常,我们的 Slack 智能体 River 就会在远程开发环境中复现问题,并提交包含修复方案的 PR。工程师第一次得知这项崩溃,可能就是看到待审查 PR 的那一刻。

需求故事、任务清单和 bug 工单,原本都是为了“动手修 bug 很慢”的时代而设计的。但如今情况完全变了。现在的真正难题,是多名工程师在彼此不知情的情况下,各自带着自己的智能体同时在修同一个 bug。

这也是我们将团队拆分为两人小组(pod)的原因之一,每个小组各自负责 App 的核心模块。订单出问题就由订单组接手,商品出问题就由商品组负责。这并非完美方案,我们也没找到能完全取代工单看板的工具,但按业务模块划分归属,至少让我们现在避免了重复劳动。

正如你所见,每当我们消除一个瓶颈,紧接着就会冒出下一个。智能体本身早已很少是唯一的问题所在,问题已经转移到了机器性能、CI、代码审查、合并以及团队协同上。

对软件工程师来说,发生了哪些变化?

软件工程师的职责就是解决问题。如今需要解决的问题依然数不胜数,只是问题的性质与以往不同,而且现在一个工程师往往要同时解决 10 个问题。

以前,工程师的大量精力都花在手动将业务意图转化为代码上。而在这次迁移中,智能体承担了绝大多数这类机械性的实现工作。但职责并未消失,只是发生了转移。工程师将更多时间投入到架构设计、编写可供智能体借鉴的代码范式、设计反馈回路、审查实现意图、调试代码周边的系统生态,以及坚守高质量门槛上。

无论 Reflex 架构、Helix、远程开发环境、代码审查流程,还是权责归属模式,指向的都是同一个答案:构建一套系统,让智能体既能干实事,又不会把代码库搞成一团乱麻。

与几个月前相比,工程师的工作形态已经截然不同,但所涉及的广度依然庞大,且令人兴奋。

对我们的用户来说,又有哪些改变?

这次迁移不仅仅关乎我们如何构建应用,它同样改变了商家所获得的使用体验。

我们把 Shopify Mobile 从运行在 New Architecture 上的 React Native 应用,彻底迁移成了纯原生的 Swift 和 Kotlin 应用,而整个过程无需用户进行任何操作。用户的登录状态得以保持,偏好设置也无缝继承。在他们看来,应用只是完成了一次常规更新,依然照常运行。

但在底层,这款 App 却发生了翻天覆地的变化:

启动耗时大幅缩减:Android 端降低了约 50%(P50 从 1.71 秒降至 0.87 秒),iOS 端降低了 14%(P50 从 0.70 秒降至 0.60 秒)。

Android 安装包体积缩小了 40%(从 80.4MB 降至 47.6MB)。

Android app download size drops from about 80 MB to about 48 MB.

Android 内存占用几乎比 React Native 时期减半(P50 从 470MB 降至 200MB)。

Android memory usage falls over time, shown at P50 and P75.

iOS 峰值内存占用下降超过 70%(从 730MB 骤降至 190MB)。

iOS peak memory drops from about 730 MB to about 190 MB across app versions.

应用如今带来了纯粹的原生质感。我们可以自由使用系统级转场、更丝滑的动画和原生页面交互,再也不用跟抽象层较劲。

一旦平台推出新特性,我们就能在第一时间支持。比如,我们在首日就完成了对 iPhone Duo 的支持。

稳定性也迎来了质的飞跃。在 Android 端,无崩溃会话率从 React Native 时代的 99.66% 提升到了原生版本的 99.98%;iOS 端则稳稳保持在我们设定的 99.95% 目标之上。此外,我们还加入了自愈机制,让智能体能够自动检测并修复崩溃。

不仅如此,现在的 App 也全面做好了迎接智能体的准备:每个页面的状态和操作都通过可内省的 ViewModel 暴露出来。借助 Reflex 架构与 CLI 工具,智能体无需启动模拟器就能测试 App 的绝大部分功能;Shopify 内部的任何人也都能使用 River 来构建并验证移动端改动。

这正是我们追求的结果:为商家带来更快速流畅的 App,同时打造一个让人类与智能体都能轻松协作、持续迭代的代码库。

我们的经验与心得

对于准备踏上这条探索之路的团队,我们有几点建议:

  • 先花时间为智能体搭建一套快速测试应用的方法。无需真机即可运行的业务逻辑,以及配合 CLI 驱动的 Reflex 架构,对我们来说至关重要。
  • 让架构具备可执行性。只要某条规则重要,就必须在示例、Architecture.md、测试、代码检查规则或 CI 中明确体现出来。
  • 多用小步检查点,少用智能体生成的大 PR。能稳步收敛,远比第一次尝试就力求完美更重要。
  • 只要各平台的产品行为一致,就使用同一套架构。一致性是让智能体产出具备可审查性的前提,无论是业务逻辑还是 UI 模式都是如此。
  • 先让智能体做初步审查,但最终决策权始终留给人类。
  • 把代码审查能力当作系统硬约束来看待。分配给智能体的工作量,应以人类能理解的代码改动量为上限。
  • 做好瓶颈转移的心理准备。写代码变快后,机器性能、CI 流程、审查、合并与协同就会成为新的瓶颈。
  • 明确权责划分。当工作推进速度快于工单流转时,权责不清就会导致重复造轮子。

结语

我们得到的最明确经验是:既然智能体已经能承担大量编码工作,工程判断力的重心就转移到了智能体周围的基础设施上——它们所遵循的架构、使用的反馈循环、偏离规范时的拦截检查、决定能否发布的审查流程,以及防止团队成员互相踩脚的权责机制。

这也正是我们重构的部分。我们重构的不仅是移动应用本身,更是我们构建应用的方式。

那么,我们的应用是全凭感觉“随性编写”(vibe coded)出来的吗?绝非如此。事实上,我们的代码从未像现在这样高度契合预期的架构规范。我们投入了大量精力设计合适的架构并筑起防护栏,确保智能体写出的代码完全符合我们的预期。

智能体不会施展魔法,平白造出好软件或烂软件。它们只是成倍放大了所处环境的影响。产品的最终质量,依然取决于你选择的模式、设计的架构、执行的检查,以及发布前投入的工程判断。

几个月后,这里写下的一切可能都会过时。届时,我们会再来分享新的变化。

来源:Shopify Engineering · shopify.engineering