级列设计理论

来源:百度文库 编辑:神马文学网 时间:2024/04/28 09:29:50
    级列理论是分析学中常见的一个思维框架,我只是把它从我最熟悉的物理学中借用到软件设计领域而已, 它本身并不是我所创造的一种概念(创造是艰难的)。在某些领域,这一分析框架可以表现出完美的数学特性,如时频分析领域的小波分析(wavelet), 统计学习理论中的支持向量机(Support Vector Machine), 分子动力学中的BBGKY级列等等。在其他一些领域它的精确性可能要弱很多,但其思想内核是一致的. 
    
    级列理论的基本内容如下:   理论物理的优美在于从少量基本原理(如最小作用量原理)出发推导出整个理论大厦。而在软件设计领域却充斥着林林总总的"最佳实践". 太多的规则只会意味着没有规则。软件设计领域的现状说明这个领域还处于非常稚嫩的阶段,应该从其他领域借鉴更多的知识。在我前面的blog中已经说明了在软件中的一些具体的分析技术。但如何有效的应用这些分析技术,我们还需要一些指导性的理论框架。如果把软件设计放在更加广泛的系统工程的背景下,一个合适的支配性原理应该是最小复杂性原理。即在软件分析过程中我们所作的一切,无论是面向对象分析,基于工作流的分析等等,其目的都是尽量降低系统构建的复杂性。只要能够有效降低系统构建的复杂性,那所采用的方法和所建立的模型就是好的。复杂性是唯一的度量,而不是是否符合某人的观点,是否采用流行的技术等(当然,采用流行技术往往意味着降低了和其它系统交互的复杂性)。
     李小龙说:简单是美。但是否最简单的就是最好的?科学界对此却有着否定的结论。关于复杂性的一个很深刻的基本事实是,复杂性是分级的,不同复杂性层次的事物有着本质的差异,不能期待一个较低复杂性的方法能够解决一个更高复杂性层次上的问题。所以Einstein说:make everything as simple as possible, but not simpler。复杂性级列的存在意味着,随着我们获取到更多的信息量或者因为系统自身的发展,当我们所建立的系统的模型沿着复杂性级列演化的时候,我们所提出的解决问题的方案也必须作相应的演化。即我们提供的不是一些固定的解决方案(solution),  而必须是一个完整的策略(strategy)。这样我们就不是孤立的看待一个问题, 而是要看到它的过去,现在和未来。
     在作分析的时候,我们都知道"从一般到特殊,从特殊到一般",但如何科学的,有步骤的去做呢? 我从等离子体物理的BBGKY Hierarchy中学到了一个基本的分析框架: 级列理论.这个理论首先定义了一个最普适的模型:气体由N个完全相同的原子组成, 其动力学由N个互相耦合的Newton力学方程来描述。理论的第二步是从最极端的简化开始,假设所有的原子之间不存在相互作用,即假定原子之间是相互独立的。则得到Vlasov方程。理论的第三步考虑系统的复杂性逐渐增加,当气体密度较高,必须考虑分子之间两两碰撞的时候,得到Boltzman方程。当需要考虑更高阶的相互作用的时候,我们得到关联动理学方程,如此继续下去建立一个无穷级列。
抽象一些地说,该理论包含如下内容:
. 建立能够描述所有情况的最广泛的模型M0, 该模型定义系统的边界
. 建立一个包含最少假设的最简单的模型Mn,该模型作为求解的基础和基本的参照。
. 建立一个从Mn到M0的复杂性逐渐增加的模型级列,确保在每一个复杂性的层次上,都存在着对系统有效的建模,而且在求解高阶问题的时候,可以参考较低阶问题的解。
   如何从这种无穷级列中做出选择,必须根据具体应用情景而定,Vapnik在其统计学习理论中详细描述了这种求解策略:
 综合代价 = 训练数据与模型预测之间的偏差 + 模型自身的复杂性
    学习 = minimize[综合代价]
