我们在工作中会使用很多库和框架,同时我也大致学习了几门其他的语言,在我看来这些接口或 api 的设计实在太有学问了。平时工作中也会封装一些库供项目使用,经常需要在功能实现和用户 api 设计上进行取舍,这大概是评判一个库是好是坏最大的学问了。

传统语言

我注意到起步较早的语言,例如 java,所有的代码都是显式可阅读的,显式可阅读的意思是所有的变量、方法都严格的需要显式的定义,对其他类或包的使用必须先准确的导入,也就是说不会凭空出现一个没有定义过的变量,程序员可以追踪一切代码的由来。

在一开始我是极力支持这样的 api 设计的,它使得一切代码都可追踪,准确的知道它的来龙去脉。

后期语言

相对的一些后期出现的语言,例如 go,下划线_是特殊标识符,用来忽略结果,举例来说有一个异常我既不想 cry,catch,也不想 throw,我认为这个异常永远不会出现,你可以用变量下划线_去接收这个异常,表示忽略这个异常,还有在 go 中用首字母的大小写来确定访问权限,再比如 nodejs 中的__dirname变量用来表示当前执行文件的绝对路径。

这些都是语言约定俗称的使用方法,我一开始很反感这样的设计,相信很多传统语言使用者在初学时会产生很多困惑,太多隐式的约定让人摸不着头脑。

但是一旦习惯了这些约定俗称的规定,那就真的太香了,让人从传统语言的繁琐中解放出来。

典型代表

我觉得还有一个例子很适合拿出来讨论,就是 jpa,jpa 是一个全自动的 orm 框架,摆脱 xml 写了 sql 的烦恼,在事务处理型业务、以及没有极致性能追求(大部分情况如此)的情况下适合在项目中使用(数据分析型业务适合 mybatis)。但是因为 jpa 太自动了,它设计了十分精简的用户 api,也就意味着它在库的内部帮你做了很多事。一开始使用觉得很舒服,但是当遇到问题时,就不知道它内部是如何处理的,很难解决问题,于是你要学习很多 jpa 的配置,了解它的内部实现,这就是在代码层面书写简洁的代价。国内大环境还是排斥 jpa 的,觉得不好用令人困惑,其实大部分情况是没有完整的学习过 jpa,而国外开发者清一色 jpa,可以说学习一次受益每一天。

总结

在接口设计时,可以通过约定俗称简化用户 api,但是有一个高昂的学习成本放在开发者面前。如果接口都按照显式可阅读的方式设计,代码会在一定程度上变得繁琐。

具体在实践中如何设计要取决于你对自己项目的信心,如果你认为它真的足够好,以致于其他开发者愿意接受这样的学习成本,那就大胆的去约定规则。

但是从人们心理的角度来说是排斥学习这些规则的,很适合举王境泽的例子,一开始谁也看不起,宁愿饿死也不吃饭,最后饿的不行,那就太香了。同样除非在代码层面已经繁琐的不行了,例如spring,迫切的需要一个解决方案,人们才那么饥渴的需要springboot。但凡用户没有饿的不行,就不要对自己炒的菜太过自信了。