王德生、张琼 著 · 第398卷 · 修订版v3.0

← 第十五章 弥补、修复与提升第十七章 试用、检测与可靠性 →

第十六章 封装保存了什么

一、不能把包起来当作已经形成能力

一份十页的证明被压成一句“依据标准结果”,一套复杂操作被藏进一个按钮,一段长期练习形成的动作不再需要逐步默念。它们都可能在外观上减少细节显露,但不能因此被认作同一种成熟封装。细节不再出现,既可能因为已经得到承接,也可能因为被遗忘、被遮蔽或从未完成。

本书讨论的封装,首先是一种能力组织。某些在反复实践中得到支撑的区别、规则和处理方式,被保留为可以在相应任务中整体使用的单位。后来者不必重走全部形成过程,却能够借助它完成某些工作。封装的价值不在于内部看不见,而在于内部相关工作能够在适当条件下继续承担作用。

因此,分析一个封装要先问保存了什么,而不是先问隐藏了多少。保存的是固定答案、可重复的操作,还是能够检查条件并调整的流程?它允许使用者省去哪些判断,又要求保留哪些判断?这些差异决定它能进入什么层级的活动,不能只用一个“智能”或“自动化”的名称代替。

从刀具进入这一问题,我们就不会把封装限定在软件之中。刀的结构可以承接先前实践中的某些取舍,操作规程可以承接另一部分,使用者的熟练方式又保存了不同内容。它们并不具有相同存在方式,却可以在当前任务中共同形成一个可使用的能力单位。

为了给封装判断留下可辨认的边界,可以把三种说明分开。第一种只是物理影响,例如物体受到阻力;第二种说明这种影响怎样进入任务相关的分辨,例如阻力使当前操作被暂停;第三种再追查哪些经过试用和比较的取舍被保留,使这种分辨能够较稳定地被后来者使用。三种说明并不互相排斥,却承担不同的解释义务。若只完成第一种,就还没有充分说明历史判断的封装。

这个区分也防止反向推断过度。我们可以确认某一结构在当前任务中承担了判别作用,而暂时不知道其全部来历;这时应当把当前功能的证据与历史来源的假说分开保存。新发现的制造记录可能改变历史解释,却不必取消已经观察到的当前作用。封装的形成史和作用方式既相连,也各自需要依据,不能因为两者使用同一个概念就让一个方面替另一个方面作证。

二、保存的是选择性的关系,不是全部过去

工具的形成史包含大量已经消失的尝试。一个成品通常不会让后来者直接读出所有失败、争论和偶然条件。本书说历史判断进入工具,并不是说工具完整储存了自己的传记,而是说某些选择结果及其实现关系在当前结构中继续发生作用。

以构造性的量具案例来看,制造者通过比较保留了一段标准长度,使用者可以借助它辨别对象是否落在某个范围。这个结构不必讲述制造过程,便能参与当前判断。但它也不自动保存为什么选择这个范围、范围适用于什么任务、何时需要重新校准。后几项工作可能由记录、规程和其他检测系统承接。

因此,封装通常分布在不止一个载体中。把可见物件当作全部封装,会遗漏说明、维护、训练与检验;反过来,把任何相关社会条件都无限纳入,也会使分析边界失去作用。应该围绕当前能力所依赖的关键关系确定范围,并说明扩大或缩小范围会改变什么判断。

选择性保存也使封装具有历史代价。被淘汰的可能性不再容易看见,某些只在少数任务中重要的条件可能被边缘化。封装为后来者减少工作,同时也规定了默认入口。它既是能力积累的形式,也是需要持续接受价值检查的选择安排。

三、结构性判断不等于心理裁决

对于刀具中的封装判断,最常见的质疑是:没有意识,怎么判断?这个问题提醒我们必须区分不同层次。人的心理裁决可以包含理由意识和自我反思;工具中的结构性承接则可以不具有这些特征,却在复合活动中实现某些对适当与不适当、可行与不可行的区别。

