第12章
第十二章 封装是什么:隐藏细节,还是形成能力?
一 一个按钮后面,可能是能力,也可能只是包装
两套系统都只有一个按钮,按钮上都写着“检查证明”。第一套系统把文字交给生成模型,请它给出一段评价;第二套系统要求命题具有明确的形式表达,生成可检查的证明对象,报告使用的假设,并在无法完成时返回未解决的义务。两者的界面同样简洁,不能因此说它们封装了同一种能力。前者可能提供有用建议,后者则可能在限定范围内承担一种较清楚的检查任务。名称没有决定作用,内部形成了什么可运行关系才有决定作用。
这使我们首先区分包装与封装。包装改变成果呈现给使用者的样子,封装改变后续活动可以可靠调用什么。一个漂亮标题、一份结构整齐的报告、一段从容的解释,可以改善沟通,却不自动增加结果成立的依据。把没有解决的问题隐藏在流畅表达里,只是减少了疑问的可见性,并没有增加活动的可靠性。
反过来,封装也不以界面漂亮为必要条件。一份格式朴素的程序,只接受满足明确约束的数据,给出可以复算的结果,并清楚返回错误原因,可能比一个无所不能的对话窗口更适合作为后续研究的条件。可调用性不等于顺手感;顺手而无法辨明适用范围,甚至可能使错误更容易进入下一层活动。
设想一个求平方根的工具。对非负实数,它返回非负平方根;对负数,它拒绝按实数任务继续,并询问是否切换到复数问题。这个小小的停顿十分重要,因为它保留了对象改变的痕迹。另一工具直接输出一个看起来合理的数,既不说明数域,也不说明取值约定,用户虽然得到答案,后续运算却可能已经建立在不同问题之上。
一个成熟单元因此不只是“能产生结果”,而是使结果与任务之间形成稳定联系。我们应当知道它正在完成哪件事,在什么条件下声称完成,结果带有什么依据,哪些情况不属于它的承诺。并非这些信息每次都要完整展示,但它们必须以适当形式存在,并能在需要时进入活动。
工具说明书本身也可能只是包装。写着“高准确率”“专家级”“全面审核”,却不说明任务、样本和失败条件的说明,没有形成可使用的边界。真正的封装说明应能帮助使用者作出不同决定:这类输入可以继续,那类输入需要转换,有些结论只能作为候选,还有一些地方应当停止调用。若所有情况都得到相同的绿色标记,说明便没有承担区分作用。
这一区分对于教育尤其重要。一个教学平台宣称封装了“理解力”,但实际只提供标准答案和解释文本,所封装的可能只是解释生成,不是学习者理解的发生。后者还涉及学习者如何进入任务、怎样形成差异辨认、怎样迁移和修订。平台的输出可以成为条件,却不能把尚未发生在学习者活动中的能力也一并宣称已经交付。
同样,一套科研智能体可以封装文献整理、候选命题生成或某些验证流程,却不能仅凭覆盖了从题目到论文的全部栏目,就宣称封装了完整科研。研究中的问题适当性、证据充足性和成果新颖性,各有不同成立条件。把栏目连在一起,可能只是把若干未完成义务连在一起,而不是使它们共同完成。
本书因此主张对封装采取一种关系性的定义:在指定任务范围内,一组过程及其支撑条件获得可重复调用的组织,能够输出具有相应依据的结果,并保留异常响应与修订路径。定义中的“指定范围”不是为了减弱工具,而是为了让工具真正成为条件。没有边界的全能承诺,反而不能稳定支撑任何具体研究。
当我们说刀封装了一部分切割条件,或者一套程序封装了一种计算,所说的都是这种相对稳定的调用关系。工具没有装进一份完整的人类意识;它改变的是过去探索形成的条件如何在此刻继续生效。封装的本体不在外壳,而在后续活动与过去能力之间建立了什么可持续关系。
二 封装说明的五个位置
为了把讨论落到可以分析的对象,本书采用一个简明的封装说明:C=〈任务,条件,过程,依据,重开规则〉。这不是给世界另立五项基本元素,也不是证明可靠性的公式。它只是要求一个能力承诺回答五类问题,避免把“这个工具很好用”当作全部信息。不同领域可以有更精细的说明,五个位置是分析起点而非统一认证标准。
任务回答“究竟完成什么”。寻找一篇文章、总结已经提供的文章、判断文章是否支持某项结论,是三项不同任务。一个擅长摘要的系统,不会因为摘要写得准确,就自动擅长查证来源;一个检索到相近标题的系统,也不意味着找到了所需要的证据。把任务写清,是阻止能力信用在相邻任务之间无依据流动的第一步。
条件回答“在什么范围内完成”。对一种数学程序,这可能包括数域、精度、维数和输入类型;对文献整理,这可能包括材料是否完整、版本是否确定、语言是否可处理。条件不是附在末尾的免责文字,而应当参与调用决定。违反条件时仍然照常输出,意味着封装没有把自己的边界带入运行。
过程回答“怎样组织活动”。这里不要求普通调用者阅读全部实现细节,而需要说明哪些环节承担哪些任务,特别是可能改变结果意义的环节。例如,先提取原文再概括,与先凭题目推测再寻找佐证,是不同过程;把不同模型的意见汇总,与用独立证据检验意见,也是不同过程。即使最终文本相似,依据结构仍有实质差异。
依据回答“为什么有理由接受”。数学证明、实验测试、来源核对和专业审查,都可能提供依据,但不能随意互换。一个命题在很多数值上成立,不等于它已对所有情况被证明;一份材料有正式出版标识,不等于其中每个结论都适用于眼前问题。依据必须与声称的完成程度相配,否则封装只是把证据类型的混淆稳定了下来。
重开规则回答“什么时候不应再把它当作整体使用”。输入条件改变、出现与结论冲突的证据、依赖版本更新,或者任务转向原本未承诺的目标,都可能触发重新展开。重开不意味着每次都推倒重来。它应当定位需要重新认识的部分,使已成立的内容可以保留,而不成立的连接能够被修改。
让小林使用一个矩阵计算单元。任务是计算给定矩阵对一个向量的重复作用;条件是有限维、数值类型明确、计算步数已定;过程是逐步乘法或经过验证的等价算法;依据包括精确运算核对或误差说明;重开条件包括改变数值精度、改变矩阵族、由有限步观察转向无限时间结论。最后这一项尤其重要,因为任务的逻辑性质已经变化。
如果小林观察到一百步后的数值很接近,她可以报告这次计算的现象,却不能从同一个按钮直接取得“必然收敛”的信用。计算单元没有失职,错误发生在调用者或上层流程扩大了结论。封装分析由此能够定位失败:有时内部过程错了,有时输入越界,有时结果被误解,有时任务被静悄悄地换掉。不同失败需要不同修复。
五个位置还使改进变得具体。若问题在适用条件,就补充或改变条件检测;若问题在证据,则增加恰当的核验;若问题在结果解释,则改进接口;若问题在异常处理,则形成重开路径。不是每次失败都需要更大模型,也不是每次成功都说明全部位置已经成熟。能力建设因此可以摆脱单一规模竞赛。
这些说明可以分层保存。一般调用时,用户看到任务和关键条件;需要研究时,能够进入依据与过程;出现异常时,找到对应修订路径。把全部细节同时铺开并不叫透明,可能只是把识别关键问题的负担重新交给用户。好的封装说明应当降低无关复杂性,同时提高与当前决定有关的信息可达性。
对于普通生活服务,说明可以非常简短;对于论文中的关键依赖,说明需要更具体。不能把一套用于高风险研究的完整表格强加给每次日常调用,也不能因日常调用追求方便就取消科研依据。颗粒度应当跟随任务,而不是由一种普遍的审计冲动决定。
三 隐藏实现为什么可以增加理解
帕纳斯在关于模块划分的经典论文中,对按处理步骤分割系统与围绕设计决策进行信息隐藏的划分作出比较。他所讨论的目标包括灵活性和可理解性,而不仅是把程序切成较小片段。[13] 对本书而言,重要启发是:不必把全部内部细节暴露给每一个相邻环节,反而可以使关系更清楚、修改更可控。
设想一套文献平台,把文章存储、来源定位、段落引用和论证写作组织成不同单元。写作模块应当得到确定的段落和出处,不应需要知道资料存放在哪一种磁盘结构中;更换存储实现,不应迫使所有研究者重新学习引用。这种隐藏保护的是稳定关系,不是把证据藏起来。用户仍须能够看到所引原文,内部文件怎样索引则可以由另一层承担。
由此可见,隐藏细节与隐藏依据是两件事。前者可能支持可靠调用,后者可能制造盲目信任。一个程序可以不向每位用户展示排序算法的每一步,同时明确排序依据和结果类型;一个研究系统却不能把尚未核实的引文来源也一并隐藏,并以商业秘密为由要求读者接受。哪些细节可以被保护,哪些依据必须可得,需要依据它们在任务中的作用判断。
相同原则也适用于数学。把一个已经证明的命题作为引理使用,是对其内部过程的暂时隐藏;完整陈述假设和结论,则保留了上层推理所需的关系。若连假设也省略,只留下一个定理名称,隐藏便越过了合适边界。真正有助理解的抽象,不是让人少知道一切,而是让人集中看到当前层级不能缺少的东西。
因此,理解的深度不能只按看到的细节数量衡量。一位研究者阅读大量底层实现,却不知道任务接口如何错配,可能仍未理解失败原因;另一位研究者先建立依赖结构,在关键节点深入检查,反而可能更准确地定位问题。读得多与理解得深可以相伴,也可以分离,区别在于细节是否进入了有意义的组织。
这还使“打开黑箱”得到新的解释。黑箱并不是只有完全封闭与完全透明两种状态。可以有结果层、条件层、证据层、实现层和维护层的不同入口。对不同疑问,打开不同入口才有价值。若用户问的是某段引文是否存在,给他数十亿参数并不能回答;若用户问的是计算误差,给他一段品牌承诺也不能回答。
设计良好的层级入口,还可以减少权威依赖。过去只能凭专家一句“没有问题”接受的内容,现在可能具有可复核对象;过去所有疑问都必须找到原作者,现在可以先定位到具体定义或版本。封装与开放并不必然对立。封装能够使内部劳动变成可调用能力,开放则可以使关键依据和修订路径不被私人权威垄断。
当然,任何接口都会作出选择。它突出一些关系,暂时压低另一些关系,因而可能不适合新的任务。研究者需要拥有修改接口的可能,而不是永远被一套旧抽象限制。帕纳斯讨论的软件模块不等于本书全部认知对象;这里的延伸是把接口可修改性带入思维活动,并要求实际案例检验这种延伸何时有效。
从这个角度说,封装可以成为理解的建筑,而不是理解的敌人。底层劳动获得稳定形式,上层活动能够直接面对新的关系,人不必在每一次调用中同时承担全部层级。理解没有消失,它被重新组织了。关键不在隐藏了多少,而在隐藏之后,重要问题是否更容易提出、证据是否更容易进入、必要修订是否更容易实施。
四 从可调用到可继承:封装还需要时间
一个流程今天可以运行,未必明天仍然可以继承。模型变了,依赖库变了,资料位置失效了,原来默认的定义也可能改变。若封装只是一次成功对话中的操作顺序,离开当时的人与情境便无法恢复,它拥有演示价值,却未必拥有文明继承意义。继承要求关键条件能够被后来者重新接入,而不是只留下结果的截图。
这里需要区分保存物与保存能力。存下一篇报告保存了某个显露,保存输入、方法、依据和修订说明,才可能帮助后来者继续活动。但也不能把所有数据一股脑堆进档案就当作能力保存。后来者无法辨认重要版本、无法知道哪项结论有效,同样难以接续。可继承性依赖有用的组织,而非存储容量本身。
小林的矩阵研究若只留下最终结论,新参与者很难知道她为什么排除某种规则。若留下最小反例、条件修正和证明义务,后来者就不必再次经历同样混淆。这里被继承的不是她的全部心理过程,而是经过整理、能够支持后续判断的关键发生节点。文明继承不需要复制每一个瞬间,却需要保留能够继续起作用的差异。
版本也不是行政编号。一个结论修改后,旧版本可能仍然适用于较窄任务,新版本则开放了另一范围。若更新只覆盖原文件,不说明条件变化,过去研究的依据就可能变得不可追溯。成熟封装应能说明何处保持、何处改变、哪些调用需要重新检查。这种能力使更新成为积累,而不是反复遗忘。
封装成熟还包含人的习惯变化。一个从未见过某工具的人,不会因一份技术证明立即形成实际调用能力;长期使用者也可能因为习惯而忽视新出现的边界。技术上的成立与使用者侧的信任需要连接,但不能彼此替代。训练、反馈和可见的异常处理,是使两者逐步相配的活动条件。
若这套条件由多人共同维持,成本需要被承认。更新资料、修正接口、解释变化和维护验证,都可能没有新论文那样醒目的外观,却直接决定封装是否能够继续服务研究。一个只奖励第一次发布的制度,可能拥有越来越多产品,却缺少可持续继承的能力。封装论由此把维护从附属工作提升为知识发生条件的一部分。
然而,维护也可能变成僵化。某个团队因为投入巨大,不愿承认封装应该缩小、拆分或退出,于是用不断补丁保护旧组织。可继承不等于必须永久保存同一种实现。继承的对象应当是仍然有价值的能力和依据;实现可以替换,任务可以重新定义,过时承诺则应当结束。
因此,可靠封装具有一种双重时间性:它使过去的有效劳动继续起作用,也使未来的修订仍然可能。只有前者,封装会变成纪念碑;只有后者,所有活动都处于无法调用的永远试验之中。成熟的组织让一部分已经成立的内容安定下来,同时让边界处仍然能够发生新的研究。
一个按钮可以隐藏细节,却未必形成能力;一份长说明可以列出限制,却未必建立可靠调用。封装成立于任务、条件、过程、依据和重开关系之间:这些关系获得相对稳定的组织,后续活动才有理由把它们当作出发条件。使用端的简洁,应当由必要支撑的真实存在来保障。当这种组织改变时,颗粒度扩大、层级提升、维度打开和广度增加便需要分别命名,不能用同一个“更强”抹去差异。