即在能够解决问题的方案中选择最简单的一个。
建立级列(Hierarchical)理论,首先需要建立最广泛的模型。在量子力学中,确立了如下基本概念:
 1. 确定性的态。
 2. 所有态构成完备的态空间。
 3. 系综(即态的集合)的动力学。
   首先,状态的确定性非常重要。即使在量子力学中,量子态存在几率诠释,态函数本身在数学上仍然是确定性的,即在任一时刻,任一地点存在唯一的值。如果我们的讨论没有一个确定性的基础,那所有的推演都将变得极为困难(模糊数学目前提供的帮助很少)。而且确定状态本身就是一个极为重要的简化过程。因为一般我们可以建立Markov模型,使得系统的演化只与系统当前的状态有关,而与系统的历史状态无关,因此大大减少系统模型的参数。
   其次,状态演化的结果必须仍然处在态空间中,否则我们在该空间中建立的理论就存在着"盲点",存在着失效的可能。
   第三,我们研究的不是单个状态的演化,而是综合考虑相邻的状态。
   在软件世界,理论物理的这些真知灼见依然有效,只是在所有的概念前加上了"有限"这个修饰语。有限状态机(Finite State Machine)正是理论计算机科学研究的基本模型。所有的计算机都可以看作是有限状态的,因为所有的内存和硬盘能够表示的状态数是有限的。目前计算机科学中几乎所有重要的理论成果都和有限自动机理论相关。在软件编制的过程中,我们第一步所要做的也是确定系统的状态。与物理系统所不同的是,我们认为物理系统的状态及其演化规律是客观存在的,而软件系统中的规则是由开发者确立的,我们必须尽一切可能使得系统的状态能够被确定下来。例如,我们编制getXX()和toString()等函数来暴露系统的状态,以确保系统状态的可观测性;使用assert断言来确保函数执行时的状态;尽量减少函数的副作用来避免依赖函数调用历史。软件世界中态空间不完备的例子最著名的就是Y2K问题。所以很多人说,软件中最大的bug就是地址空间不足,因为这是任何技术手段都无法解决的问题。
    首先, 级列理论需要定义一个最一般的普遍模型, 但这并不意味着对系统的一种过分的限制. 实际上, 我们所讨论的任何问题都有一个总体的框架限制,  它的作用只在于揭示出我们所研究的问题的基本要素并勾勒出一幅全景式的图像. 最一般的情况与我们的求解能力的距离可以是非常遥远的,例如真正实作的时候在物理中往往我们只是研究一阶或者二阶情况。而在计算机领域也是存在着最一般的 模型的, 那就是Turing Machine. 在一般情况下, 我们是能够建立一个足够普遍的模型以囊括绝大多数变化可能的, 虽然我们极有可能没有能力去求解这个模型. 
    对于系统的完备性, 物理学与数学的态度是有着深刻区别的. 在物理学中我们只需要在研究问题的范畴内维持概念的稳定性即可, 这往往意味很多简化与隐含条件,并不是一种终极的完备性. 而在另一方面, 数学的完备性并不能保证它描述现实世界的完备性. 最明显的, 从经典力学到狭义相对论, 再到广义相对论, 在每一个层次上都是存在着非常完美的数学描述的, 其数学空间都是完备的, 但是很显然, 即使是广义相对论, 它也不是对于物理世界的完备描述. 目前物理学界仍然在量子引力的黑暗中摸索. 所有这一切都不影响我们在建筑工程中以足够高的精度应用力学原理.

    级列理论所描述的绝不是一种从一般到特殊的思想的应用, 而是同时包含着从一般到特殊和从特殊到一般两个方向. 在级列理论中, 我们首先研究的一般是最特殊的情况, 即最简单, 对称性最高的情况. 此时模型中特征元素个数很少, 而且界限分明, 很少交互或者发生关联. 我们得到简单模型的解之后, 就可以将其作为初始解去求解更高阶的模型. 这是从特殊到一般的一种进展. 而在另一方面, 我们可能以创造性的方式得到某个更高阶模型的解, 此时我们需要研究高阶模型与较低阶模型之间的关联, 考察当更高阶的模型退化到低阶模型的时候, 它们的解是如何自然的实现退化的.  虽然迭代这个名词在当前软件工程领域如日中天, 但我想很多开发人员却从未花上一刻时间去真正的体味这个概念本身的内涵, 而陷入了人云亦云的窘境. 从数学上说, 迭代过程的基本问题是收敛问题, 而且往往收敛过程中的控制策略要远比迭代初始值的选择更重要. 那么什么样的控制策略才是保持探索性但又倾向于收敛的呢? 连续性是最基本的要求. 
