.. Kenneth Lee 版权所有 2018-2020
:Authors: Kenneth Lee :Version: 1.0
再谈什么是高层设计
这次谈架构设计的一个外延。这里用高层设计这种叫法,既可以是架构设计,也可以是系 统设计,乃至大一点模块的概要设计。无论是哪种,下面的讨论都是成立的。
想起要讨论这个话题,是因为最近和一些朋友、同事讨论起新的构架设计趋势,他们谈到 一些构架工具直接转换代码的努力,基于模型进行设计的尝试(比如scade suit这样的方 案),还有通过形式化验证来保证架构上的算法定义可以被彻底地观测等。
我个人不太看好这个方向,我不否认在特定的场合它们可以发挥一定的作用。但他们有一 个依赖在现实中是无法得到满足的。这依赖就是,认为高层设计是可以Specific的。但高 层设计恰恰是不Specific的设计。
怎么说呢?比如说,你跟别人说,“给我来杯咖啡”。这句话(需求)是不Specific的,因 为你没有说:
什么咖啡?
多大的杯子叫“一杯”什么才算给你“来一杯”?
我帮你喝了,然后把账单落你头上算不算“给你来一杯”?
等等。
实际上,没有任何需求是可以Specific的。所以,我们说的Specific,是这个选择在我们 的需求语义范围内,我们就认为它是Specific的。比如我要咖啡。Latte,Cappuccino或者 Mocha都在我的范围内,但矿泉水就不在了。如果我们有这个共识,我们说咖啡,就是 Specific的。
换句话说,我们要把高层要求做Specific,就需要在自己想控制的范围内,把所有的选择 都选择了。如果我们能把所有选择都选择了,我们哪里需要“高层设计”呢?我们做高层设 计的目的,就是为了在陷入细节选择之前,把一些模糊的点挑出来,看看这些点本身,在 逻辑上是否可以自恰。我们是在做反向校验,不是在做正向建模。而你现在想做一种工具 (无论它呈现为语言还是自动代码生成器),只要表述少数的逻辑,就可以表达你的选择 ,这可能吗?
我前几天写了一个关于InfiniBand逻辑空间的分析:infiniband概念空间分析,从这个分 析就很容易看出来,我们可以简单说MR,就说明了所有对内存的要求,前提就是定义这个 名称的细节,并保证这个细节可以解决特定领域的问题。这本质是什么?这本质是抽象。 在特定的领域,某些选择具有共性,所以我们可以抽象,并定义它的细节。这种定义,一 但离开了那个环境(比如这个例子中从RDMA进入本地加速器这个领域),就不再有效的。 然后你想就某种语言为基础,直接定义一个工具进行这种转换?这不是缘木求鱼吗?
所以,所谓模型直接编码,它不是不行,本质上它是定义一种DSL,你得把心思放在DSL本 身的问题上,而不是工具上。前两天我还听了一个软件架构的Podcasts,嘉宾是Humane Assessment Method的作者(Tudor Girba),他有一个观点说得很有道理:我们都觉得我 们可以发明一些工具,把已有的逻辑,通过这些工具来解决。但我们却没有注意到,如果 这些逻辑可以通过工具来解决,这里面必然包含了特定的逻辑,这些逻辑必然是相对固定 的。但我们编码的时候却其实不断在解决新的问题……既然如此,我们发明这些工具的意义 在什么地方呢?
当然,这个问题是可以回答的:这些工具的意义在于固化逻辑。但既然如此,我们的工作 就不是如何做这个工具,而是如何找到这种固化的逻辑,并且固化它,否则进行这样的语 义定义是没有意义的。更不要说现在大部分所谓架构模型生成代码的努力,表达能力远远 不如普通编程语言的表达能力,这相当于让你一个只有英语4级的中国人用英语去讨论哲学 问题,这个东西怎么可能讨论得清楚?
形式化验证是一样的,如果形式化验证本身的模型语言可以表达得和C一样,我们何必用C 来写代码呢?C代码中的每个转折,都有其边界效应在的呀(比如内存和Cache的速度问题 ,Memory Barrier问题等),这些边界效应本身就是它功能的一部分啊,你凭什么认为形 式化验证建模可以约束这些边界效应?
形式化验证在很多地方确实很有用,比如芯片指令的名称空间校验,这些都属于窄接口, 宽实现的场合。但看看“窄接口,宽实现”这个说法:它本质就是模块接口抽象么:)
到头来,这里没有银弹,大部分情况下,核心还是你基于现实的逻辑推演,这代表我们今 天代码的大部分。
上面我想表达的逻辑表达完了,但我有另外一个独立逻辑和这个是相关的,我想顺着推演 一下。没有看过我的《道德经》定义的读者可以忽略。
《道德经》里面有一段很有趣的表述,是关于恍惚的:
视之不见名曰夷。听之不闻名曰希。抟之不得名曰微。此三者不可致诘,故混而为一。其 上不皦,其下不昧,绳绳不可名,复归於无物。是谓无状之状,无物之象,是谓惚恍。迎 之不见其首,随之不见其後。执古之道以御今之有。能知古始,是谓道纪。
这段东西非常难懂,我花了相当长时间理解它。我一直找不到机会把这个理解写出来,因 为它需要一个比较高的抽象层次作为理解的依托,但写在这个文档后面倒是挺合适的。
视之不见,听之不闻,抟之不得名。这个其实很好理解,什么东西是你看见了当没有看见 ,听见当做没有听见的?——答案是,不在你决策链中的东西。你开车的时候扫过前面,你 捕获的仅仅是和你开车有关的信息:有没有人在路上,前面有没有红绿灯等,有没有车准 备并线……至于有个人戴着今年最新款的帽子,还是周杰伦亲笔签名的,你看见了,你就不 知道,因为你根本就不关心。所以,你看见一个东西,你觉得你都看见了,其实你很多东 西根本就没有“看见”。你看见的是你提取的“Pattern”,不是全部,这是我们脑子的本身的 特性(弱点)。
我们看见的是“妙”,是interesting,是“关注点”,不是反馈回来的信息本身。
而且这个东西具有相关性,无法被清晰地定义,完全取决于你如何去建这个Pattern。所以 它不皦也不昧(“不黑不白”也“不不黑不白”的样子,比喻无法确切定义,因为逻辑还没有 被整理出来(为确定目标)。但换句话说,逻辑一旦被确切定义出来,它就丢失更多的精 度了),你在一个方向上(比如开车)提取的“名”(概念),换一个方向(比如追星), 你原来那个名就“不精确”。
所以,“恍惚”就是信息在没有形成逻辑链之前的样子,我们有时思考问题需要这个样子, 这样我们才更精确地了解现实,这个就是“道纪”,基于它,我们就可以响应任何变化,针 对目标去解决问题。而我们所有在开始阶段就进行Specific的努力,就是丢失信息的开始 。
所以,构架设计,其实是维护一种“恍惚”的状态:我维护了很多信息,并在遇到问题的时 候基于目标来把恍惚的信息“清晰化”,去解决那个特定的问题,但我不用这个“清晰化”的 信息作为我思考问题的基本,我用“道纪”作为我考虑问题的基本,这样我在解决新问题的 时候,才能保证信息的最大可靠性。这就是“不为天下先”这个策略的理论基础。