构架的关键是解耦,尤其是对一些“重要”决定的解耦。在软件开发初期,经常会有一些看似很重要但是与业务逻辑其实没有关系的决定,例如框架,数据库,服务器等。一个优秀的系统是不会依赖于这些决定的。
我们要对这些于业务逻辑无关的“重要”决定划清界限。
例如:
在这样的构架下,数据库和GUI于核心业务逻辑划清了界限,所以数据库和GUI相对于业务逻辑只是可替换的插件。
独立可执行文件
- 界限: 通过面向对象中的多态和继承来实现界限的分割。
- 依赖: 源码依赖,低等级模块实现高等级模块的接口。
- 通讯: 内存内方法调用,代价很低,可以频繁交流。小于1ms
动态库连接
- 界限: 通过一些语言和框架的特性来将模块分割为可独立开发和部署的单位。例如jar,exe,gem等。
- 依赖: 源码依赖,低等级模块依赖于高等级模块的接口。
- 通讯: 内存内方法调用,代价很低,可以频繁交流。小于1ms
本地多进程
- 界限: 通过进程进行分割,模块将被分割为可独立开发,部署和运行的单位。每一个模块都是一个完整的子系统。
- 依赖: 通讯协议依赖。低等级的模块需要知晓高级模块的通讯协议和地址。
- 通讯: 通过本地的socket或者消息队列进行通讯。代价相对高,小于10ms
服务
- 界限: 在所有模式中最强的界限,模块将被分割为不同服务。每个服务拥有自己的服务器和地址。
- 依赖: API依赖。低等级模块依赖于高级模块的API和数据结构。
- 通讯: 网络通讯。 10ms ~ 10s
