人物采访 / T SALON

编辑内容

曹立成谈 1688 终端架构:动态容器、低代码与开发者成长

回顾 T Chat 第 13 期两段录播,从强运营业务的动态化诉求、端侧容器与页面搭建,到架构收敛、多端一致性,以及曹立成的 Android 经历、技术表达和团队建设。

T Chat 第 13 期曹立成分享 1688 终端架构的封面
T Chat 第 13 期曹立成分享 1688 终端架构的封面

本期视频发布于 2022 年。文中的技术状态、个人经历与观点均为当时情况。

第 13 期 T Chat 的前半场,曹立成以 1688 的实际业务为例,解释一个大型客户端怎样支持频繁变化的运营活动;后半场则回到个人,从最早折腾 Android 手机,聊到进入基础架构团队、练习技术表达、建立团队氛围与选择成长方向。两段录播合计约 93 分钟。

从业务变化出发设计容器

页面增长快于人手,发版也跟不上运营节奏

强运营业务首先遇到的并不是技术选型问题,而是变化速度不匹配。活动可能今天上线、下午调整,客户端却有固定的发版窗口。促销页面持续增加,开发团队人数不会同比增加;同一个应用又可能同时存在原生、H5 和多种跨端技术,页面展示与交互逐渐变得复杂。

曹立成给出的起点是把页面拆成容器和组件:容器承接底层能力,页面中的不同区块通过组件组合。如果组件能够独立调整、上线和下线,大部分运营变化就不必等待整个应用发版。问题由此从“怎样更快写完一个页面”,转向“怎样让页面能够持续组合和调整”。第一段 00:32–04:17

容器承担效率、体验下限和多端复用

容器有三个目标。第一是提高研发效率,使开发者围绕组件工作。第二是保障体验和稳定性的下限:动态化增加灵活性,也可能让不同组件的性能、资源占用和异常处理参差不齐,公共底座要把这些差异控制在可接受的范围内。第三是支持多个客户端复用,1688 的业务除了主客户端,也包括面向商家和细分品类的产品。

他以常用网络库作类比:公共框架的价值之一,是让经验不同的工程师在使用相同能力时得到相对一致的结果。容器同样需要让业务开发者能够灵活做事,又不必人人重新解决资源、通信和稳定性问题。第一段 04:17–07:00

先分场景,再统一底层能力

首页、搜索和商品详情直接影响浏览、下单,关注性能与体验;营销页面强调快速变化;对外开放的业务需要承接商家的扩展;收藏、足迹等工具场景则相对稳定。容器要服务这些不同需求,不能只围绕某一种页面设计。

他的架构将业务场景与公共能力分开:上层通过统一 API 接入,下层提供插件、事件、调度、交互、埋点、资源、数据和脚本运行等能力,再与数据平台衔接。比如浮层、弹窗和页面可能同时出现,需要调度优先级;资源预推和缓存影响首屏;业务效果、性能与用户分群又需要共同的数据基础。第一段 07:00–11:08

协议和工作流程比技术栈的数量更关键

容器与业务之间主要通过插件、事件、调度和交互协议协作。不同渲染方案可以使用各自的桥接方式适配协议,但不应迫使每个业务重新理解容器内部实现。底层能力收拢、协议稳定之后,变化更多发生在上层业务。

一个简化的工作流程是:启动容器,加载协议,取得组件结构和对应数据,完成渲染,再处理交互。页面、卡片、浮层虽然大小不同,仍可以沿用这一流程。曹立成也提醒,架构图列出了多种适配能力,并不代表团队必须同时采用所有方案;满足自身需求的一两种方案就可能足够。第一段 11:08–17:04

多端复用的单位是业务模块和组件

在容器之下,需要先解耦基础库和业务能力;容器之上,搜索、推荐、商品、会员和消息等业务模块再组合成不同页面。同一个推荐模块可能出现在首页,也可能出现在工作台。不同客户端通过皮肤、资源、数据参数和交互配置形成差异。

他展示主客户端与工业品类客户端的页面,说明看起来不同的产品可以共享大量模块。这里的前提是业务结构本来就有共同部分,并且团队已把这些共同部分沉淀为组件。容器提供复用条件,组件划分与业务解耦决定能复用到什么程度。第一段 17:04–22:59

用 DSL 和搭建平台把动态化落地

一个可理解的起点:DSL 描述,原生组件渲染

为了让听众能把思路带回自己的项目,曹立成给出较小的实现模型:使用 DSL 描述布局和组件,在客户端解析为原生界面。他将这种方式称为原生增强。它能够沿用原生渲染能力,额外引入的引擎和学习成本较少,也方便通过下发描述实现动态布局。

可以把它理解为将原本写在本地的布局描述移到平台:开发者在 Web 编辑环境中编辑,平台下发描述,客户端按约定解析。分享也介绍了 Flexbox 布局与现有开源布局、容器项目作为参考,并说明 1688 当时大量使用集团的动态化能力。完整的生产方案仍需补足发布、稳定性、性能和业务定制,不能把一个演示级解析器等同于成熟平台。第一段 22:59–29:06

