posts - 157, comments - 216, trackbacks - 0, articles - 6

2005年12月27日

    级列设计理论中我们谈到一般和特殊的关系, 但这是否指的是“相对抽象” 以及 “相对具体”之间的关系, 而“一般”到“特殊”和“特殊”到“一般”这两个方向是否指的是具化过程和抽象泛化过程? 我猜测有这种想法的人大概是受到软件设计中所谓抽象封装思想的影响. 很显然, 我并不是这样认为的. 一般性(普遍性)与抽象性是不同的概念. 在物理学中相对论是比Newton力学更加一般性的理论,但它和Newton力学一样都是关于我们这个世界的真实的理论,都是非常具体的。虽然我们有的时 候会说相对论更加抽象一些,这不过是暗示这个理论所描述的情形与我们的日常经验距离遥远而已,并不意味着它是某种只存在于概念空间的东西。实际上我很少谈 到抽象与泛化过程,这对于物理学而言并不是一个合适的命题.

    有些人认为"service层, data object层,  dao层只是对程序职责的描述并不是实现,在实现中应该根据实际情况进行合并与取舍"。在我看来, 持有这种看法的人已经把自己的思想限定在了某一个复杂性层次上, 认为这些职责是天然的,必然的存在于程序中的. 但实际上, 我们肯定可以想见更加复杂的情形, 仅仅三层并不足以充分表达程序的结构, 而另一方面, 在极端简单的情形下, 例如只有一个数据库,只有CRUD操作, 此时根本就不存在这种职责. 一种所谓的职责从来就不曾存在过,我们自然也不应先把东西搞复杂起来,再合并取舍回去。

posted @ 2005-12-27 22:21 canonical 阅读(723) | 评论 (3)编辑 收藏

    级列理论是分析学中常见的一个思维框架,我只是把它从我最熟悉的物理学中借用到软件设计领域而已, 它本身并不是我所创造的一种概念(创造是艰难的)。在某些领域,这一分析框架可以表现出完美的数学特性,如时频分析领域的小波分析(wavelet), 统计学习理论中的支持向量机(Support Vector Machine), 分子动力学中的BBGKY级列等等。在其他一些领域它的精确性可能要弱很多,但其思想内核是一致的.
    
    级列理论的基本内容如下:
    http://canonical.blogdriver.com/canonical/562888.html

    首先, 级列理论需要定义一个最一般的普遍模型, 但这并不意味着对系统的一种过分的限制. 实际上, 我们所讨论的任何问题都有一个总体的框架限制,  它的作用只在于揭示出我们所研究的问题的基本要素并勾勒出一幅全景式的图像. 最一般的情况与我们的求解能力的距离可以是非常遥远的,例如真正实作的时候在物理中往往我们只是研究一阶或者二阶情况。而在计算机领域也是存在着最一般的 模型的, 那就是Turing Machine. 在一般情况下, 我们是能够建立一个足够普遍的模型以囊括绝大多数变化可能的, 虽然我们极有可能没有能力去求解这个模型.
    对于系统的完备性, 物理学与数学的态度是有着深刻区别的. 在物理学中我们只需要在研究问题的范畴内维持概念的稳定性即可, 这往往意味很多简化与隐含条件,并不是一种终极的完备性. 而在另一方面, 数学的完备性并不能保证它描述现实世界的完备性. 最明显的, 从经典力学到狭义相对论, 再到广义相对论, 在每一个层次上都是存在着非常完美的数学描述的, 其数学空间都是完备的, 但是很显然, 即使是广义相对论, 它也不是对于物理世界的完备描述. 目前物理学界仍然在量子引力的黑暗中摸索. 所有这一切都不影响我们在建筑工程中以足够高的精度应用力学原理.

    级列理论所描述的绝不是一种从一般到特殊的思想的应用, 而是同时包含着从一般到特殊和从特殊到一般两个方向. 在级列理论中, 我们首先研究的一般是最特殊的情况, 即最简单, 对称性最高的情况. 此时模型中特征元素个数很少, 而且界限分明, 很少交互或者发生关联. 我们得到简单模型的解之后, 就可以将其作为初始解去求解更高阶的模型. 这是从特殊到一般的一种进展. 而在另一方面, 我们可能以创造性的方式得到某个更高阶模型的解, 此时我们需要研究高阶模型与较低阶模型之间的关联, 考察当更高阶的模型退化到低阶模型的时候, 它们的解是如何自然的实现退化的.  虽然迭代这个名词在当前软件工程领域如日中天, 但我想很多开发人员却从未花上一刻时间去真正的体味这个概念本身的内涵, 而陷入了人云亦云的窘境. 从数学上说, 迭代过程的基本问题是收敛问题, 而且往往收敛过程中的控制策略要远比迭代初始值的选择更重要. 那么什么样的控制策略才是保持探索性但又倾向于收敛的呢? 连续性是最基本的要求. 参见 反问题的级列求解 http://canonical.blogdriver.com/canonical/974280.html.

    级列理论最关键的部分其实是两个存在性: 一是复杂性级列的客观存在, 二是级列之间连续性的客观存在. 注意到级列理论所描述的只是存在性,在一般情况下, 我们并不能直接得到从低阶解推导出高阶解的构造方法。而复杂性的级列的存在意味着总存在超越我们当前认知范围的信息, 从低复杂性层次上升到高复杂性层次可能是需要非凡的创造力的, 决不是显然的。此时我们唯一的选择只能是从后验的角度去检验这种存在性。模型的可退化性正是连续性的一种自然推论。这在物理学中是一件不言而喻的事情也是 一种强制性的要求:狭义相对论可以在低速情况下退化为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