本书并不把后一种作用直接等同于前一种经验。刀没有因为参与切割判断就成为会解释人生的主体,检查程序也不会因为报告通过就自动承担研究者的全部责任。需要比较的是实际功能和连接,而不是用同一个词抹平存在方式的差异。

同时,不能因为差异存在就把工具排除在能力解释之外。一个结构若稳定限制了不合要求的调用,使使用者能够感知关键变化,并进入后续修订,它就可能承接了一部分原先需要反复处理的判断关系。去掉这种结构,任务所要求的注意、技能和检查方式可能重新改变。

为了避免泛化,本书要求三个说明:被承接的区别与什么任务相关,它怎样进入当前反馈,改变相关结构以后会有什么可检验差异。只说一块石头有重量,尚不足以称为判断封装;当它被纳入有条件的测量或比较活动时,才需要继续分析其构成作用。

四、一个可操作的封装说明

为了把概念用于研究,我们可以为一项显式封装建立简洁说明:它服务什么任务,在什么条件下使用,内部承接哪些工作,当前依据是什么,何时需要重新展开。这五个方面并非工具历史中的统一格式,而是本书提出的分析与工程设计工具。

可暂记为C=〈任务、条件、过程、依据、重开规则〉。这个写法不是新的SDE基本方程,也不是完成可靠性证明的形式系统。它的作用是让不同封装可以被具体比较:两个按钮看起来相同,却可能具有不同适用范围;两个证明模块结论相同,却可能使用不同假设和验证依据。

任务说明防止能力名称无限扩张。条件说明防止过去成功被无边界转用。过程说明使我们知道哪些工作真的被承接,哪些仍待外部判断。依据说明区分已测试、已证明、仅被演示或尚未核实。重开规则则使封装能够响应变化,而不是在第一次形成之后永久免检。

这份说明不应全部压给普通使用者。不同层级可以显示不同粒度:使用者先获得任务、边界和异常处理方式,专业复核者能够进一步展开过程与依据。封装的成熟不是让每个人填写更复杂的表,而是让必要信息能在需要的位置被实际取得。

五、界面为什么也是封装的一部分

一个封装能否使用,取决于它怎样与外部任务连接。界面不只是好看的表面,它决定什么可以输入、什么会被拒绝、什么状态被显示,以及使用者能从结果中知道多少。内部能力再强,如果界面误报完成或隐藏必要条件,整体判断仍然可能失真。

设想一个证明模块输出三个结果:已证明、尚未完成和输入不适用。若界面把后两者都显示为空白,使用者便无法区分系统正在工作、任务不成立还是工具不支持。若把任何非错误输出都显示成绿色通过,又会使探索过程被误读为完成。界面的区别正参与了价值显露。

因此,封装不是越少显示越成熟。可以减少不相关实现细节,但必须保留影响当前使用的状态和条件。软件模块化研究早已讨论,把可能变化的设计决定隐藏在明确接口后面,而不是简单按处理步骤切块。[R7] 本书与之相接,却进一步追问:这些接口如何承接价值判断,又如何在使用中形成新的能力。

接口还要保留不确定性而不制造瘫痪。不是把所有未知都作为同等严重的警报,而是区分影响当前任务的缺口、可以在条件下继续的部分,以及需要专业复核的异常。良好的封装让使用者少处理无关细节,同时更容易看见必须处理的差异。

六、封装内部可以继续发生复杂判断

我们容易把封装想象成一个冻结的旧结果。对于某些简单工具,内部结构的确相对稳定;但许多封装保存的不是固定答案,而是一套继续运行的过程。一个排序工具每次处理不同输入,一个检验流程每次检查新的对象,一个证明系统每次面对新的证明项。整体调用并不意味着内部没有新的活动。

这让封装具有两个时间层次。第一层是能力形成史:哪些结构和规则经过试用、比较和修正而获得支撑。第二层是当前执行史:这些结构怎样处理这一次对象的差异。过去可靠性支持调用,当前运行仍需满足当前任务的要求。二者相连,却不能互相替代。