这种方案有明确边界:如果旧版应用里根本没有某个原生组件或交互能力,下发对应标签也无法让它凭空出现。增加新的客户端能力仍然需要发版,并处理新旧版本兼容。动态布局不能消除所有版本约束。

搭建平台先有物料,再有页面

低代码搭建的前提是已有可用组件。组件发布到物料池后,业务人员创建页面,再编辑容器层级、组件位置和数据。曹立成展示的平台并不要求所有操作都表现为自由拖拽,增加和删除组件也可以完成搭建;关键在于组件和协议具备清楚的语义。

数据有两条路径:一部分直接写入页面下发协议;另一部分描述动态数据源,由客户端请求接口后再与组件绑定。皮肤、实验、埋点和性能配置可以作为扩展信息逐渐加入。页面维度还可以挂载公共插件,避免每个组件重复承担同样的工作。第一段 29:06–34:32

预览需要反映真实客户端条件

搭建后的静态预览往往展示所有组件的集合,真实页面却受到登录状态、客户端版本、人群条件和投放时间影响。因此平台支持扫码,在实际客户端上检查层级、样式、数据与展示条件,再发布页面。

运营可以配置不同时间段的皮肤和资源,到了相应时间自动切换。客户端拿到发布后的页面地址,交给容器完成协议请求、数据处理与渲染。这样,已具备的组件能力可以被反复组合,日常活动调整也不必总由客户端工程师重新编写整个页面。第一段 34:32–38:48

下发协议如何变成可交互的页面

协议主要描述四类信息:布局结构、组件绑定的数据、组件模板和组件样式。布局决定层级与排列;数据可以内置,也可以来自动态接口;模板描述使用什么组件及其属性;样式处理背景、间距和透明度等表现。

模板与数据必须提前约定绑定关系。比如文本组件的内容不是写死的,而是指向返回数据中的某个字段,那么容器先解析占位关系,等数据到达后再填入相应位置。点击跳转等预置行为也可以在协议中描述;超出已有能力的行为仍需客户端实现。第一段 38:51–41:34、43:07–45:55

现场问题:大协议、定制入口和旧版本兜底

面对“一个很大的 JSON 会不会拖慢响应”的问题,他承认全量下发会带来成本。可以精简部分描述,也可以利用缓存、拆分请求与结果拼接;首页、搜索和详情等核心场景还可以使用标准化的定制入口干预默认流程。

他区分了动态下发布局描述与直接下发可执行代码:这里讨论的基础模型仍然由本地组件完成渲染。某个组件在旧版应用中不存在时,不应假设它能正常展示。分享中提到的开源项目提供局部参考,所展示的整套内部平台当时并没有作为一个完整项目开源。第一段 41:34–45:55

当基础设施成熟,架构继续往哪里走

收敛方案,让流程可以观察和度量

在一个长期演进的客户端中,同类技术方案容易越积越多。曹立成认为下一步首先需要做减法,收敛重复方案、统一核心流程。架构也应当“白盒化”:业务开发者知道关键流程在哪里、哪些环节能够扩展,排查问题时能找到明确入口。

在此基础上,通过日志、链路与指标建立可观测能力。崩溃告警往往说明问题已经发生,而更细的观测可以帮助团队按页面、人群和设备分析达标情况,追踪依赖、定位问题。分享强调的是将这些能力落实到客户端具体场景,并没有把“建立平台”本身当成最终收益。第一段 45:56–49:01

多端一致性需要对应的工程手段

业务足够复杂之后,Android 和 iOS 对同一条件产生不同行为,会让排查和兜底越来越困难。他提出两种思路:保留各端实现,但加强逻辑对齐和交叉审查;或者将适合共享的逻辑放到同一份代码中,通过跨平台编译生成各端产物。

前一种路径需要流程和语言可读性支持,后一种则是他在当时关注 Kotlin 跨平台能力的原因之一。具体共享哪些逻辑,仍要与现有架构和业务边界相适应。第一段 49:01–50:46

从单个 SDK 走向场景解决方案

技术成熟之后,收益往往来自多个能力的组合。用户运营可能需要识别浏览行为、判断触发条件、展示挽留内容并统计结果;性能优化也需要针对具体页面和用户路径安排资源、请求与渲染。

他认为仅靠发现某个孤立函数的低效,很难持续推动整个应用的显著进步。架构团队需要理解具体场景,把基础能力组合起来,最终用体验或业务指标检验效果。分享末尾还谈到当时受到关注的 AR、VR、数字形象与端侧智能,作为客户端工程师可探索的新交互方向;这些是 2022 年的探索判断。第一段 50:46–54:46

曹大的成长路:兴趣、反馈与能力边界

从折腾手机到完成真实项目

曹立成最初接触 Android,来自大学时期对手机界面和系统的兴趣:刷机、调整主题、替换资源,让自己使用的设备变得不同。随后,他开始写简单应用。按钮能够点击、界面立即响应,这种可见的反馈带来了持续学习的动力。

