02 「服务端消费优先」设计哲学 本节摘要:上一节看到拓扑里服务端是「唯一中枢」,这一节讲贯穿整个 OpenWork 的核心设计哲学——「服务端消费优先(Server-consumption first)」。它的意思很简单:App(包括桌面渲染进程和所有客户端)只是服务端 API 的客户端,绝不发明平行行为,凡是服务端能做的都走服务端。这条哲学看似平淡,却是 OpenWork 避免行为漂移、让多客户端天然一致的根本。本节讲清它的含义、它带来的红利,以及违反了会怎样。
本节摘要:上一节看到拓扑里服务端是「唯一中枢」,这一节讲贯穿整个 OpenWork 的核心设计哲学——「服务端消费优先(Server-consumption first)」。它的意思很简单:App(包括桌面渲染进程和所有客户端)只是服务端 API 的客户端,绝不发明平行行为,凡是服务端能做的都走服务端。这条哲学看似平淡,却是 OpenWork 避免行为漂移、让多客户端天然一致的根本。本节讲清它的含义、它带来的红利,以及违反了会怎样。
「服务端消费优先」可以拆成两条规矩:
| 规矩 | 含义 |
|---|---|
| App 是服务端的客户端 | 渲染进程、桌面、CLI 接入的 Agent,都通过服务端 API 干活 |
| 不发明平行行为 | 如果服务端能做某件事,App 绝不自己在客户端另做一套 |
举例对比:
后者就是「发明平行行为」——它在客户端和服务端各做了一套,迟早会不一致。
💡 一句话记住:服务端是单一事实来源(single source of truth),App 只消费它,不另起炉灶。
这条哲学解决一个工程痛点:行为漂移(behavior drift)。考虑没有这条哲学的场景:
渲染进程自己实现「列工作区」 │ ▼ 服务端也实现「列工作区」(给别的客户端用) │ ▼ 时间推移:有人改了服务端的实现,忘了改渲染进程 │ ▼ 结果:桌面显示的工作区列表 ≠ 实际工作区列表
这就是行为漂移——同一件事在客户端和服务端各一套,改了一边忘了另一边,行为就不一致了。规模越大,漂移越严重。
「服务端消费优先」从根上消灭这个问题:只实现一遍(在服务端),所有客户端都调它。改一处,所有客户端同步生效,不可能漂移。
因为所有客户端都调同一套服务端 API,它们的行为天然一致——桌面看到的、CLI Agent 看到的、企业云看到的,都是同一份真相。你不用担心「桌面能做但 CLI 不能做」。
每件事只实现一遍(在服务端)。改一处,所有客户端受益。没有「改了 N 个客户端」的重复劳动。
客户端只负责「展示 + 调 API」,逻辑很薄。这让新增客户端(比如未来加个移动端)成本很低——只要它会调 API 就行。
薄客户端(展示+调API) │ ▼ 服务端(所有业务逻辑)
因为客户端依赖的是 API(契约),不是实现,服务端内部怎么重构都行,只要 API 不变,客户端无感。
讲个反例感受一下。假设有人为了「快」,在渲染进程里偷偷自己实现了一份「读文件」逻辑(不走服务端):
渲染进程:自己读文件(平行行为) │ ▼ 服务端也有「读文件」API │ ▼ 后果: ├─ 权限绕过:服务端的权限检查(第 4 章)被绕开了,客户端能读不该读的 ├─ 行为漂移:服务端改了读逻辑,客户端读的还是旧的 └─ 多客户端不一致:CLI 走服务端读到新逻辑,桌面读到旧逻辑
最严重的是权限绕过——OpenWork 的权限治理在服务端(第 4 章),客户端自己读文件等于绕过了治理。这正是为什么「服务端消费优先」不容妥协:它不只是工程整洁问题,更是安全问题。
⚠️ 一票否决:代码评审里看到客户端绕过服务端自己实现业务逻辑,基本要被打回——尤其是涉及权限/文件/引擎的操作。
把这条哲学和上一节的拓扑对照,你会发现拓扑的形状就是这条哲学的体现:
换句话说,拓扑是「服务端消费优先」的物理体现。理解了哲学,你就能解释拓扑为什么长这样;理解了拓扑,你就能把哲学落到具体设计上。
诚实地说,这条哲学不是绝对的。有些事必须在客户端做,服务端做不了:
「服务端消费优先」针对的是业务逻辑,不是说一切都在服务端。判断标准是:「这件事是不是业务逻辑?」是 → 走服务端;不是(纯展示/系统交互)→ 客户端做。
拓扑和哲学都清楚了,最后一件事——把它们串成一次具体的控制流旅程。这是下一节的主题。