---------------------------------------------------------------------参见 反问题的级列求解
    实际观测到的结果是系统内在结构的外在表现,而软件开发是从需求分析开始,经历系统分析,设计并实现的过程,即从用户需求逆推出软件的结构。这种根据外在 表现求解内部结构的模型的过程,在数学上称为反问题(inverse problem)。关于反问题,一个众所周知的难点在于解的不适定性。因为不同的结构可以有类似的外在表现,因而反问题的解是不稳定的。在一个既定的情况 下,我们按照某种粗略的外在度量标准,从反问题的众多近似解中选择了一个。但是当所需的外在表现发生微小变化后,我们第一次选择出来的结构可能无法适应这 一微扰,而我们再次求解出来的结构可能与原先的结构有着巨大的差别。因而原先选择的解在结构上是不稳定的。在数学上,我们称之为奇异解(singular solution)。在数学上,在求解反问题的时候为了避免选择到奇异解,经常采用的技术手段就是类似于级列理论的所谓镇定方法。即我们提出一系列的模 型,对它们进行一维参数化。当参数较大时相当于对原有模型的一种近似,原有模型的细节被淹没在正定泛函的大范围结构中,整体呈现出一种简单的结构,而当参 数越来越小时,原有模型的细节被逐渐识别出来,整体模型逐渐复杂化,最终参数为0时恢复到原始情况。常见的模拟退火算法(simulated annealing)就属于这一策略族。通过模型的连续性,我们建立了一个复杂模型与一个简单模型(因而物理意义明确)之间的一条连续的纽带,沿着这条可 退化的途径,我们才有可能回避奇异解,保证复杂模型的物理有效性。
    在软件设计中,我所提出的级列设计思想正是这样一种渐进演化的设计思想。我们极力维护模型的可退化性,保证复杂的模型不至于锁定在错误的角落中。而基于模型的连续性,我们对于未来的发展进行外推才有了一定的根据。---------------------------------------------------------------------
    级列理论最关键的部分其实是两个存在性: 一是复杂性级列的客观存在, 二是级列之间连续性的客观存在. 注意到级列理论所描述的只是存在性,在一般情况下, 我们并不能直接得到从低阶解推导出高阶解的构造方法。而复杂性的级列的存在意味着总存在超越我们当前认知范围的信息, 从低复杂性层次上升到高复杂性层次可能是需要非凡的创造力的, 决不是显然的。此时我们唯一的选择只能是从后验的角度去检验这种存在性。模型的可退化性正是连续性的一种自然推论。这在物理学中是一件不言而喻的事情也是 一种强制性的要求:狭义相对论可以在低速情况下退化为Newton力学,而广义相对论可以在引力均匀的情况下退化为狭义相对论。在软件领域, 似乎只是到了近几年, 可退化性才得到了一些重视,至今很多人对它的思想实质仍然没有充分的了解。退化是否是指系统中不同职责部分的合并但是这些职责依然存在? NO, NO, NO. 精简机构的原因难道是为了裁减人手,增大人均工作量吗? 精简的原因首先在于人浮于事, 本身就没有那么多的职责, 却要生造出那么多的处理步骤来. 我们或者合并部门,或者干脆撤销部门,一些专门因为内部协调而生的部分更是要被毫不留情的裁减掉。在常见的软件开发中, 明明是非常简单的数据库访问操作, 偏偏要在service层, data object层, dao层都把同样的接口代码重复一遍, 美其名曰多层体系架构, 可以保持系统的灵活性. 可是谁需要这种灵活性, 它到底是设计的灵活性还是设计的脆弱性? 在简单的情况下, 选择meta driven的方案,从描述文件直接驱动多个层次的运作往往能够极大的提高系统的稳定性和灵活性.

    假设现在有一个网络应用, 我们首先考虑最简单的情况, 例如我们假设只存在一种通信协议:打电话. 我们可以通过电话通知另一方的接线员, 让他把信息记录下来再录入系统当中,以此维持系统的运转. 如果永远都只有一个固定的接线员X通过唯一的一部电话M来完成通信过程, 则系统中的多个概念就会发生简并: 通信将等价于打电话,等价于打电话给X, 等价于使用电话机M打电话给接线员X. 随着系统的复杂性逐渐增大, 系统的对称性出现破缺, 原本被认为同一的概念出现了微妙的不同, 并可能演变成差异巨大的两个分支. 假设现在多了另外一种通信协议:硬盘交换. 我们可以把数据拷贝到一块硬盘上, 然后携带到远处的机房, 在那里把数据导入系统, 以维持系统的运转. 如果我们的系统演化到了这个阶段是否意味着我们原先的软件模型已经彻底崩溃了? 并不是如此的, 在一个宏观的粒度上, 我们的系统所需要的可能只是一种端到端的通信手段, 只是现在通信这一更高层的抽象概念不再等同于更加细节化的具体通信手段(打电话)了. 如果原先系统设计中的各个主要模块之间只存在高层抽象之间的依赖, 则只需要增加一些数据导入导出模块, 我们的系统就可以平滑(连续)的接纳一种新的通信协议. 一种宏观的高层视图如果直接映射到某种实现, 则它所对应的就是一种最简单的系统模型. 系统的不断发展相当于是给这个最简单的模型不断补充细节, 使它不断的复杂化. 这种变化是有脉络可寻的, 很多时候是局部的, 轻微的. 当然, 持续累积下去, 也许有一天我们会突然发现系统已经面目全非了, 甚至原先的高层视图(简单模型)也无法维持了. 但是即使这样, 是否意味着我们原先的设计失败了呢? 答案仍然是否定的. 软件系统如同其他系统一样, 处在不断的演化状态当中, 但是什么叫做系统的演化? 很多人有一种错觉, 以为软件结构完全不变, 完全不需要源代码级别的修改, 只需要通过外部配置导入扩展对象的设计才是好设计, 才是成功的可扩展设计. 这是以一种静态的僵化态度来看待程序的演化, 没有理解演化的实质.  演化(evolution)首先是一种变化(variation). 按照级列设计理论, 当系统沿着复杂性的级列发生演化的时候, 因为不同复杂性层次之间存在着本质性差异, 我们不能奢望现在的简单设计能够一直包容越来越复杂的模型, 更加现实的态度是能否在未来的复杂的模型中为现在的简单设计找到位置. 我们不预言未来, 也无法保证我们现在的行为能够容纳将来的选择. 在适度重构的意义下实现部分重用已经是我们能够做到的最好程度了. 我们需要理解世界本身是在变迁的, 即使现在我们能够预测到未来, 现在就为其作准备也未必是适当的, 因为现在的最优不等价于将来的最优, 同样将来的最优也不等价于现在的最优.     在上文中的网络应用的例子中, 也许系统最终发展成为一个非常庞大的系统, 而我们最初设计的功能成为了该系统的一个子模块, 这不是完美的可扩展性吗?   http://canonical.blogdriver.com/canonical/1002861.html 


    级列理论的思想是非常通俗的, 并没有丝毫神秘的地方. 复杂性的级列可以在空间中呈现出一种复杂性递增的形态,也可以沿着时间轴展开,构成发展的形态。在传统设计理论中也在频繁的处理着这些问题, 因而可以看到很多相近的思想, 但是我们也需要注意到一些细节性的不同.  传统的设计中也讲层次,但是多半说的是stratify而不是hierachical,是同一时刻可以看到的一种层次堆垒关系,而不是在不同复杂性层次上 才揭示出的级列关系. 传统设计中也讲高级抽象与低级抽象之间的关系,但没有提供级列理论中完整的视图, 也很少强调每个层次上元素之间的连续性。

    关于级列设计理论在软件设计中的适用性, 我只想提一下witrix平台中的jsplet开发框架,  参见 
       从级列理论看MVC架构 http://canonical.blogdriver.com/canonical/579747.html
       jsplet:对Model 2模式的批判 http://canonical.blogdriver.com/canonical/591479.html
    在2002年左右, 我是先得到级列设计理论, 然后才根据其思想设计的jsplet框架. 在整个witrix平台的设计中, 级列设计理论也是重要的指导思想. 不过, 以我的经验来看, 一般人是很难理解他人的思想的, 即使是对别人的想法有些兴趣, 实际思考的东西与作者的原意往往也有着很大的差异.  http://canonical.blogdriver.com/canonical/1014773.html
    
    最后我还是强调一下一件最最基本的事情, 一件每个人都应该时刻牢记的事情: 不要孤立的看待问题, 而是寻求一种概念之间的连续性.  http://canonical.blogdriver.com/canonical/1016684.html