应用比赛让他尝试更多小作品,而一个与灾害搜救有关的研究项目,把兴趣推向了更复杂的问题:如何利用移动设备、自组织通信和数据传递辅助定位。项目延续到毕业设计,让他在实际需求中接触网络、通信和系统协作,也逐渐确定了 Android 开发方向。第二段 00:02–06:37

从“能跑就会了”到认识自己的边界

谈到从新人到专家的阶段变化,他并没有把过程描述成始终自信的上升线。早期带着项目经历进入工作,对自己的能力很有信心;在饿了么实习时,也敢于尝试把当时尚不成熟的 React Native 引入真实工程,为此学习前端技术。

后来进入美团基础架构团队,看到更复杂的工程与同事的实现,他开始意识到能写出演示、让代码运行,与真正理解问题之间还有距离。接下来的阶段是通过请教、阅读和项目逐步积累,知道自己能解决什么、行业里有哪些成熟方案,以及遇到新问题时该如何选择。

这种成长最终表现为更客观的自我判断和更丰富的方案储备。经历过动态化技术快速发展的阶段,也让他能够把后来出现的方案放到更长的演进脉络中理解。第二段 06:37–13:31

Kotlin 的价值来自生态与跨平台可能性

在当时的访谈中,他把 Kotlin 看作 Android 开发者值得持续投入的语言:平台与工具生态对它的支持、与 Java 的协作、语言表达能力,以及逐渐扩展的跨平台用途,共同推动了它的普及。

讨论从 Android 延伸到后端与原生跨平台代码。他关注的重点是,同一项语言能力可以连接不同领域,使开发者有机会复用已有积累。访谈中提及的生态状态属于当年的观察,不能直接替代今天对具体库版本与平台能力的核查。第二段 13:31–18:11

把技术讲清楚,也让团队里的贡献被看见

分享技巧先从组织思路开始

曹立成认为,技术分享要让听众获得接近讲者的理解。自己做出了东西,并不代表已经能把它讲清楚。写文章是一种成本较低的训练:有意识地整理问题、设计理念、核心模块、落地过程与最终效果,避免把文章写成流水账。

演讲还需要另外练习。幻灯片应呈现经过抽象的模型,讲者再补足解释,页面之间要形成从问题到解决方案的连续叙述。紧张、音量和表达节奏,也需要在实际分享中改善。

严谨体现在内容之外的细节。他回忆团队技术文章审稿时对语句、错字与标点的要求:这些细节会影响读者对专业程度的判断。分享能力因此包括思考、组织材料、口头表达与反复校订。第二段 18:11–22:43

个人技术品牌建立在可持续的优质内容上

谈到工作繁忙时怎样建立技术品牌,他先强调内容积累。文章是可以反复使用的基础材料,但需要把工作里的具体问题抽象成别人也能理解和借鉴的模型。相较单纯增加数量,他更倾向于投入时间写出值得细读的文章。

在有内容之后,再通过社群交流、投稿和技术会议扩大触达。读者持续从文章中获得启发,才会逐渐建立对作者的稳定认识。他也提到表达时的自信:在认真准备之后,应当相信自己产出的内容有价值,愿意让别人看到并参与讨论。第二段 22:43–28:26

团队氛围需要传承,也需要具体激励

团队中的分享、沙龙、新人培训和经验传递,可以帮助知识流动。但技术氛围也需要让那些不容易被看见的工作获得正向反馈,比如维护稳定性、解决用户体验问题、提高代码质量,以及长期帮助同事。

他介绍了团队通过项目与奖励认可不同类型贡献的做法。主持人进一步把对内的技术氛围与对外的技术品牌联系起来:内部积累产生有价值的分享,外部认知又可能吸引志同道合的人加入,再反过来改善团队。这个过程需要长期持续。第二段 28:26–31:27

招聘看基础,也看协作与持续学习

在他看来,技术基础、工程素养和学习能力是重要前提。架构和技术方案不断变化,开发者需要跟着问题继续学习。与此同时,一个人的产出存在边界,更大的目标需要拆解任务、协调协作并将结果重新组合。

因此,沟通与合作能力并非技术之外的附属项。能让多人共同完成复杂项目的人,也更有可能承担更大范围的责任。第二段 31:27–33:18

成长方向可以不同,转型应尽量承接已有积累

访谈最后讨论客户端工程师的后续发展。他给出了几种不同方向:深入某个技术领域、解决困难问题;围绕架构演进和研发效率工作;贴近业务,运用技术组合改善增长、留存等目标。不同方向需要不同能力,也对应不同的岗位空间。

他特别指出,理解业务并能把技术转化为结果,同样需要复合能力。做业务并不天然意味着技术浅。对于想探索新方向的人,他更建议从已有经验延伸,比如以客户端能力连接新的交互和图形场景,减少完全抛弃过去积累的成本。这些建议应结合个人兴趣、能力与实际机会来判断。第二段 33:18–38:14

查看本期原视频与分段信息:我在 1688 做终端架构 →