pstack 拆解 03 · 基础与体验
模型不会替你判断"这个数据结构对不对",它只会围绕你给的形状把代码补全。所以最靠近地基的决定必须你来拍。
这一篇讲两条:先把核心数据结构定下来,以及在实现便利和用户愉悦冲突时选后者。
foundational-thinking
基础思考的背后是一个很老的程序设计判断:程序等于数据结构加算法,而这两者的难度是不对称的。 学术练习里算法是难点,但在真实的业务系统里,算法通常是平凡的;真正复杂的是数据本身,以及它随时间、并发和边界演化出来的形状。所以重心的正确位置在数据。数据结构定对了,控制流和函数往往自己就变得显然;定错了,后面每个函数都在跟形状搏斗。这不是"先写类型再写代码"这种规矩,而是一个关于难度分布的判断。
它有一句判据:先把核心的数据结构和类型定下来,再写逻辑。
原文把这一点分得很清。结构决策保护的是未来的选择权,代码级决策保护的是简单性。这是两类不同的决定,不要混在一起。
它的细则。
先数据结构。 尽早定义核心类型,把每一种访问方式都走一遍,选出和主要路径匹配的结构。不要一边写逻辑一边改数据结构,那样每改一次都在还债。
在代码层面,DRY 的是结构,不是每一行。 类型和数据模型应当收敛,三句相似的话仍然好过一个过早的抽象。显式胜过聪明。
并发推论。 在两个 actor 之间共享状态之前,先问一句:如果另一个 actor 同时改它,会发生什么?只要答案不是"什么都不会发生",就隔离。
先搭脚手架。 如果某样东西让后面每一个阶段都受益,就先做它。CI、lint、测试基础设施、共享类型都是脚手架。排序为的是选择权:设置先于功能,测试先于修复。
每个增量都落地一个连贯的抽象,或者加深已有的抽象。 不要把一个新能力拆成一堆特殊情况,散到各个调用方去协调。
减法排在脚手架之前。 先清干净,再打地基。
落到一句检验上:数据结构定对了,下游代码会变得显然。如果你发现自己在写第六个特例分支,大概率是结构错了,不是逻辑不够多。
experience-first
体验优先的背后是一个价值排序:软件存在的意义在使用者那里,实现只是手段。 这个排序听起来显然,但默认的惯性恰恰相反:写代码的人会自动优化自己顺手的一侧,把难做的交互砍掉、把不顺手的状态留成边界情况,而这些都是以牺牲体验为代价,换取实现的省事。所以这条原则是要把默认的排序扳回来。它同时也给"用户"划了范围:UI 的用户是使用者,库的用户是 import 它的同事,下一个维护者也是用户。
它有一句判据:当实现便利和用户愉悦冲突时,选用户愉悦。
它的细则。
每一项都要有理由。 一个功能、一个控件、一个选项,如果说不清它为谁解决什么,它就不该存在。
少而精。 三个打磨到位的功能,胜过一个粗糙的十个。功能数量不是进度。
先做原型再承诺。 设计决策在扔掉的 HTML 里做,比在生产代码里做便宜得多。
把细节做对。 过渡、对齐、间距、反馈、错误状态,这些就是体验本身,不是收尾工作。
收紧核心循环。 每个功能要么服务于中心工作流,要么给它让路。
它和 foundational-thinking 的关系值得记住。原文有一句,基础应当服务于体验。基础思考管的是工作的顺序,体验优先管的是目标。一个决定先做什么,一个决定做到哪里算好。
参考
原文都在 pstack 上游仓库(cursor/plugins):