3.91. 回调还是直调

我们常常遇到这样一种构架选择,我们实现一个功能,提供funca, funcb, funcc三个接口(也可能是四个、五个接口,类别而已),但我们对这三个功能有多种实现,比如我们有三个模块P, Q, N,都可以提供这三个接口相关的功能。

这时我们有两种架构选择:

第一种:P,Q,N都提供func[a..c]接口,在实现的过程中,发现他们有重复的代码,就抽象为公共函数,由公共模块COMM提供。这种选择比较安全,是根据需要“自然”产生的抽象结构。

第二种:实现一个PROXY作为funca, funcb, funcc的代理,P,Q,N提供一组回调函数,支持COMM对三个功能的提供。

最终判断应该用哪个方案的标准是比较简单的:如果最终PROXY只是一个二传手,每次调用基本上都是二传给P,Q,N,这个PROXY就失败了,不如一开始就直调P,Q,N。更失败的情形是,PROXY里面还要反复判断P,Q,N的属性,从而走入不同的流程,这相当于很多流程都被判断了多次(如果一开始就进入P,Q,N其中一个,根本就没有这些事),这样这个构思就流于失败了。

当然,很多时候我们需要P,Q,N在一个二进制中共存,所以PROXY是必不可少的,但如果我们认为这个需求可以简单通过代理func[a..c]直接实现,不认为PROXY中有额外的代码,我们的问题还是前面这两种模式中选择一种。

如果我们可以预判func[a..c]的实现大部分都是公共的,需要P,Q,N的支持非常有限(比如只有init和read/write一类),那么,很自然我们可以选择第二种方案。

但如果我们对此没有把握呢?比如,我们对于PROXY的详细流程推演还在初期阶段,我们很难猜走到什么流程的时候,会需要P,Q,N都补上什么回调的时候,我们应该作什么选择?特别是这个选择可能要几年的发展才会最终确定的时候,我想,第一个方案是不二的选择。无论未来会怎么样,后者变前者的成本很高,但前者变后者的成本就低得多。