低代码编程困于形式
2025年2月19日 — 17分钟阅读在你所热爱的伟大创造背后——无论是音乐、艺术还是技术——其形式(它看起来像什么)是由其内在逻辑(它如何工作)驱动的。我在观看一场关于细胞自动机的演讲时注意到了这种模式,并意识到这其实是“形式追随功能”的另一种表述。发明一种形式是一项艰巨的任务,因此你必须间接地去处理它——首先揭示其背后的逻辑。这让我意识到低代码编程的一个关键问题:它被困在了形式上,而不是让形式
低代码编程困于形式
Essays
2025年2月19日 — 17分钟阅读

在你所热爱的伟大创造背后——无论是音乐、艺术还是技术——其形式(它看起来像什么)是由其内在逻辑(它如何工作)驱动的。我在观看一场关于细胞自动机的演讲时注意到了这种模式,并意识到这其实是“形式追随功能”的另一种表述。发明一种形式是一项艰巨的任务,因此你必须间接地去处理它——首先揭示其背后的逻辑。
这让我意识到低代码编程的一个关键问题:它被困在了形式上,而不是让形式追随功能。低代码编程长期以来一直被困在节点和连线的范式中,因为其设计者过于专注于形式,而忽视了应该驱动它的底层功能。因此,整个领域陷入了局部最小值。我们该如何突破它?我们又该如何为这个领域找到一个支撑形式的功能呢?
来自CellPond的线索
我观看了一场演讲,不仅被演讲本身所吸引,还被Lu Wilson在关于CellPond的演讲中的一句引言所打动——CellPond是一种扩展了我对细胞自动机期望的低代码编程语言。尽管我已经看过约翰·康威的生命游戏,并且阅读了大量史蒂芬·沃尔弗拉姆的《一种新科学》,但Lu Wilson在演讲的最后10分钟展示的精彩低代码效果并非重点。真正的关键在于:CellPond系统底层有一个仅包含四种操作的虚拟机。这四种操作对应于我们熟悉的CPU中的内存操作:读取、写入、分配和释放。对我来说,这种联系是完全出乎意料的。图案的网格(形式)是由底层虚拟机(功能)所告知和驱动的。
“我认为如果你从CellPond中学到了什么,你带走的不仅仅是用户界面——当然,如果你想,也可以带走用户界面。这让我非常惊讶,因为在阅读过去解决这些问题的所有方案时,它们都与高级用户界面有关;它们都是关于用户界面的。我以为我不得不构建一层又一层的用户界面,但实际上,一旦底层的东西理顺了,用户界面就自然而然地解决了。”
——Lu Wilson ( 🐤 · 🦋)
我思考着:Lu Wilson是如何想出底层功能的?这似乎有点神奇。这一令人困惑的启示让我意识到,这不仅仅是关于用户界面——这里有一个更深层次的原则在起作用。
形式追随功能
在随后的几个月里,我一直在思考这个问题。关键在于开头的引言。
当你弄清楚底层的东西时,用户界面就会自然到位。
直到我在开车时听保罗·格雷厄姆的《制造者的品味》,我才意识到CellPond演讲正是“形式追随功能”这一常被重复的格言的体现。以下是相关摘录:
在艺术中,传统上最高地位一直被赋予人物绘画。这种传统背后有一定道理,不仅仅是因为人物画能够触动我们大脑中其他画作无法触动的按钮。我们对观察人脸如此擅长,以至于我们强迫任何绘制它们的人努力满足我们。如果你画一棵树,将树枝的角度改变五度,没人会知道。但当你改变某人眼睛的角度五度时,人们会注意到。
当包豪斯设计师采用沙利文的“形式追随功能”时,他们的意思是,形式_应该_追随功能。如果功能足够困难,形式就会被迫追随它,因为没有多余的努力去犯错误。野生动物之所以美丽,是因为它们过着艰难的生活。”
——保罗·格雷厄姆《制造者的品味》
说实话,我以前从未过多思考过“形式追随功能”。当你第一次听到它时,它似乎显而易见。当然,给定一个界面,它表达的难道不是它的目的吗?否则似乎会适得其反。
直到我被迫去发明一种形式,我才真正理解了它的含义。“形式追随功能”是针对那些需要发明形式的人的,而不是当你被给予形式时。用我自己的话来说,就是:
如果一个设计是好的,那么它的外观、感觉和工作方式就是其功能、其代数、其理性——其底层本质的直接表达。**要设计一种形式,你不应该凭空想出来。你必须间接地解决问题,先弄清楚它的功能。**一旦功能——底层本质、内在一致性和代数——被弄清楚,形式就会随之而来。
功能的三种面貌
我所说的“底层本质”并不是说它独立于人类创造而存在;相反,每个设计都嵌入在塑造其内在属性的环境中。任何有用的东西的功能总是与其环境有关。当我们理解一个设计良好的东西的环境时,我们就能理解它为何看起来如此。动物的形式反映了它对其环境中生态位的适应。
我所说的“理性”是指某种内在一致性。一个设计良好的东西的功能将具有一种重复的对称性。在设计选择中,它会在尽可能多的场景中一致地使用同一件事物。良好的游戏设计可以让一个物品具有多种功能。在《半条命2》中,重力枪可以让玩家拾取并发射物体。它被用于将环境物品变成武器、解决基于物理的谜题以及到达难以到达的地方。在《我的世界》中,水桶可以用来灭火、创建安全下降的瀑布、灌溉农田以及作为对抗某些敌人的屏障。
我所说的“代数”是指一套关于设计组件如何组合的规则。大多数游戏都有一个物理引擎,用于计算游戏中物体在空间中的相互作用。它是一个“运动计算器”。《塞尔达传说:旷野之息》还增加了一个化学引擎,用于计算不同材料之间的相互作用。它是一个“状态计算器”。
总之,功能代表了控制设计底层组件之间的关系、互动和环境适应性的无形结构。形式不能脱离其功能而存在,而其功能是由其环境塑造的。我们可以直接观察和互动形式,但其功能在没有大量工作来推断它的情况下对我们是不可见的。
一个没有被功能所指导的形式会显得脱节、不一致且令人沮丧。如果没有底层功能来支撑形式,形式的形状就仅仅是设计师不一致的随意想法。功能让设计师对形式的目的保持诚实:为功能服务。当然,你可以独立于功能去探索和玩弄形式,但这属于艺术的范畴,而不是设计。
要发明一种形式,先从功能开始
“形式追随功能”是给那些创造东西的人的建议,尤其是那些工作成果有一个非常直观的界面面向最终用户的人。要发明一种形式,先从功能开始。但即使你已经知道这一点,也很容易犯两种错误。
第一种错误是追求形式而不考虑功能。相反,你必须忽略形式,至少在最初,专注于先弄清楚功能。这主要是因为功能的无形性。专注于形式是一个容易犯的错误,即使在你的创意生涯中也是如此。
这种错误是可以理解的。每当人们与任何东西互动时,他们的最初接触点是界面——用户与设计之间的桥梁。对于任何新接触某事物的人来说,从界面开始是很自然的,因为这是他们最熟悉的部分。因此,当他们反过来在这个领域创造东西时,他们就从界面、形式开始。你可以很容易地看到这一点:一个领域的新创意者会先模仿大师,然后才找到自己的声音。
这也很好理解,因为功能比形式更抽象、更无形。抓住一个无形的东西是更困难的,你可能需要从具体的东西开始。事实上,在面对一个不熟悉的领域时,先画出具体的例子是一个很好的过程。但是,很容易忘记后退一步问:“这些例子的共同底层逻辑或抽象是什么?”当你能够后退一步时,你就是用具体的例子作为理解底层功能的垫脚石。
第二种错误是追求功能而不考虑用户。对于那些倾向于走向另一个极端的人来说,这是一个警告,这并不意味着在弄清楚功能时可以忽略最终用户。如果我们能够将底层功能的实用性表示为一个向量,它仍然需要指向用户的方向。底层功能必须支持并为在其上构建的可见形式提供上下文。两者都是为了使它们的实用性向量的方向和大小能够支持用户朝着他们的目标前进。
太多的后端工程师错误地将“形式追随功能”解释为可以随意设计任意的数据库表和API,假设前端会弥补。这就是我们得到糟糕界面的方式,最终用户需要了解数据模型才能有效地使用它,比如Git。
说到低代码编程,我认为它陷入了第一种错误,专注于形式。
低代码编程不仅仅是节点和连线
节点和连线图已经成为一种懒惰的默认选择。大多数低代码语言设计者从未问过这些方框和箭头是否真的有助于程序员。这是一个典型的让形式先于功能的例子。
更多推荐




所有评论(0)