“人的判断+刀的封装判断”也可以这样理解。刀的结构不必每次重新制造,但它在这一块冬瓜上的作用仍要进入当前反馈。既有经验提供起点,对象差异使某些动作继续或调整。被封装的是可以承接的部分,不是把未来每一次结果预先完成。

因此,封装不必意味着人停止学习。某些内部判断由系统持续承担以后,使用者能够学习新的整体关系;出现边界问题时,又可以有目的地展开相关部分。封装与展开不是两种互相排斥的世界,而是在同一实践中按任务变化进行的组织方式。

七、封装与记忆、抽象、委托有什么不同

封装与记忆相接,因为过去经验能够保留并参与后来活动。但记住一个答案,不等于形成能够再次适用的能力。若不知道条件,也没有办法核验新的对象,记忆可能只是一个可复述内容。封装要求研究记忆怎样进入条件、动作和反馈,成为可使用关系。

封装与抽象相接,因为多个内部差异可以在某一层被作为一个单位处理。但抽象本身不保证相关工作已完成。我们可以抽象地谈“证明引擎”,却没有任何可靠引擎;也可以把一套未解决的问题命名为模块,让图纸显得完整。封装的成立需要具体承接,而不只是概念上把边界画出来。

封装与委托相接,因为使用者可以不亲自处理全部细节。但委托只是任务分配的一种安排,受托者是否具备能力、证据怎样返回、条件怎样保存,都还需要检验。把难题交给另一个人或AI,不会自动生成一个成熟封装;重复委托也不能代替对实际结果的判断。

这些区分使封装概念避免吞并一切。它不是记忆、抽象和分工的替代名称,而是关注它们何时形成一种经过支撑的整体使用能力。若一个案例无法指出这种新增关系,使用既有概念已经足够,就不必强行称为封装发生。

八、封装不是隐藏,而是附带重开权的承接

上一节把封装与记忆、抽象、委托分开。这里再把它与“隐藏”分开,因为这是最容易发生的混同。封装不是隐藏,而是附带重开权的承接。

本书意义上的封装要写明四项:调用条件;重开条件,包括触发重开的信号和重开到哪一层;拆封权,即由谁打开;回写去向。判据由此而来。一项被折叠起来的能力,若只规定了何时可以调用,没有规定何时必须重新打开,它是黑箱;若只保存了内部内容,没有规定在什么任务里可以整体调用,它是档案;调用条件与重开条件都有,并写明拆封权与回写去向,才是本书意义上的封装。第四节的C=〈任务、条件、过程、依据、重开规则〉中,任务与条件对应调用条件,重开规则对应重开条件;这里补上的是“谁”与“回到哪里”:重开不能只是一条规则,还要落到某个有权、也有能力打开它的人或机制上,并规定打开以后回写到哪里。

日常案例一:药盒里的说明书。一盒常用药,说明书写着适应症和用法用量,这是调用条件;还写着“服用三日症状未缓解,或出现皮疹、呼吸困难,应停药并就医”,这是重开条件——在这些信号下,“按说明书吃药”这个封装必须打开,交给医生重新判断;它还指明了谁来打开:不是病人自己加量,而是医生。一盒只印着“每日三次,每次两片”、没有任何停药与就医提示的药,是黑箱;一本只讲药理机制、不说何时适用的药理书,是档案。说明书兼有两者并指明拆封的人,普通人才能安全地整体调用一种自己并不了解内部的能力。

日常案例二:住宅的物业维修规约。绝大多数住户不知道墙里的管线怎么走,房子对住户是封装的。规约写明住户可以自己做什么,例如换灯泡、刷墙,这是调用条件;写明出现漏水、墙体开裂、电闸频繁跳闸时必须报修,这是重开条件;写明承重墙和燃气管道只能由物业或有资质的人打开,这是拆封权;维修以后更新图纸和维修记录,这是回写。少了其中任何一项,这套房子就会在某个地方变成黑箱或档案。