posted @ 2005-12-27 01:27 canonical 阅读(835) | 评论 (1)编辑 收藏

    近代数学和物理学的发端是从微积分的发现开始的,人类第一次系统化的将连续性的思想推向了极限,也开创了崭新的思维方式。记得高中自学微积分的时候我也花 了很多时间去思考连续性的问题,但是后来渐渐习以为常了。研究生的时候重新开始考虑连续性的问题,只是关注的方向是概念体系中的连续性。
    all or nothing是我们的思维中经常出现的一个误区。很多时候我们的讨论局域在一个封闭的既定的体系中,最后的结论也是在原地转圈圈。就像是“人性本善”与 "人性本恶"的争论一样,数千年无所结论。也许我们真正的问题应该是猪有善恶吗,猩猩有善恶吗,何谓小善,何谓大恶?
    有些时候,某些简单的概念被其复杂的外表所遮蔽。例如提起网格(grid), 很多人的第一印象大概是高深,是一个宏大的体系架构。但是我说如果现在只允许你写下1000行代码,你打算为网格写些什么。我们在网格出现之前所作的工作 与网格之间有什么关系,将所有的概念逐个从网格这个体系中剥离出去之后,最后会剩下些什么。
    我们需要对概念有一个连续性的理解,而不是将它们作为一个不可破的黑箱来看待。这是分析学的基本态度。

