计算机领域有句话:“计算机的任何问题都可以通过增加一个虚拟层来解决”。另言之:"All problems in computer science can be solved by another level of indirection"。其主要思想是将调用者和被调者隔离开,既屏蔽细节,又提高了灵活性。由于标准统一在此处收口,因此又提高了效率与安全性。
这个思想在计算机硬件、计算机网络、计算机网络无不如此。计算机网络的7层协议,每一层都可以看做下一层的虚拟层;计算机操作系统可以看作计算机硬件的虚拟层;JVM可以看作是操作系统的虚拟层;分层的计算机软件架构事实上也是利用虚拟层的概念;开启了云计算时代的Virtual Machine是bare metal/host OS的虚拟层(上层是不同的guest OS)。
这个思想在生活中也是经常见到。例如:集装箱的引入大大提升了全球化的效率。原来的货物都是杂乱的堆在车里或船里,而集装箱将货物和承载货物的工具分离开,大大提高了运输的效率,还增强了安全性。
有的人也许觉得集装箱不算什么大发明。但事实上它的标准化能大大提升效率。之前看到SAP的基础引擎提供了一套标准化的插件机制,所有的产品都是基于一个统一的插件开发平台,每一个产品都是一个插件,每一个插件都按照名字约定好了。大家都遵守这个简单的“共识”插件架构进行开发与维护,效率大大提升。这正是SAP基础引擎平台的神奇之处。背后的道理与集装箱是一样的。
道理非常简单,似乎人人都懂,但做起来并不那么简单。知道系统里哪个部分需要动手术加一层indirection,考量的是能力、经验和智慧。展开来说一下:
第一、抽象能力。计算机的任何问题都可以通过增加一个虚拟层来解决,这一虚拟层为什么要加,加在哪里?需要“抽象”。抽象是简化问题、解决问题的核心,也是设计的精髓。为什么要抽象?抽象能带来间接(Indirection),能隔离变化,间接能控制依赖方向,间接能提供扩展性。
比如:SOA也是这样的抽象和屏蔽实现的思想。插件框架也是用OSGi框架作为中间层来向上层屏蔽实现的细节,而ORM是对数据库的抽象。
第二、业务能力。业务理解深刻了,逻辑清晰了,自然就知道哪里经常变化,哪里可以进行共性的提炼。举个栗子:你经常写网页,后来发现数据与显示分离的好处,并且设计出MVC模式。因此,好的抽象与架构是不断对业务进行分析和思考而获取的。架构源于分析,而非设计。分析源于对业务的深刻理解。要想获得可扩展性,你需要看得远一点,对上下文做充分的了解。
第三、性能。分层的优点在于,依赖方向得到最好的控制,而且代码复用高、耦合低。每个层次有自己的核心问题,比如引擎这一层就是做一些业务无关的功能,比如渲染器、物理引擎。比如框架层就是为业务支撑的,着眼于开发效率。但随之而来的问题是多引入一层虚拟层带来的系统性能瓶颈问题如何解决。这个考验功底了。
最后要提醒的是,增加虚拟层也许会有一些副作用,最有名的是污水池反模式(architecture sinkhole anti-pattern).这个反模式是这样的,请求流简单的穿过几个层,每层里面基本没有做任何业务逻辑,或者做了很少的业务逻辑。比如一些JavaEE例子,业务逻辑层只是简单的调用了持久层的接口,本身没有什么业务逻辑。这其实是一种形而上学。本文强调的是一种思想,切记!