重开条件、拆封权、回写去向这三项,缺了任何一项,失败的样子各不相同。没有重开信号,异常出现时没有人知道该停:病人吃了一周药还在吃,住户看着墙上的水渍继续住。没有拆封人,信号出现了却没有人接:家长群里人人都觉得该有人去问学校,结果谁也没问;或者人人都去拆,住户自己凿开墙找漏点,把封装拆坏了。没有回写,打开过的封装合上以后和原来一样:修好的管道没有进图纸,下一位维修工又要从头找。这三种失败可以分别记录,修复也不同——补信号、指定人、建立回写记录,各是一件事。

重开权还意味着拆封的人需要有能力打开。一份规约写着“燃气管道由有资质的人员处理”,小区却找不到这样的人,拆封权就只在纸上。把这一点放回 AI 工具:一个模型接口若写明“结果存疑时交人工复核”,就要同时说明哪一类人员、在多长时间内、凭哪些材料复核;否则“交人工”只是把黑箱换了一个名字。拆封权也不必永远在同一个人手里。家里的电闸跳了,第一次可以由住户自己合上,这是第一层重开;同一天跳第三次,就要交给电工,这是第二层。分层的拆封权,让大多数小异常就近处理,少数大异常交给能处理的人,使用者不必每次都把整个封装交出去。

调用条件也不能省。一本只告诉你“出现什么情况必须就医”、却不告诉你平时怎么吃的药品说明书,使用者每次都得去问医生,这项能力实际上没有被交到他手里。这就是档案的样子:内容都在,却不能在任务中整体调用。

与 Parnas 信息隐藏的切口。Parnas 主张按可能变化的设计决定划分模块,把这些决定隐藏在明确接口之后,使用者不必知道内部。[R7] 本章第五节与之几乎相同。切口在于:信息隐藏规定的是使用者不必知道什么;本书还要求规定在什么信号下必须重新打开、打开到哪一层、由谁打开、打开后回写到哪里。判断不同的那一刻是这样的:一个接口稳定的软件模块,使用者从不需要看内部,按信息隐藏的标准它是合格的;某一天它开始偶发异常输出,而系统中没有任何规定说明什么样的异常要触发审查、谁有权读源码并修改、修改后要通知哪些调用者——按本书的标准,它此刻是一个黑箱。两种判断在平时一致,在异常出现时分开。若某个领域的信息隐藏实践已经普遍包含了重开信号、拆封权和回写规定,例如成熟软件工程中的缺陷报告、代码负责人与变更通知制度,那么本书在该领域没有增量,只是给已有制度起了一个名字。

本书写作本身也可以按这一判据检查。书中引用的每一项文献,对读者来说是一个封装:读者不必读原书,就可以把“某某已经讨论过外部媒介的构成作用”整体调用。这个封装的调用条件,是引文准确对应原书说过的内容;重开条件,是读者发现引文与原文不符,或本书据它推得太远;拆封人是任何能查到原书的读者;回写则是勘误与修订。若一条引文不能指向读者可以核对的位置,也没有勘误渠道,读者就只能整体接受或整体怀疑,它就从封装退回了黑箱。

可裁决预测:比较两类封装——只有调用条件的,与同时写明重开条件、拆封权和回写去向的。若在出现边界情况时,后者的异常被发现的时间、被交给合适处理者的比例、修复后同类问题的复发率都没有可辨认的改善,那么重开权不是封装成立的必要部分,本书应当退回 Parnas 原有的表述。

九、封装中的价值选择如何继续存在

一把工具、一条规则或者一个模型接口,通常已经决定了某些差异优先显露、某些操作容易完成、某些结果被归为成功。使用者不每次重新判断这些选择,并不意味着选择已经变成价值中立。它们可以通过结构继续影响当前活动。

因此,封装评价不能只问运行是否稳定。一个系统可能稳定保存了不合适的比较对象,也可能持续排除某些有效反例,或者让使用者只能接受一条固定路线。三方程、六路径和三原理需要进入封装本身,评估它所保存的关系是否支持真、善、美的共同发生。

