最近 Meta 的分享了 Instagram Direct 迁移 Jetpack Compose 的经验,感觉还挺有意思的,不过确实有种都到了「大千世界」了,然后你才分享「焚决」的意思,这次 Meta 公布的迁移数据是:
迁移后的 UI 代码量减少 50%,AI Agent 执行时间下降 35%,工程师与 Agent 的往返次数减少 32%,单次 Agent Session 的 Token 成本降低 33%。
但是这些都不是重点,数据看了也没啥意义,这里还是有一些「焚决」在哪里的:
- 首先是 Meta 弄了个 AI-native codebase 工程化:不一味地给 Agent 塞越来越长的 rules、skills 和项目知识,它选择改代码结构,让 Agent 不容易偷懒走偏
- 其次是 Meta 没有简单地把
RecyclerView里的 XML 换成 Composable,它非常有精力的做了一层可以同时跑在RecyclerView和LazyColumn上的 UI 抽象,然后这让几百种消息组件可以逐步迁移,同时还能做线上 A/B
而且这里还有一个有意思的细节,Meta 给代码文件维护了一套 risk score,当文件风险分数翻倍的时候,Agent 在传统 Android Views 代码上的资源效率会下降约 30%,Compose 代码只下降约 9%,也就是说 Compose 带来的优势在简单页面里可能只是少写一些代码,但是到了历史包袱很重、状态很多、抽象很多的代码里,差距居然可以会进一步拉开?
在 Instagram Direct 里面,一个会话页面要处理超过 200 种 message type,单个 UI Component 有 160 多种状态组合。
我挺喜欢里面的这个说法,意思大概就是:AI 遇到阻力的时候,会想办法绕过你的规则继续完成任务,只靠 Skills、提示词和工程规范,是不能保证它长期生成正确的代码。
所以 Meta 给出的解决办法是:让架构本身承担这部分约束。
这个其实现在很多团队做 AI Coding 的方式正好能形成对照,现在通常是旧项目一动不动,然后不断往 Agent 上面叠东西:
AGENTS.md、rules、architecture skill、state-management skill、各种“请不要这样写”的说明,这些东西每次都可能进入 Context,本身就消耗 Token,而且 Agent 真正在代码里碰到一个奇怪的历史抽象的时候,还是可能选择那个最容易编译通过的方案。
Meta 也说了:Skills 本身存在 Context 成本,加载过多规则反而降低 Agent 的表现。
比如 Instagram Direct 在最初的时候,代码里有 XML 和 Compose 直接混用的情况下, AI 经常分不清 XML 和 Compose 的边界,Meta 官方举了一个非常简单的例子,比如 Agent 要给聊天 Item 增加一个“置顶”状态,AI 很容易写成这样的结构:
class ChatItem(...) {
var isPinned = false
@Composable
fun Content(uiState: ChatUiState) {
Button(
onClick = { isPinned = !isPinned }
) { ... }
}
}
这么看起来代码挺自然的,也能用,但这里的 isPinned 跟 RecyclerView Item 实例生命周期绑定了,Item 被重新 bind、复用到另一行之后,这个状态就可能跟着对象一起活下来,然后就出现类似“偶现、滚几下才出来、怎么都不好复现”的状态泄漏问题。
所以 Meta 后来保留了项目需要的 ChatItem 这层抽象,但是 Composable 内容被限制在构造时传入的 lambda 里,UI 能看到的东西基本只剩 uiState、显式依赖和事件 callback,也就是成员字段不能是一个随手就能藏 mutable state 的地方:
大概类似这样:
ComposeItem<ChatUiState>(
content = { state ->
PinButton(
pinned = state.isPinned,
onClick = { onPin(!state.isPinned) }
)
}
)
类似这样的实现,后续如果 Agent 想偷懒也不行了,要改变 isPinned,最顺手的路径就是调 onPin(),然后状态经过正常的数据流重新进入 ChatUiState,正确的数据流同时也是代码里阻力最小的数据流,这就是这套 AI-native architecture 的意思。
在代码设计上,就要把隐藏状态变成显式输入,降低项目私有语义的数量,这样就可以把错误写法从「需要规范禁止」的规则变成「结构上很难表达」的问题,因为 AI 一用就报错。
其实就是减少不确定性,少让 AI 自由发挥,这在迁移适配的过程里是一个很有用的规则,也是你 Review 代码的时候,需要介入调整的地方,不然 AI 固执的程度,决定了它走歪之后,你再三强调,它也是会继续走歪。
所以 AI 写代码、做迁移、搞适配,在中大型项目里不是写写 Spec ,列一些规则就能能搞定的,工程设计上如果没做好,最后写出来的代码照样烧心。