目录
- 分界线的两边
- API 不只是技术概念
- 好接口的核心:最小惊讶
- 边界不是墙,是协议
- 厚边界与薄边界
- 回到那条线
分界线的两边
工程师每天都在跟分界线打交道。
模块 A 对模块 B 说"你给我一个整数,我还你一个布尔值",这是接口。微服务 A 向微服务 B 发 HTTP 请求,这是协议。前端告诉后端"我只要这三个字段,别多给",这是边界。
分界线不是为了隔离,是为了通信。
你画了一条线,线这边是我能管的部分,线那边是你的事。我承诺:只要你遵守协议,不管线那边你怎么实现我都不在乎。这就是 封装 的核心——不是藏着掖着,是建立了信任的通道。
有趣的是,这条线的形状决定了整个系统的质量。
API 不只是技术概念
我一直在想一件事:为什么大部分软件到最后都变成一团浆糊?
不是因为程序员不够聪明,不是因为设计文档写太少。而是因为边界在系统演化中慢慢消失了。
A 模块本来只该读 B 模块的公开接口。但有一天,一个紧急需求来了,开发时间不够,于是 A 直接读了一把 B 的内部数据库。这条线被跨过去了。"就这一次"——但这一次就像堤坝上的第一个裂口。下一次又有"特殊情况",再下一次,接口已经形同虚设。
等到重构的时候,没人记得哪些线还在、哪些线已经被踩平了。整个系统变成一个"这里谁都可以访问那里"的平面。每一个函数都可能被另一个天知道在哪里的调用者依赖。改一个字段,炸一片。
这不是技术问题。这是边界纪律的崩溃。
社会关系里也是一模一样的。两个人之间本来有一条边界,你知道哪些话题可以聊、哪些会越界。但当边界被模糊处理——"我们之间不用那么见外"——慢慢地,边界就塌了。不是因为恶意,是因为每一次越界都没有被纠正。
好的关系,和好的代码一样,知道自己在哪里结束,对方在哪里开始。
好接口的核心:最小惊讶
我写过一些接口,也用过很多难用的接口。我自己的经验是,区分好坏的唯一标准是:用的时候,我在想什么?
好的接口让我想的是业务逻辑:"对,这里应该返回真,然后我拿着这个真去做下一步。"我的注意力在我的问题上。
烂的接口让我想的是"这个参数为什么是 nullable 但文档没说""为什么传 'asc' 不排序,传 True 才排序""为什么返回的结构和文档对不上"。我的注意力全都在接口本身上——它在不停地提醒我它的存在。它在刷存在感。
好的接口应该是透明的。你用的时候甚至意识不到它的存在,就像你在看一篇好文章的时候不会去想字体是什么。Font 也是一种接口。
这就是「最小惊讶原则」(Principle of Least Astonishment):接口的行为应该符合调用者的直觉。返回值的名字叫 users,就别忽然在某天改成 user_list。参数叫 limit,就每次限制条数,别在 limit=0 的时候返回全部。
人的交往也是。如果一个人每次回应你的方式都截然不同——今天热情明天冷漠后天客套——你跟他的"接口"就是不可靠的。你没法和一个行为不一致的系统合作。你不确定调用它会得到什么,于是你会慢慢不再调用它。
接口的可靠程度,决定了模块之间、人与人之间的信任密度。
边界不是墙,是协议
有一个常见的误解:认为边界就是隔离。
设计模式里面有个概念叫"发布接口"(Published Interface)。一旦一个接口被发布,你就不能随便改了,因为别人已经在依赖它。你得走 deprecation 流程——先标记废弃,等所有人都迁移了,才能删除。
这听起来像是限制。但它实际上是自由。
因为有了这份协议,服务的提供方知道自己能保证什么,调用方知道自己能依赖什么。双方不需要互相盯着对方的代码。边界给了双方忽略对方内部细节的权利。
我越是尊重你的边界,我就越不需要知道你的细节。我可以把你当黑盒用,而黑盒是简化世界的最强大工具。
人际关系中同样如此。你不需要知道朋友为什么今天不太想说话,你只需要知道 ta 说「今天不太方便」的时候,别追问。你们之间的协议就是:每个人有不解释的权利。这就是边界。
边界不是墙。墙是「你不能过来」,边界是「你可以过来,但请敲门」。
厚边界与薄边界
系统设计中有个经典辩论:该用厚 API 还是薄 API?
- 薄 API:暴露最基本的 CRUD 操作。调用方自己编排逻辑。
- 厚 API:暴露高层次的业务操作。调用方只需说明意图。
薄 API 灵活,但调用方要做的事情多。厚 API 好用,但提供方要做的事情多。
没有绝对的对错,取决于边界两边的能力分布。如果后端团队理解业务,客户端的逻辑应该薄——让后端去做编排。如果客户端(比如前端)更懂用户体验逻辑,后端就乖乖暴露薄接口,让前端去拼。
这个判断本身就是设计能力。
人的边界也一样。有些人喜欢薄边界——"你有什么事直接说,不用寒暄过度。"你抛一个原子操作,对方处理,还给你一个明确的返回值。高效,但有时候感觉冷。
有些人喜欢厚边界——你得先问问"最近怎么样",确认状态再谈正事。这相当于先调一个 health_check(), 再发业务请求。麻烦点,但更有人情味。
没有哪种更好,只有哪种更适合两边的"系统架构"。
回到那条线
最后回到封面上的那条线。它把画面分成两边,光点的节奏不一样——左边密集、右边稀疏。它们各自运行在自己的频率上。
有这条线在,两边都不需要理解对方的全部细节。左边不需要知道右边为什么少,右边不需要知道左边为什么密。它们只需要知道:线还在,协议没变,我可以相信另一边。
我写边界,不是想说「保持距离很重要」。我是想说,清晰的边界让事情能长大。
没有边界,模块纠缠成铁板一块,改哪里都怕溢出。没有边界,人和人之间变成一团混合的情感,说不清谁的情绪影响了谁。没有边界,系统和系统之间互相侵入,每一个改动都变成全站验证。
所以当我在画设计文档的时候,花最多时间想的不是「这个模块里怎么实现」,而是「这个模块和外面怎么通信」。接口定义清楚了,实现只是填充。边界画明白了,里面的东西怎么烂都烂不到外面去。
反过来,边界没画好,里面再漂亮都是白搭。
设计是画分界线的艺术。
评论(0)
暂无评论,来写第一条吧~