仓库源文

.. Kenneth Lee 版权所有 2020

:Authors: Kenneth Lee :Version: 1.0

真假架构设计


上周评审了一个架构设计,看到一个典型错误设计,在这里记录一下。

老规矩,我把原来的实际情况用一个类似的例子来隐藏我们的具体技术细节。

比如说,你有三种不同的数据,作为你的输入,对数据进程处理后,输出一个商业决策。 有人做出这样一个设计:

    .. figure:: _static/商业决策例子建模.jpg

这个架构设计对吗? 我对它评价是:这个架构设计根本就没做。

当然,仅仅从这幅图你是看不出来问题的。把三种数据规整为一个封装模块,这个逻辑根 本不是这个设计的关键,这个设计的关键是:这三种数据是否有共性允许你你做出这个封 装!

很多人觉得数据封装层,硬件抽象层是万能的,仿佛写上这么一个东西就是架构设计了。 这其实在学架构设计的样子,这种设计根本起不到“保证下一步设计的构架空间可靠”这个 作用。

我给你的数据里面是否有保证数据处理输出要求的商业决策必须的逻辑?这个才是问题的 关键。所谓抽象层,关键是你是否看到变数。抽象层是有成本的,这个我们以前就谈过了 ::doc:线程的本质

如何平衡这个成本?这在于你如何确定这个控制变量(这是通用概念的控制变量,不是函 数的参数),比如你有这样一个接口:::

    input_data(int[10] data);

这里引入了一个变量:数组的内容。

我们可以扩展:::

    input_data(int[] data, int len);

这里我们引入了第二个变量:数组的长度。

我们还可以引入第三个变量,数据的类型:::

    input_data(type[] data, int len);

我们还可以无限增加下去,完全看需要。所谓封装层,抽象层,是把你的多种对象的“不同 ”转化为控制变量,从而可以降低多个处理的成本。但控制变量越多,实现本身的成本就越 高。因为使用这个数据的程序的分支就越多,响应设计和测试成本也越高。而且这个复杂 度的提高是指数级的。更不要说到维护的时候,你面对情况太多,很可能你根本改都不敢 改。

要降低这个成本就至少要保证这个变量的引入是必须的。比如你把数组大小作为控制变量 ,结果你的用了三年,所有模块给你的数组大小都是10,你这个变量就是多余的。别跟我 说什么“我架构好”,你好条毛,钱呢?你产品变快了还是你成本降低了?除了自我感动你 拿到啥收益了?

所以你完全不分析你的实际情况是什么样的,不去找这个控制变量是什么,直接来个“封装 层”就叫设计。那就怨不得某些人天天嚷着设计都是浪费时间,不如早点编码。因为你给你 时间做设计,你完全就是在玩么。

当然,不少人写出这种架构设计的时候,其实就没花时间,背后全偷偷在写代码呢。但以 我的经验,这种不做架构设计推演的代码,通常就是现在先顶住,它的逻辑链窄得像钢丝 一样,一个变化都响应不了,深度撑不了岁月,广度撑不了生态扩展(用户场景变多)。

说到底还是这句话:守弱,真心面对问题,不要学个样子。就例子中这个设计,你不定目 标,其实是设计不出来的,你可以把支持更多的数据类型作为目标,这时你的重点是要调 查所有数据类型的共性,你的分析程序是要为这种变数埋单的,因为你要接受可能很多数 据不存在或者不是你想象的那个样子。你也可以把速度做上去作为目标,这时你要把最关 键的数据作为必须输入,这样你就需要放弃部分数据类型,用最少关键控制变量来控制你 的范围。目标稍有变化,设计就会完全不同。架构设计是权衡,不是某个固定的样子。