![](https://csdnimg.cn/release/download_crawler_static/87207637/bg4.jpg)
用的 API,作为框架的实现者,我们往往会进行一些妥协,我们可能会为 了在框架内部 DRY
而设计出一套丑陋的 API 让框架的使用者去做一些重复的工作;我们也可能会因为想让框架
变得更松耦合强迫框架的使用者去使用到框架的一 些内部 API 去初始化框架的组件。如果
框架不是易用的,那么框架的内部设计的再合理又有什么意义?
尽量少暴露一些框架内部的类名吧,对 于框架的使用者来说,你的框架对他一点都不熟悉,
如果要上手你的框架需要学习一到两个类尚可接受,如果要使用到十几个类会头晕脑胀的,
即使你的框架有非常 多的功能以及配置,可以考虑提供一个入口类,比如创建一个
ConfigCenter 类作为入口,让使用者可以仅仅探索这个类便可对框架进行所有的配置。
一 个好的框架是可以让使用者少犯错误的,框架的设计者务必要考虑到,框架的使用者没
有这个业务来按照框架的最佳实践来做,所以在设计 API 的时候,如果你希 望 API 的使用
者一定要按照某个方式来做的话,可以考虑设置一个简便的重载来加载默认的最合理的使用
方式而不是要求使用者来为你的方法初始一些什么依赖, 同时也可以在 API 内部做一些检
测,如果发现开发人员可能会犯错进行一些提示或抛出异常。好的框架无需过多的文档,它
可以在开发人员用的时候告知它哪里错 了,最佳实践是什么,即便他们真的错了也能以默
认的更合理的方式来弥补这个错误。
建议所有的 API 都有一套统一的规范,比如入口都叫 XXXCenter 或 XXXManager,而不是叫
XXXCenter、YYYManager 和 ZZZService。API 往往需要进行迭代和改良的,在首个版本中把
好名字用掉也不一定是一个好办法,最好还是给自己的框架各种 API 的名字留一点余 地,
这样以后万一需要升级换代不至于太牵强。
下一步工作就是把项目中那些空的类按照功能进行划分。目的很简单,就是让你的框架 的
100 个类或接口能够按照功能进行拆分和归类,这样别人一打开你的框架就可以马上知道你
的框架分为哪几个主要部分,而不是在 100 个类中晕眩;还有因为 一旦在你的框架有使用
者后你再要为 API 相关的那些类调整包就比困难了,即使你在创建框架的时候觉得我的框架
就那么十几个类无需进行过多的分类,但是在将 来框架变大又发现当初设计的不合理,无
法进行结构调整就会变得很痛苦。因此这个工作还是相当重要的,对于大多数框架来说,可
以有几种切蛋糕的方式:
分 层。我觉得框架和应用程序一样,也需要进行分层。传统的应用程序我们分为表现层、
逻辑层和数据访问层,类似的对于很多框架也可以进行横向的层次划分。要分 层的原因是
我们的框架要处理的问题是基于多层抽象的,就像如果没有 OSI 七层模型,要让一个 HTTP
应用去直接处理网络信号是不合理的也是不利于重用的。 举一个例子,如果我们要写一个
基于 Socket 的 RPC 的框架,我们需要处理方法的代理以及序列化,以及序列化数据的传输,
这完全是两个层面的问题,前者 偏向于应用层,后者偏向于网络层,我们完全有理由把我
们的框架分为两个层面的项目(至少是两个包),rpc.core 和 rpc.socket,前者不关心 网络
实现来处理所有 RPC 的功能,后者不关心 RPC 来处理所有的 Socket 功能,在将来即使我们
要淘汰我们的 RPC 的协议了,我们也可以重用 rpc.socket 项目,因为它和 RPC 的实现没有
任何关系,它关注的只是 socket 层面的东西。
横切。刚才说的分层是横向的分 割,横切是纵向的分割(横切是跨多个模块的意思,不是
横向来切的意思)。其实横切关注点就是诸如日志、配置、缓存、AOP、IOC 等通用的功能,
对于这部 分功能,我们不应该把他们和真正的业务逻辑混淆在一起。对于应用类项目是这
样,对于框架类项目也是这样,如果某一部分的代码量非常大,完全有理由为它分出 一个
单独的包。对于 RPC 项目,我们可能就会把客户端和服务端通讯的消息放在common 包内,
把配置的处理单独放在 config 包内。
功能。也就是要实现一个框架主要解决的问题点,比如对于上面提到的RPC 框架的 core 部
分,可以想到的是我们主要解决是客户端如何找到服务端,如何把进 行方法调用以及把方