做事的方法 · 3 min

我喜欢的抽象,是让人少想一点

复杂性不会凭空消失。但一个清晰的边界,能让它不必出现在每个人面前。

先把问题说清楚

我更信任那种能用一句话说明职责的模块。它处理什么,接受什么输入,哪些事情明确不归它管。名字、边界、失败方式都说得清楚,代码往往也会跟着变得容易理解。

反过来,一个抽象如果必须先解释整套框架才能使用,可能只是把原来的复杂性换了个位置。层数增加了,使用者要记住的事情却没有减少。

模型是为了少一些猜测

以一个数据表字段为例,字段标识和显示名称不是同一件事。名称可以改,引用不应该随之失效。把这两个概念明确分开,比约定“大家记得别用名称作为主键”更可靠。

领域建模吸引我的地方就在这里:把模糊的约定变成系统可以表达的约束。模型不是为了显得严谨,而是为了让下一个修改它的人少猜一点。

type Field = {
  id: string;   // stable identity
  name: string; // editable label
  kind: 'text' | 'number';
};

界面也是边界

一个好用的界面不该把所有内部状态都倒给用户。它应该让人知道现在能做什么、做完会发生什么、失败后怎样继续。内部可能有缓存、队列和事务,但这些不一定需要变成界面里的三个新概念。

隐藏实现不等于隐藏后果。删除会影响什么、数据是否保存成功、一次操作能否撤销,这些必须表达清楚。少一些需要理解的机制,不能以少一些掌控为代价。

给变化留一个入口

边界的价值,还在于让改变尽量停留在一个地方。存储方式可以变化,用户看到的记录标识不必变化;一个页面可以重做,领域规则不应该跟着复制一遍。

我并不认为每个小程序都需要复杂架构。先有一个真实的问题,再找到值得保护的边界,通常比预先设计所有可能性更踏实。

最后还是回到使用者

判断一个抽象好不好,我会问:一个第一次接触这里的人,要记住多少额外信息,才能安全地完成一件小事?如果答案没有变少,结构再漂亮,也值得再想一遍。

公开参考