价值发生学进一步追问这些选择怎样形成。它们可能来自合理的资源限制,也可能来自旧任务已经不适用的条件。发现历史原因并不自动否定封装,但使我们能够区分哪些部分可以保留,哪些需要重新检验。批评封装不必等于拒绝工具,往往意味着让工具的能力更适合当前任务。

这也说明,成熟封装应当允许在适当层级质疑其标准。并非每个使用者都要随时修改内部规则,但至少需要存在能够报告不合适之处、进入复核并获得说明的路径。否则,历史判断会以不可见的形式支配当下,而当下差异却不能返回历史承接。

十、封装为什么能够形成新的判断粒度

当一段复杂过程能够作为整体使用,研究者可以在不同时展开全部细节的情况下,把它与其他整体联系起来。一个已验证引理成为证明结构中的单位,一套成熟编辑流程成为专著制作中的单位,一次可预期的交通行程成为生活安排中的单位。这种粒度不是内部简单了,而是内部相关工作可以被暂时承接。

新的粒度也会改变问题。原来需要问“每一步是否成立”,现在可以问“哪些模块可以组合”;原来只能处理一个局部对象,现在可以比较多个结构的差异。新问题并不由节省时间自动出现,它需要使用者进入新的互动,但封装为这种进入提供了条件。

这里的整体不能脱离其边界独立存在。某一模块对于调用者是整体,对于修改者仍是需要展开的过程;对一个任务足够粗粒度的描述,对另一个任务可能过粗。判断粒度始终相对于当前问题,不能把某一种封装永久指定为世界的最后单位。

于是,下一层的多成为上一层的一,并不意味着多被消灭。它们被保存在能够重新展开的承接中。新的“一”又进入新的“多”,组成另一轮问题。封装的文明意义可以从这里研究:历史能力不仅被保存,还能够支持原先未形成的组织方式。

十一、不可见、不可理解与不可追溯不是同一回事

普通使用者不看见内部细节,是封装常见的使用状态;他不理解全部内部原理,也可能不妨碍适当使用。但若没有任何可行途径追溯关键依据、发现错误和实施修订,问题就不同了。不能把前两种合理省略,当作第三种失去检查的理由。

追溯也不必意味着公开所有内容给所有人。复杂系统可能需要不同角色承担不同检查,涉及隐私或保密的材料也要适当处理。本书在此提出的是能力要求:必要的判断应当能够被合适的机制完成,并让使用者获得与其任务相关的状态和边界。具体权限安排需要另行设计,不能由封装概念自动推出。

一个人遇到异常后能够调用专业复核,而不必独自重建全部技术,仍然可以保有有意义的判断参与。相反,界面提供了大量内部日志,但无人能够理解和处理,也不等于系统透明。可追溯性是一种实际工作能力,不是信息数量的堆积。

因此,封装成熟不能用“可见细节越来越少”单独衡量。更重要的是,哪些细节不必看,哪些差异必须显露,需要时谁能展开,以及展开以后能否改变相关运行。这四个问题把使用便利与判断保障连接起来,而不是要求二者永远相互牺牲。

十二、封装需要一部形成史,也需要继续发生

本章给封装安排的不是一种神秘实体地位,而是一组可以研究的关系:历史取舍怎样选择性保留,当前任务怎样调用,必要判断怎样承接,新差异怎样触发改变。这个定义同时拒绝两个极端:把工具当作毫无判断内容的执行物,以及把工具当作永远正确的独立裁判。

封装也不是创造的反面。没有可以稳定使用的能力,新的活动往往被迫不断从零开始;只有稳定而不能重新展开,历史能力又可能成为创新的限制。需要研究的是二者怎样转换,而不是在坚持一切手工与信任全部自动化之间作一次永久选择。

把细节折叠起来,并不能独自证明封装已经成立。值得整体调用的,是内部工作得到实际承接、外部条件没有被偷减、必要时仍能重新展开的能力。这样的能力既保存过去,也接受当下检验。它何以获得支撑,不能由一份说明或一次顺利演示回答;必须继续考察试用中的差异、检测的覆盖和失败之后真正发生的修改。

← 第十五章 弥补、修复与提升第十七章 试用、检测与可靠性 →