仓库源文

.. Kenneth Lee 版权所有 2020

:Authors: Kenneth Lee :Version: 1.0

所谓内部设计

最近评审一个设计,里面有一个状态机,其中一部分是这样的:

    .. figure:: _static/内部状态.jpg

其中这个Si呢,按作者的说法,这是一个“内部”状态,对你们“外部”的人不可见。我对这 个说法晕死了。我评价说,既然不可见,你写它干嘛?

但作者反驳说:你不看,我们内部设计的人要看,我就多写两句,你咬我啊?

在现场我气疯了,横看竖看都不顺眼,总觉得哪里不对劲,但一时完全不知道怎么反驳这 个说法。

现在我已经冷静了,所以我来思考一下这个问题的核心在哪里。

状态机其实是一种抽象的概念,所谓从一个状态切换到另一个状态,在现实中肯定是一个 渐变的过程,我们不关心这个中间过程,是因为在这个中间过程中,这个系统无论和我发 生什么互动,行为要不和S1一样,要不和S2一样,不会产生额外的情形。

所以,系统被认为在S1状态的时候,发生event1,它必然是执行action1,然后它后面再和 我交互,行为一定是S2的行为,我完全不用管你是不是一点点切换过去的,这里只关心的 是,我只要保证event1发生了,后面再发生别的事件,系统的行为是在S2上定义的,没有 别的情况。这通常要保证中间的过程上,系统接受不了其他事件。

好了,现在你表达给我听,说这是个渐变的过程,S1,是通过S1-Si-S2,S1-Si-S2-Si-S2, S1-Si-S2-Si-S2-Si-S2……等不同的过程变到S2的。这个事情我不关心。你说我不用关心, 这我没有意见。但这时你说,“我这个状态是内部用的”,那我暂时变身为你内部的人,我 就应该认为,这个Si如果是有意义的,你内部会有些不公开的事件在发生着。那就同时意 味着,你内部的人在讨论的时候,认为在S1到S2的跳变过程中,有一段时间里,即使已经 到达你对外承诺的S2状态(注意,这时,在公开的接口上已经可以收新的事件了),你可 以从那个状态离开。你可以说我中间过程都是原子的,这个过程外界事件输入不进来。但 问题是,你的内部状态管理的时候,这个S2是一个固定的状态,不应该在不同条件下有不 同反应的。但你明明不是,你这个状态其实有两个含义:

  1. 对外承诺的S2状态(不得跳回到Si)

  2. 内部中间过程的S2状态(可以跳回到Si)

那你这个状态机其实不是严格在每个状态上对刺激都有唯一反应的系统。那我就会认为你 的内部状态机建模是不靠谱的。你的内部状态机建模不靠谱,我就不会承认你的外部承诺 是靠谱的。

所以吧,我们不要以为内部设计和外部承诺是可以分离的,我们在所谓的“外部”,“内部” 画一条线,只是为了提供一定的变化自由度,这种自由度仍受限于这个接口的属性本身的 。

所以,别动不动就用“这是我内部的问题,对你不可见”来打马虎眼,语义不是出现在接口 定义上的,而是在概念空间上的。如果你在说一个事情的时候,忍不住把一个事情说出来 ,被质疑的时候又说这个东西不可见,麻烦你彻底去掉那个概念,看你是不是还能说通。 否则,你只是在躲设计逻辑链而已,这个问题迟早还是要爆的。

所以,你做Out of Order执行,你做Cache,这些你以为你是内部处理,对用户不可见,其 实你还是要求软件无论是编译器还是高级语言代码,重排指令,按Cachenline取数据,这 些其实都是“可见”的,你躲着说不暴露这种接口,后面也别让用户给你改软件来保证性能 。