posted @ 2005-12-27 01:25 canonical 阅读(666) | 评论 (0)编辑 收藏

    敏捷思想的流行使得很多人对可扩展设计产生了一种怀疑的态度。这有几方面的原因,一方面是J2EE平台本身提供的分布式机制等技术因素很容易诱导你定义不 必要的扩展需求,第二是基于目前的技术手段对于程序结构的分解仍然有着很大限制,具体的程序实现中往往会引入某种强制依赖,削弱了潜在的可扩展性,第三则 是设计者本身对于技术和业务的把握不够深入,在考虑设计的可扩展性时经常做出错误的判断。但是一个只满足当前需求的系统一般不是个好系统,也很难在多次迭 代生命周期后继续生存。XP(extreme programming)强调简单化,其实质在于简单的东西可以在未来被重构(refactor),从而适应未知的变化,它本身并不排斥可扩展设计。
    从基本的常识出发,我们都知道现在应该为将来做些事情,准备些资本。可扩展设计的价值观不应是现在解决将来的问题,而是寻求未来发展之后现在的解是否仍然 部分有效,是否仍然可以部分被继承。即我们考虑的不是将未来的解纳入到现在的体系中,而是考虑现在的解在未来的体系中的位置。不是在现在如何支持我们所预 想到的几种未来的扩展方式,而是无论未来如何变化,怎样才能保证现在工作的有效性。这里所关注的重点是现在而不是将来!面对演化我们所能采取的最好的策略 就是尽量有所积累,尽量不放弃我们的过去,而不是把宝押在对未来的准确预测上。一个厚重的设计往往在后期会因为预料的太多反而在遭遇未预料到的变化时不知 所措,结果造成系统整体架构的失效,必须做更多的工作打补丁来使得它勉强工作。象EJB这样distribution ready的技术现在已经公认有过度设计之嫌,因为这些已经ready的特性一般并不会被应用但是我们却不得不为这些无用的特性付出代价。
    
    可扩展设计所依赖的基本原则之一是IoC(Inversion of Control)。IoC是目前轻量级容器(lightweight container)的核心设计思想,但其实它的应用远不止在轻量级容器这一领域。基于IoC设计,大量的知识(依赖)被剥离出业务对象本身,对象对于其 生存环境和应用场景的假设大大减弱,而我们的期望正在于无论未来的应用环境如何变化,只要提供必要的知识,业务对象就能工作。可以说,IoC是可扩展性的 一种基本要求。
   
    可扩展设计所依赖的另一个原则是连续性(continuous), 这可比IoC要复杂和深刻的多了。如果说现代设计的核心观念是演化(evolution), 那么在我们的思想中演化到底有着什么样的图景? 至少需要一个方向加上一条连续的途径,evolution才能发生。在级列设计中,一个简单的系统架构需要能够scale up,而一个复杂层次上的系统架构也需要能够以优雅的方式scale down。这种变化是自然的因为它们是连续的。

posted @ 2005-12-27 01:24 canonical 阅读(767) | 评论 (2)编辑 收藏

    实际观测到的结果是系统内在结构的外在表现,而软件开发是从需求分析开始,经历系统分析,设计并实现的过程,即从用户需求逆推出软件的结构。这种根据外在 表现求解内部结构的模型的过程,在数学上称为反问题(inverse problem)。关于反问题,一个众所周知的难点在于解的不适定性。因为不同的结构可以有类似的外在表现,因而反问题的解是不稳定的。在一个既定的情况 下,我们按照某种粗略的外在度量标准,从反问题的众多近似解中选择了一个。但是当所需的外在表现发生微小变化后,我们第一次选择出来的结构可能无法适应这 一微扰,而我们再次求解出来的结构可能与原先的结构有着巨大的差别。因而原先选择的解在结构上是不稳定的。在数学上,我们称之为奇异解(singular solution)。在数学上,在求解反问题的时候为了避免选择到奇异解,经常采用的技术手段就是类似于级列理论的所谓镇定方法。即我们提出一系列的模 型,对它们进行一维参数化。当参数较大时相当于对原有模型的一种近似,原有模型的细节被淹没在正定泛函的大范围结构中,整体呈现出一种简单的结构,而当参 数越来越小时,原有模型的细节被逐渐识别出来,整体模型逐渐复杂化,最终参数为0时恢复到原始情况。常见的模拟退火算法(simulated annealing)就属于这一策略族。通过模型的连续性,我们建立了一个复杂模型与一个简单模型(因而物理意义明确)之间的一条连续的纽带,沿着这条可 退化的途径,我们才有可能回避奇异解,保证复杂模型的物理有效性。
    在软件设计中,我所提出的级列设计思想正是这样一种渐进演化的设计思想。我们极力维护模型的可退化性,保证复杂的模型不至于锁定在错误的角落中。而基于模型的连续性,我们对于未来的发展进行外推才有了一定的根据。

posted @ 2005-12-27 01:22 canonical 阅读(612) | 评论 (0)编辑 收藏