原语优先:
打破“简单”与“强大”的二元对立
在创业圈,人们总是喜欢抛给你各种两难的选择(Trade-offs)。最经典的一个就是:“你是要做一个简单的产品,还是要做一个强大的产品?”
通常的建议是:你必须二选一。要么做成 Apple 那样极简但封闭,要么做成 Linux 那样强大但极难上手。如果你试图两者兼得,就会变得平庸。
但我(Dax Rad)从构建 Open Code 和多年 DevTools 的经验中得出的结论是:这种二元对立是虚假的。当你看到这种所谓的权衡时,正确的答案永远是——你要想办法同时做到这两点。因为这才是真正的难点,也是真正的机会所在。
1. 直线开发的陷阱
对于开发者工具来说,最简单的路径是“减法”。为了让新用户上手容易(Onboarding Experience),我们往往会削减功能,提供一个高度封装的、“开箱即用”的体验。
这听起来很美好,但问题在于:开发者工具从来不是靠“上手体验”赚钱的。
我们赚钱的时机,是当客户的公司规模扩大、业务逻辑变得极其复杂、需求变得刁钻古怪的时候。如果你的产品在那个阶段无法支撑,用户就会遭遇所谓的“弹出时刻”(Ejection)——他们被迫放弃你的工具,去寻找更重型、更灵活的替代方案。
如果你为了前期的简单而牺牲了后期的扩展性,你实际上是在为别人培养用户。
2. 什么是“原语优先”策略?
如何既保持简单的上手体验,又能承载无限的复杂度?答案在于构建顺序。
当你想要构建一个功能(Feature)时,不要直接去写实现这个功能的代码。这叫“直线射击”(Straight-shot),虽然快,但它是死路。
相反,你应该遵循“原语优先”(Primitives-First)的路径:
- 首先,思考为了实现这个功能,我们需要什么样的底层积木(Primitives)?这些积木应该是通用的、原子的。
- 然后,开发这些积木。这会很痛苦,比直接写功能要慢得多。
- 最后,利用这些积木,组装出一个“默认配置”,这就成了你呈现给用户的那个简单好用的功能。
CASE STUDY: Open Code 的子智能体
举个具体的例子。Open Code 需要一个功能:让 AI 能够搜索并理解你的代码库。
我们没有直接写死一段代码去调用搜索接口。相反,我们先退一步,构建了一个通用的“子智能体框架”(Sub-agent Framework)。这是一个纯配置驱动的底层系统,允许你定义任何 Agent 的行为、工具集和指令。
然后,我们利用这个框架,配置出了一个“搜索 Agent”,并把它作为产品的默认功能发布出去。
这样做的好处是什么?
现在,市面上有无数关于搜索的新点子:用专门的模型搜索?用不同的 Prompt?用新的向量数据库?因为我们是基于原语构建的,我们不需要重写代码,只需要调整配置,就能快速集成这些新特性。
更重要的是,用户也可以这样做。如果用户觉得默认的搜索不够好,他们可以下沉到原语层,自己配置一个专用的搜索 Agent。
3. 将 Power Users 变成你的研发团队
当你采用原语优先策略时,你获得了一个惊人的副作用:你的高级用户(Power Users)开始为你创新。
任何产品都有这样一群早期采用者,他们愿意忍受复杂的配置,只为实现特定的需求。如果你给了他们足够强大的原语,他们会组合出你完全意想不到的功能。
“老实说,90% 的时候,用户用原语搞出来的东西都是针对他们自己奇葩需求的,甚至有点疯狂。但每隔一段时间,会有那么 10% 的时刻,你会发现:‘天啊,这个点子太棒了!’ 然后我们可以直接把这个配置吸纳进来,变成产品默认的‘开箱即用’功能。”
这就是原语策略的闭环:原语 -> 用户创新 -> 官方标准化 -> 更好的默认体验。
4. 不要有太强的“观点”
最后,这关乎一种心态。在开发者社区,我们经常看到关于“你应该用什么编辑器”、“你应该怎么工作”的争论。但作为工具构建者,我学到的最深刻的一课是:
你没有资格拥有太强的观点(Opinions)。
如果你想服务 5000 万开发者,从初创公司到 70 年历史的石油巨头,你不能教他们做事。你必须适应他们千奇百怪的环境。
直接构建功能往往带有强烈的“观点”(比如:我认为你应该这样搜索)。而构建原语则是“无观点”的(Mechanism, not Policy)。
通过提供无观点的原语,再加上一套有观点的默认配置,你就能达成那个看似不可能的目标:既像 Apple 一样简单(默认配置),又像 Linux 一样强大(底层原语)。
英文互联网语境中的 "Primitives":
What, Why, How
在硅谷的产品设计(Product Design)和系统工程(System Engineering)讨论中,"Primitives" 是一个极其核心的概念。以下是该概念在更广泛语境下的定义与应用。
定义: Primitives(原语)是指系统中最小的、不可再分的、具有原子性的构建块(Building Blocks)。它们不预设具体的使用场景,只提供单一的基础能力。
比喻: 如果成品功能是“乐高城堡”,那么 Primitives 就是那一个个标准的 2x4、1x2 的乐高砖块。砖块本身不是城堡,但它是一切城堡的基石。
可组合性 (Composability): 产品经理无法预测未来所有的用户场景。与其构建 100 个特定的功能来覆盖 100 个场景,不如构建 10 个原语,让用户通过组合(Compose)来解决无限的问题。
逃生舱口 (Escape Hatches): 在工具类产品中,用户最痛恨“黑盒魔法”。当高度封装的魔法失效时,Primitives 提供了“逃生舱口”,允许用户降级到底层手动解决问题,而不是被卡住。
解绑 (Unbundling): 它允许将复杂系统解耦,便于独立维护和升级。
这通常遵循经典的 Unix 哲学:"Mechanism, not policy"(提供机制,而非策略)。
- 正交性 (Orthogonality): 确保原语之间互不干扰,改变 A 不会破坏 B。
- 低级优先 (Low-level First): 先暴露 API 和配置项,再在上面封装 UI。例如 Figma 在做复杂的响应式设计功能之前,先做出了 Variables 和 Tokens(原语)。
- 通用性测试: 一个好的原语应该能同时支持你当前想做的功能,和你还没想到的下一个功能。