.. Kenneth Lee 版权所有 2023
:Authors: Kenneth Lee :Version: 0.1 :Date: 2023-01-09 :Status: Draft
细节迷信
最近有一些模模糊糊的关于架构沟通的感受,我看看能否通过本文让它清晰一点。
这种感受通常是这样来的:有些人写了一个设计,我看完就不想看下去,但别人要求我给 个意见,我可能只适合选择说:“我看不懂,没有意见。但要我签字给钱,我肯定不给。”
但这样可能别人还是会有意见的:这么多人都给意见了,你凭什么不给?你要反对就堂堂 正正反对,给出反对的理由,这不给意见又不同意,你这是怠工。
但我确实不是怠工,这种问题怎么发生的呢?让我一点点类比来说明这个问题。
比如说,你让我和另一个人打一架,而且告诉我说,他只有一米六,平时抽烟,但不喝酒, 写字工整,有一个儿子一个女儿,老婆是个售货员……所以我肯定能打赢。
你说我信吗?
我当然不信了。拿着这个信息我没法做判断啊,你给了我很多信息,但拿着这个信息我也 没法作出有效的判断啊。
这是一个明显的例子:虽然你给了我很多“信息”,貌似做了一个“设计”,但我根本没法采 信你这个设计。
但这个例子对工程师说服力不强,因为这个例子的错误太明显了,我只是用来强调我在说 什么,我现在给你一个更真实的例子。
比如有人要做一个硬件自动Page Fault的设计,有人这样总结Linux的Page Fault的所有情 形:
然后他就开始讲他的从硬件发起缺页的方案了。
你说他前面这个总结对不对呢?如果你当作科普读物来看,基本上也不能说错,但你要我 按这个来判断他的方案对不对,他这个总结对我来说,和前面那个打架的例子一样,都是 毫无意义的信息。但这种情况,因为细节多,很多工程师就分辨不出来它们其实不能成为 我们判断的理由了。更不要说再插进来一批不是这个领域的其他工程师,或者只做管理的 各级经理和技术领导了。
Linux的缺页处理太复杂了,设计大量的代码,不同的平台,不同的版本,不同的配置,稍 有一点变化,某些逻辑就不成立。所以,简单几行字,(即使补上我前面省略掉的一些细 节,)也是无法总结的。
这种总结要起作用,只有到了你拿它推出某些结论的时候才是有效的。你要让硬件来完成 这个缺页,那你前面的总结就必须从某个角度“穷举”所有有可能被硬件缺页取代的情形, 然后一个个对上你的方案,表明这些情况你都可以解决。这种总结就是可被判断的。你给 我来一堆只是“总结上没错”的话语,然后另外去谈你的方案,你前面这些证据就不是证据, 而是装饰。这种所谓“设计”,我就当作“没有”,你问我有什么意见,我的意见就只能是“你 重写吧”,或者“你给钱我帮你重写吧”,反正你让我提“意见”,我是给不了的。我甚至认为 它说得每一句都“对”,但“毫无意义”。
这个问题的本质是什么呢?我觉得主要就是“设计是不能运行的”,所以我们很多人的设计 其实是用来忽悠自己的,他们只是打算尽快编码,看运行的结果是不是对的,然后他们就 觉得“这就证明我的设计是对的了”,这是他们对设计的唯一证明方法,他们不能靠脑子来 证明某个概念模型是正确的。
所以,不少工程师把信息建立在代码上,或者接近代码的“详细设计”上,他们高层概念建 模是随便说说的,他们真正的信心是那些复杂的消息顺序流图,或者复杂的API列表,甚至 是包含很多循环递归的算法。他们觉得:“你看,我这么复杂的(你们没有写过这个代码都 看不懂的)的流程和参数都给出来了,你们怎么还不觉得我的高层抽象是有道理的呢?”
我一度认为,这种想法也不算错,毕竟能证明抽象的只有具像。但看了一堆不实用的最终 设计后,我发现并非如此。所有这类设计的失败,都源于我们我们的代码只是其中一个具 像,但我们的软件要运行在各种抽象上(软件必须在时间和空间的广度上使用)。所以, “只要能写出代码而且测试良好”我们的抽象就被证明了,这是自己骗自己。因为很多产品 到拿到市场上去的时候,应用到各种场合的时候,你才发现它根本就没法工作,因为当初 就只考虑过实验室的环境。
所以,设计是不可取代的,没有设计,就没有抽象,没有抽象,就没有适应性。用别人定 义的框架(比如开源软件,标准组织的定义),你以为设计不重要,但离开了那些软件和 标准组织,你活不了三天。
所以,我个人非常反对用PPT写设计——你用文档写设计,你的逻辑通常是不得不连续的——你 总得说——我发现有如下规律,因此我可以在这里加一组行为,这样这个规律就会变成这样, 所以,我们就可以得到这个……这样,你整个证明就是有序的。
但如果你用PPT写,你常常就可以先写一个“Page Fault”的特点,“硬件处理缺页的流程”, “性能测试结果”……这中间是啥关系,你其实就没有正经想过。人脑其实相当懒惰,它是找 到某种Pattern就认为规律存在的。只要看见“因为……所以……”,然后因为和所以里面有相关 专业的名词,可能它的承认了这个规律存在了。但这样并不能保证我们的设计成立。
当然,你非要分离这种逻辑链条,非要你写文本文件,你一样可以让逻辑链支离破碎。很 多特别喜欢“模板”的工程师就是这样:每个模板章节都填点东西进去,逻辑只和模板标题 有关系,互相之间就没有关系了,和目标就更没有关系了。这没有意义。但至少,写连续 的文本对比写分离的页表至少文本提醒了你需要维持逻辑的连续性。
前面说的这个问题只是问题的主要方面。在这种证明中,我常常还碰到另一个问题:工程 师在对比现有方案的时候,常常去比较现有方案的某个特征,而不是引入这个特征的原因。
比如他们会说,RDMA做内存迁移的时候需要pin住物理页,我们可以不pin住物理页,这样 性能就比较高了。谁不知道不pin住物理页性能比较高呢?但为什么人家要pin住物理页啊? 你得消除掉这个原因才能谈你的优势啊。
这种时候,他又常常开始在他的细节中找出一堆的要素来,说:“我这里这样这样,那里这 样这样,所以我就不用pin了。”,这特别迷惑人:在大量的细节中取出一组细节,我先不 说这组细节是否真能证明你说的结论。你不把这组约束放在高层抽象中,你如何保证在后 续的升级维护中,你可以维持这组细节成立呢?如果你的每个目标的保证,都是依赖一组 细节来保证的,最终这个系统的全部目标组合在一起,你是靠什么来保证这些目标(的支 撑细节们)是不会发生逻辑冲突的呢?
这些情形,都是“细节迷信”,觉得“细节都可以了”,抽象怎么可能不成立?这种想法本身 都是毫无逻辑的。