|
数学上的有效性与物理中的有效性是不同的,例如对于密码学问题,如果通过穷举法破解密码成功时,经过这些密码加密的数据已经过了有效期限,此时我们在数学上定义穷举法不是一种有效的破解方法。但是物理层面上我们说只要一种方法比另一种方法能够更快的解决问题,我们就说第一种方法比第二种方法有效,而无论密码被破解的时候该密码是否已经过了有效期限。
我所表述的论题并不是说特定的领域结构无法在某个特定的通用语言中有效实现。我想很多人对我的话语都有些误解。
如果我们认为一种通用语言是比较稳定的,则它一般选择只内置一些通用的不带有领域特定含义的概念. 而缺乏领域知识,或者说因为通用语言故意的摒弃领域依赖, 它在处理领域相关的问题的时候并不是有效的.这种有效性不是数学含义上的,而是可以进行物理度量的.
现在ErLang对通信领域具有良好的支持,你可以说它对于通信领域的结构是有效的。但是显然在ErLang中编写界面就不如面向对象语言得心应手。在ErLang中实现界面结构的时候,它对于界面结构的表述就不是那么符合我们直观的,对我们的实现过程来说就不是那么经济的。因此在界面结构的实现上,目前我们可以说ErLang相对于面向对象语言而言就是不那么有效的。也许你会说ErLang做XX发展之后怎见得就更差。但是如果允许引入未来这一具有无限可能性的因子,我们基本上无法针对现实的情况作出判断。例如我们目前并无法证明广义相对论相对于牛顿力学是更加精确的,如果允许在太阳星系中增加越来越多的隐蔽的摄动星体的话。按照库恩的科学革命论,每一个科学时代都具有着自己的科学范式,它总是具有着充分的自我辩护能力。范式的更新意味着格式塔的崩溃。回顾历史,哥白尼刚提出日心说的时候,并不是在计算精度,计算简洁性上真的远胜托勒密的地心说,只是日心说的哲学隐喻撼动了人心。
我说实际上现在的通用语言也是无法有效承载Domain Specific Structure的,这并不是意指在通用语言中无法针对特定应用作出特定扩展来支持特定的结构,而是说Domain Specific Structure是任意多的,作为通用语言它不应该把越来越多的结构内置在语言中(这不是很多人对ruby的希冀吗),这么做对它来说首先是不经济的。同时某些特殊的结构在一定的场景下是有用的,但是把它抽象出来扩展到通用领域的时候,会出现有效性的丧失。例如现在我的系统中只需要10个相互依赖的线程,如果我们定死了10这个数字,显然我们可以发展一种这个领域特有的高效的一些算法结构。而抽象到通用语言中的时候,显然我们只能假设线程数是任意大,或者是充分大的,而无法充分利用10这一领域信息,因此在这个意义上我说通用语言不是有效的。
传统上数学使用的一种逼近范式是:当n趋于无穷大的时候,偏差趋于无穷小。现在物理学对数学的一种常见要求却是:当n限定在有限数量范围的时候(例如10以内),我们如何才能尽量减少偏差。这要求对小样本数学进行深入的研究,它所具有的物理内涵也是不同的。
在物理的视角下,我们所关心的不是世界在终极的意义上能否分解为函数的复合,不是要导向一种宗教式的顶礼膜拜,而是强调要尊重自己所直接感受到的,充分利用我们因为在这个世界上存在而获得的直观意象,发掘自己的直觉,这样我们才能在无限复杂的世界上借助有限的信息做出选择。
因为在认识上物质和意识的两分,传统上哲学便分为唯物和唯心两大流派。唯物主义因为非哲学的缘故在国内占据主导地位。但在哲学上却从未平息过思想的纷争。胡塞尔的现象学试图重新回归形而上学,摒弃物质和意识的二元论,将它们统一到现象这个一元概念之中。我个人的思想基本是唯物主义的(毕竟少年时受过太多官方的教育),但是对我们目前所掌握的所有知识却持有温和的怀疑。
当一个非哲学家说到“客观规律是客观存在的”的时候,这是以他者的态度,从上帝的第三只眼看世界。但是我们此时此刻却存在于此一世界,因而不可避免的要卷入这滚滚红尘当中。为什么我们在应用分析和综合方法之后,能够通过螺旋式上升的路径逼近终极的真理?这就如同说一个迭代总会收敛,而且必然收敛在正确的结果之上。我们所认识到的一切为什么不能是为了应用方便而不自觉采用的机会主义的产物?所有可能的哲学都是我们在此生有限的存在中所无法证实或证伪的。当我开始质疑为什么我们不能是离(我们在有限时空范围内认为的)本质愈近,离真实愈远的时候,这不过是用一种无意义置换了另一种无意义,但是一个人的观点却因为他的情感的注入而对他显出不同。我们如何才能有勇气,有力量,有方法在有限的时空中创造出变化?
人类千年的智慧传承到我们这些普通的接受者手中的时候,它们都不可避免的陈腐了,庸俗了。当我们在说到这些真理的时候,我们的喉舌已经脱离和思想的联系。这些永真的话语在唇齿间跳动的时候甚至不能在我们的思想中激起微小的涟漪,它们不过是鹦鹉学舌。
道是无情却有情。有人说我们对规律的揭示是分析,实验和直觉的产物。可是直觉是什么?这里的逻辑类似于“如果A则B,否则其他一切情况则X"。所谓的直觉是一切非直觉的补集,实际上涵盖了我们所有丰富的情感历程和生存体验。理性却需要非理性来拯救。我们的行为总是受到情感的驱使。例如我在blog上写下一篇关于函数式语言的文章,一些技术爱好者纷纷发表议论,这是否是理智推演的结果?来的时候一腔热情,去的时候是否真的带走了什么事实?这样的事情每时每刻都在我们的世界中发生。我现在并不喜欢"XX之道"的提法,其实所论与道无关,只是利用了传统上对于道的敬畏,绑架了我们真挚的情感,却没有带来任何真实的体验。多情使得我们成为被忽悠的对象。
活着,用海德格尔的话说,一个字“烦”,用萨特的话说,两个字“恶心”,用普罗大众的话说,三个字“不想死”。但如何去活?中国人将个人的命运化入了家国的绵延,按李泽厚的话说,实现了心理学和伦理学的统一,在生的途中实现对情感的构建和塑造,这并不是单纯的个人生命体验,也不是宗教中神秘性的情感迷狂或心灵净化。
我在前面的文章中列举了大量物理学相关的例子来试图说明采用物理视角的必要性,但是可能因为物理事实大家不熟悉,结果直接被无视了. 在本文中我想有必要举一个软件领域的例子。只是在实际思考的过程中,我主要还是基于物理概念进行推理.
首先我所谓“现在的通用语言”,它并不意指“现在至未来所有通用语言之合集”,而是指“目前正在被使用的某一种通用语言”,这种差别便体现了我所强调的不同的价值观和不同的视角。不是一种覆盖一切的全称判断,而是在特定物理约束下的物理实体。
现在无论我们设计什么大型系统,一般总是要优先考虑微内核设计。但是很显然,如果我们的编程控制能力极强(强大到不现实的地步),我们可以把所有的代码实现为一个大的整体。一个整体的好处是勿用质疑的,否则Linux Torvalds就不会有信心和Tanenbaum PK。但即使是Linux, 随着系统越来越庞大,在内核中也补充了很多模块管理策略。我并不把这种情况看作是一种现在技术能力不到位所造成的结果,而是把它看作是在现实的物理约束下所促成的一种必然的选择。
按照类似的逻辑,我认为在通用语言层面不应该导入越来越多的特征,实际上也不可能把所有可能的结构方式都内置在语言中(这种不可能不是数学意义上的不可能)。这会破坏一种语言的纯洁性,使得它极难维护和发展。为了扩大通用语言的有效应用范围,一种显然的方式是在语言中定义一些支持结构再次抽象的机制,通过可插拔的方式实现与domain相关的知识的融合。ruby这样的语言提供了大量的元编程机制, Witrix平台中tpl模板语言也发展了一系列编译期结构构造技术, 但是显然它们都不能说是结构抽象技术的终极形态. 目前我对所有通用语言所提供的结构抽象和结构组装能力都是不满意的,因此在Witrix中发展了一些领域特定的结构融合手段.例如根据"继承"关系的结构诠释(继承可以看作是两个一维集合之间的覆盖关系), 我们扩展了extends的结构操作方式, 定义了广义的extends算子. 这些特定的结构关系目前在领域特定的BizFlow语言中体现, 它们在通用语言中是难以想象的, 而把它们放置在通用的语言中也是不合适的(这种复杂的结构融合操作如果不能结合领域知识进行直观的理解, 必将导向一种思维的混乱). 这就是我所谓"现在的通用语言无法有效承载Domain Specific Structure"的含义. 这种说法其实类似于"集合论是无法包容所有数学结构的". 我们在集合论中只研究最普遍的关系,而特定的结构在特定的学科中研究.
关于ErLang的例子, 我的原意是用来说明结构问题是独立的,它是和具体语言无关的.即基于消息传递发生数据关联的超轻量级进程模型这一结构不是和ErLang语言绑定的. 为此我特意加了一段说明:"这里不是要证明某种语言中无法描述这些结构,而是说结构是客观存在的,它并不是要在基础语言层面得到充分解决的". 即使在语言层面我们并不解决这个结构问题, 它仍然客观存在着,我们仍然可以用其他的技术手段去定义,去解决. 解决了这个结构问题就必然会带给我们价值,而无论我们使用何种实现语言.
"什么原因,什么样的约束条件,导致了现在的通用语言是无法有效承载消息传递发生数据关联的超轻量级进程模型". 这一命题并不是我原文中论点的合理推论.我并不是要说某一种特定的领域结构无法在一种特定的通用语言中得到支持.而是说如果我们认为一种通用语言是比较稳定的,则它一般选择只内置一些通用的不带有领域特定含义的概念. 而缺乏领域知识,或者说因为通用语言故意的摒弃领域依赖, 它在处理领域相关的问题的时候并不是有效的.这种有效性不是数学含义上的,而是可以进行物理度量的. 现在也有很多人认为ErLang并不是真正的通用语言,它是针对通信领域进行了特定结构调整的, 是内置了领域特定结构的. 而目前在ErLang上建立GUI的努力也并不算是成功.
在前文中我举了一个例子试图说明:"在限定的物理约束下,我们的选择范围会大大缩小". "比如说我现在有无穷多种方式从北京跑到上海,但是如果限定只允许用1升汽油,那么我们的选择就近乎于0". 这里并不是要说明加上物理约束之后,我们便没有任何选择了.而是说物理约束对无穷多的可能方式起了限定选择的作用, 它最终造成我们在具体的物理场景下可能只有非常有限的选择. 例如现在允许用100升汽油, 有多少种运输方式可以满足我们的要求? 如果允许1000升呢? 但是如果不考虑所有物理约束, 我们是否能够证明说: 飞机和拖拉机的运输能力是完全一致的, 因为它们都能从北京开到上海.
我的观点是结构问题是独立存在的,它具有自身的价值, 研究它也需要建立特定的价值观. 一个结构可以体现为语言上的某种语法特征, 也可以通过框架等实现, 或者表现为某种设计模式,某种编程技巧. 我们在思考结构问题的时候并不是从特定语言的机制出发的, 当语言不直接支持的时候我们可以发展特定的实现技术支持它. 在未来的日子里某个结构可能被证明具有普适的价值,它会被吸收到某个通用语言中成为所有程序的支撑结构, 但是更多的结构永远都不会进入通用语言, 而是居留在某个特定的领域. 通用语言的发展并不是完全基于抽象的数学分析而进行的, 它可以从更加丰富的物理世界中吸取营养. 当一种结构进入通用语言的时候, 它所带来的绝对不只是一组数量关系,而是同时带来一系列经过实践检验的物理诠释.
我所谓的领域并不是指业务领域, 而是结构领域, 一个可以定义特定结构的物理场景. 一个特定的结构仍然可以支撑着任意多的具体应用. 例如CRUD操作可以作为数据管理模型. BizFlow作为界面和单实体的交互模型.
函数式语言为我们提供了一种具体的技术工具, 但是在现实的开发中, 为了有效的处理结构问题, 显然我们需要多种视角的组合, 而不是把所有可想见的图景都纯化为函数. 我们对世界的体验是多样化的. 这就是我所谓"世界比函数的集合要复杂"的含义.
有一位网友,今年大二,询问我怎样才能成为技术高手. 我并不确定如何定义所谓的技术高手, 但是既然问到我, 便列举一下可能相关的事实.
首先请明确以下事实:
A. 挣钱能力和技术能力相关,但不成正比。
B. 他人的信任与信赖和技术能力无关。
C. 泡妞能力和技术能力可能负相关,请谨慎面对。
没有人知道未来是什么样子. 也没有人能够保证自己永远都是技术大潮中的弄潮儿. 如果你只是担心知识的老化, 担心能否长期的保有一份工作. 那么只需要不失去别人的信任,越来越熟练的做好本职工作就可以了。任何工作中当时用到的知识永远都只是很少的部分,只要别人给你机会重新学习,你的人生经验就会是你最宝贵的财富。
大二的小孩不要每天尽整些没用的东西。认真学好自己的专业课。做软件开发并不需要什么高深的知识,但是接受知识传承,得到全面教育的时机却是一去不回的。
不要怕学得多,更不要自以为学得多。我在学校的时候,横扫图书馆的哥们并不少。
读了书并不意味着懂得了道理。用自己的语言能否讲述学过的内容?能否用个简图勾勒Unix内核的结构?学过一门语言到底它有什么不同,能否勾勒发展的脉络?你学过的东西并不是你的东西. 你既无法消费它,也无法贩卖它. 在书本以外你是否真的意识到这些知识的存在性? 最重要的问题是, 你创造的东西在哪里?
读书开始的时候半知半解是正常的。这就如同张无忌背七伤拳经,总有一天你会懂得,只是需要不时的去回味。数学典籍中经常有这样的说法,本书内容是封闭的,只需要某某领域知识,但是掌握它需要数学成熟性。成熟是需要时间的。
读书不是以数量取胜。一个领域中类似的书只要细读一本,完整的读下来,读的时候多方参照,做简短的笔记。读一些原始的文献,读大师的原著。尽量选用英文的经典教材。懂一点学科的历史,知道什么是文化。了解一些学术界的八卦,吹牛的时候多一些谈资。
学习任何一个领域都需要深入, 需要掌握大量的相关细节, 因为只有这样才能够不再被细节问题所干扰, 而集中精力于真正的思想核心.
拳不离手,曲不离口。连Knuth老兄都在勤奋的敲程序,所以请不要找借口, 先编上十几二十万行代码再说话。编写而不是抄写。
天下没有免费的午餐。不付出相应的成本,无法得到相应的回报。学习没有捷径,只有方法。只是方法正确并不能保证你走到终点,毅力,机缘都是不可或缺的。你是否能够1天10小时以上持续地考虑同一个问题,是否能够保持同样的注意力坚持到每本书的最后一页, 是否一年365天对新鲜事物总是保有一份天真的好奇。
在工作中除了抽象的思想和具体的技术知识之外,还有大量小的trick. 例如调用equals的时候把常量放在前方if(MY_CONST.equals(myVar)).
一般不可能通过书本学习掌握所有这些技巧,只能在编程的实践中观察总结,更多的时候是要你主动思考,重新去发现这些方法。一个人的工作效率很大程度上是受其工作习惯所制约的,你是否在随时随地的改进自己的工作?
怎样才能做技术高手?这个问题我并不知道答案。公司里所需要的也不是技术高手,而是能够解决问题的人。不过如何培养合格的程序员,在公司内部也有两种看法。adun说要给他们指明职业发展的方向,关心他们遇到的困惑。这是P大的浪漫主义情怀。X罗说要给他们可以完成但是不易完成的任务,等待大浪淘沙后的结果。这是T大的现实主义精神。
开源是不可阻挡的历史洪流,我们只能改变自己的思维方式,调整自己的行为目标来适应它。
面对未来的挑战,Alan Kay有一句名言:The best way to predict the future is to invent it。如果你不知道该怎么创造,那就先从捏造开始练习吧----事物之间总是可以建立关联的。
现在讲软件工程的, 所谈论的多半是项目工程,
即如何在有限的时间内配置使用有限的资源在单个项目中达到既定的目标. 传统上, 在这一领域基于预测和计划的瀑布方法曾经占据主流,
但是随着项目的日益复杂化, 各种基于演化(evolution)思想的工程方法在实证中逐渐发展起来. 在时空跨度更大的软件工程领域,
例如延展到软件的不同版本以及多个相似项目的工程中, 演化更是逐渐取得了无可置疑的主导地位. 但是, 从另一个方面说,
目前所有这些软件工程方法所推崇的演化实际上都是非常有限的, 它们通过迭代(iteration)所能够描述的演化过程都只是片断性的,
例如一个项目中的演化, 一个软件产品的演化, 最大的莫过于一整条软件产品线的演化. 所有这些演化过程都面临着一个天然的屏障:
商业公司.在公司内部, 知识或代码可以由开发人员携带到下一个项目, 或者从一个小组传播到另外一个小组, 在新的基础上继续演化的进程.
但是核心的知识或者代码一般只能通过商业交易传达到其他公司, 这是一条非常受限制的途径. 而一个单个公司所开发的软件包, 即使是平台级的产品,
如果只是内部使用, 受限于该公司所从事的业务领域, 其所面临的使用检验也是非常有限的. 而且出于经济上的原因,
单个公司往往无力支撑多个实现同样功能的解决方案, 因而它倾向于消灭软件中的多样性, 这有可能会进一步限制演化的进程.
开源(OpenSource)软件为软件演化创造了新的可能性.商业友好的开源软件可以被不同的公司自由的运用于不同的业务,
因而可以参与到不同的局部演化过程中. 在应用的过程中, 开源软件面临着巨大的重构压力(这往往是超越了应用最广泛的封闭源码软件包的),
有可能保持更快的演化速度. 而通过对开源软件的回馈, 对开源软件的改进可以传播到时空范围跨度巨大的软件开发过程中. 而且基于源码的开放性,
开发人员的知识交流也随之开放起来. 类比于Darwin进化论, 我们可以说开源驱动了整个软件业界的共同进化(co-evolution).
多年前, Eric Raymond在著名的文章"大教堂和市集"中 http://263.aka.org.cn/Docs/c&b.html,
提出了开源的工程价值, 但其所关注的重点仍然只是单个软件如何在开源的模式下演化, 从今天的观点看来, 这篇战斗檄文已经显得有些局促了.
开源所造就的巨大演化空间远远超越了软件工程所能够提供的. 开源软件现在已经在商业开发领域站稳了脚跟,也渐渐超越了单个公司能够控制的范围.
可以说开源软件的发展是无可逆转的, 我们已经不会也不应该再回复到原先的封闭世界中.
每当我在文字中对函数式语言有些不敬之意时,便好像动了某些人的奶酪,以至我的言辞总在被曲解后遭到排斥。我想这就是因为视角差异过大所造成的. 但是谦虚谨慎是传统的美德, 不能容纳他人的观点只会妨碍自己在某些方向的探索。
首先请不要轻易怀疑我的知识水平。当然如果总无法聚集起足够的注意力来理解别人话语中的细节,我也无话可说。
容纳他人的观点就意味着不要总在自己的话语体系中试图找到反例. 一个人总是受限于他的知识范围,因此他也经常在自己的知识范围内篡改曲解别人的意见。我从未说过 "一个具体的问题是现有的通用语言无法描述的". 我说的是"现实开发中所需要处理的结构问题并不是在语言层面得到充分 解决的", " 现在的通用语言也是无法 有效承载Domain Specific Structure的". 请注意我对定语和动词的选择。其实我已经举了大量的例子来进行说明,但可能因为大多数人不是物理背景,对相关的内容不熟悉,所以直接无视了。这也很对,符合物理学的精神。
可能大多数人都知道函数式语言和命令式语言都是和图灵机等价的,因此它具有某种终极能力,怀疑它无异于怀疑我们世界存在的基础。但是请注意,这种等价性是数学性的。它潜在的要求是无限的能量和时间消耗。如果在限定的物理约束下,我们会发现我们的选择范围会大大缩小。所以我说"函数式语言和命令式语言的计算能力相同,但是在具体的情形下它们的描述能力是不同的". 比如说我现在有无穷多种方式从北京跑到上海,但是如果限定只允许用1升汽油,那么我们的选择就近乎于0。飞机和汽车的运输能力是相同的吗。物理学的一个基本精神在于一种物理性的约束是始终存在的。而事实上,我们在实际工作中也总是在各种有限的物理条件下工作。
也许有些人认为这种区分是无关紧要的,我们只关心某种终极的东西。但是物理学中有着太多的例证,说明在有限约束下,整个系统呈现出完全不同的性质。在通信领域我们都知道Shannon定理,它的物理诠释是在有噪声的信道上可以 有效的进行 准确的信息传递。但是这一诠释只能在有限的数学精度(远大于我们实际需求的精度)上成立, 在绝对准确的数学意义上,这是不可能的事情。
你觉得现在的通用语言做起领域相关的东西来很方便吗,这就是我所谓无法有效承载的含义。在这里我也没有否认"未来的牛语言可以轻松搞定目前难题"的可能性。
因为所有的软件设计最终都要落实到某种代码实现上,所以怎么会有什么神秘的软件结构是现有的语言无法描述的呢。但是ErLang中那种高并发,支持错误恢复的程序结构是在其他语言中能够轻松实现的吗。很多人不是在潜意识中认为ErLang的成功是函数式语言排他性的成功吗,不是认为命令式语言无论如何实现不了ErLang的程序结构的吗。很显然,在命令式语言中是无法直接实现ErLang中的程序结构的,否则它就变成了函数式语言,但是所有发生在ErLang世界中的事实都一样可以发生在命令式语言的世界中。ErLang语言的编译器可以是使用命令式语言实现的,在终极的意义上,语言之间能有什么区别呢?
我说"实际上现在的通用语言也是无法有效承载Domain Specific Structure的", 这还有另一层含义。通用语言设计总是要考虑到内置结构的某种通用性,设计时能够凭依的信息较少,因此不可能直接制造某种复杂的领域相关的结构。而目前已知的通用语言中提供的结构抽象的手段也不够强大(实际上我认为任何语言都不会强大到内置所有结构,也无法提供所有的结构抽象手段), 相当于是把领域结构问题推给程序员解决。这就如同C语言把内存管理推给程序员解决一样。现在ruby比较流行不就是因为它能够动态处理很多结构问题吗,但是它现在所作的一切就是足够的了吗。难道二十年之后再来看这个语言,不能够发现它存在着巨大的改进空间吗。我们目前在Witrix中通过tpl模板语言,bizflow extends等机制,结合整体框架设计实现了一些与ruby不同的结构构造方法。这些手段都极大的增强了我们面对领域问题时的信心,也确保了我们的领域知识是技术层面上可积累的。但是即使这样,我对程序发展的现状就是满意的吗?难道不存在更加丰富的结构知识等待我们去发现吗?一般人总是习惯接受已经存在的现实,在有限的职业生涯中把它们当作不变的真理,却没有耐心的去思考如何去改变。
我认为很多结构问题不是需要在语言层面得到解决的,而是应该在独立的结构层(平台,框架)进行解决。这意味着没有必要在语言层面直接内置某种特定的结构,内置某种特定的结构抽象手段。这基本类似于说不要把集合论扩大到包含所有的数学关系,请在别的学科分支中进行研究。需要注意的是,我所谓的领域知识不是特定的业务知识,而是从业务知识中可以分析得到的某种更加通用的普适的结构知识,甚至是可以使用数学进行精确描述的。
现代软件发展的时间还很短,与数学和物理学这样深刻的学科相比,它无疑是相对幼稚的,是待成长的,是更加的不完美的。在程序构建的基本问题上并没有抽象出什么可以实际操作的精确规律。这是所谓Pattern在软件业流行的部分原因:我们希望用这种半形式化的方式捕获某种思考的结果。但是软件真的除了基于抽象数学的全局的全称性的证明之外,不能够在局部进行某种更加复杂,更加严谨的分析吗。
我们说结构问题是独立的,这也意味着它和具体的实现语言具有某种意义上的分离性。通过一种语言书写的结构可以在另一种语言中得到表达。我们可以建立语言中立的技术结构。一种所谓的结构在概念上具有某种确定的形态,我们可以脱离具体的语言来理解它。例如我说"面向对象的继承关系从结构观点上看是两个一维集合之间的覆盖关系". 在java中我们可以直接使用语言提供的继承机制,而在C语言中我们就需要建立某种结构体,手动维持所有的指针关联。而在Witrix平台中,我们从继承的结构诠释出发,定义了更加复杂的extends算子,这就需要利用java语言编制特定的parser来实现了。但是显然,在思考的时候我们所有的思维指向是结构本身,而不是任何通用语言的语法。
在物理学中,通过摄动分析我们可以清楚地意识到:同样一个物理现象对应的数学模型可以是众多的,但是在特定的参数区我们会选择某种特定的数学表述,并确定其中的待定参数。
delta函数是物理学家狄拉克引入的,在Schwatz引入分布概念建立广义函数论之前,物理学家们已经使用这一函数工作了很多年。后来Abraham Robinsen利用数理逻辑方法,建立了非标准分析,通过模型论的方法精确定义了无穷小的概念,从更加直接的角度论证了delta的合理性。但是在物理学家看来,这些数学又有什么区别呢?物理学只是按照物理的诠释进行工作,具体的数学只是它可选的工具而已。
物理的真理并不是蕴含在数学中的,它需要我们独立的探索,从与数学不同的观点进行思考,检验,最终我们才能做出真正的发现。广义相对论可以采用Riemman几何进行描述,但是它的物理诠释却是Einstein提出的. 没有人说Riemann或者Hilbert发现了广义相对论。另外一方面,因为Einstein的工作触发了对于微分几何的更加深入的研究,靠着物理直觉的导引,我们将这一数学分支推进到了难以想象的深度。"数学是无法涵盖物理学的". 这不是说最终物理学无法采用数学语言进行描述,而是说在这一发展过程中,所有思想的推动来源于物理学的经验,来源于我们在这个物质世界上所进行的反复验证。不是在一个封闭的小屋中,整天摆弄各种数学符号,我们就能够发明所有的物理公式所对应的数学。实际上,现在学术界普遍承认,没有物理学的推进,很多数学的进展是不可能发生的。
物理系每天都在演算着Feynman路径积分, 但是所有人都知道这是没有什么严格的数学依据的.目前并无法定义路径积分的收敛性,但是所有人对此避而不谈. 只要形式演算合法,物理预测符合实验, 合理性的证明只是数学家们的事情. 在量子场论中所采用的重整化(Renormalization)方法不过是回避无穷大问题的一种形式手段.我们仍然无法在数学层面对所有的演算都给予合理化解释. 在更多的物理分支中工作,你就会发现物理学家的胆子不是一般的大。也许在未来我们能够发现这些物理过程背后数学机制的精确定义, 但也许最终我们也无法找到合适的定义方式. 但这对物理学家来说, 并不是很大的打击.因为指引我们的是物理直觉,是独立于数学的物质世界的意象。
我所想讨论的不是某种终极意义上的可能性,不是绝对概念之间的冲突,而是在物理现实的约束下,我们如何才能有效工作的问题。我已经反复表述了自己的观点: " 结构是可抽象的,是具有独立意义的。这就是Witrix所提出的面向结构的设计视角。不是强调对象的所谓业务含义,不是强调某种通用语言(例如ruby)的灵活的语法结构。在这之间存在着厚重的具有物理意义的可以进行结构分析的技术层". 也许有人觉得我说的这是废话, 但是当系统化的执行一种思想的时候,就会揭示出未预料到的可能性. 整个Witrix平台简单的说起来就是" 面向结构的级列分析", 但是如何找到合适的技术形式来体现这一思想,却绝对不是一件平凡的事情. "在Witrix中我们实现的代码重用程度和程序整体结构控制能力是超越了目前所有已知的公开技术的。这不是什么哲学,而是我们在残酷的商业竞争中得以生存的资本". http://canonical.javaeye.com/blog/126467
在我看来,计算机领域充斥着纯数学的深沉遐想和从工程实践而来的轻佻常识,还没有注意到物理学所能带来的不同的同样深刻的视角。我常说,好好学习物理是必要的,因为这个世界远比你想象的要复杂的多。
我的观点并不是什么具体的程序结构问题不能用函数式语言处理.我所要表述的是这和函数式语言中能否加入结构解决任意复杂问题无关。为什么所有的问题不能在集合论中解决,为什么要有独立的数学学科。物理学所有的定律都使用数学表述,是否意味着物理学的真理蕴含在数学之中。
我说 实际上现在的通用语言也是无法有效承载Domain Specific Structure的。其实与以下说法是类似的
数学是无法涵盖物理学的,现在的已知的数学工具是无法有效承载尚未得到充分探索的领域的物理的
我说 我所关心的不是语言层面的问题。这类似于说 不要把所有物理问题都推到数学层面去解决。
我们应该研究独立的结构,应该建立单独的价值观和方法论。不要谈及一个技术进展的时候就说某某语言好,不是一说到DSL的优点就要去抱ruby的大腿。此外,我的观点也不是去做业务分析,不是去如何更好的实现业务到基础技术结构的映射。
不是强调对象的所谓业务含义,不是强调某种通用语言(例如ruby)的灵活的语法结构。在这之间存在着厚重的具有物理意义的可以进行结构分析的技术层。
我想说这个结构层面现在并未得到充分的关注,我们对于结构的问题并不是非常清楚,对程序结构的稳定性更是少有经验。我们在Witrix中做了大量的工作,试图做到如下的图景:
永远只写代码片断,而所有的代码片断组合在一起又构成一个可理解的整体
对背景不是分解让其成为可见的部分,而是采用追加的,增删的方法对背景结构进行修正,则我们有可能在没有完整背景知识的情况下,独立的理解局部变化的结构。即背景是透明的,知识成为局部的。
http://canonical.javaeye.com/blog/126467
在Witrix中我们实现的代码重用程度和程序整体结构控制能力是超越了目前所有已知的公开技术的。这不是什么哲学,而是我们在残酷的商业竞争中得以生存的资本。
号外:
不要把具体的技术和一种技术思想混为一谈。一种实现总是包容了太多的思想。思想错了,实现对了。实现死了,思想活着。
关于哲学的问题是很有意思的,因为它是引起最多思想冲突的地方。原本[关于认识的悖论]这篇blog是我在重温维特根斯坦之后反思自己的哲学观念所写下的一些文字。我在具体的推理中是明晰的,但是在哲学思想方面一直是混乱的,所以估计对旁人而言它确实没有什么可读性。不过如果有人感兴趣愿意讨论一下, 我想说明一下我在哲学方面的几个观点:
1. 哲学于我而言是严密的逻辑论证,还是浪漫的情感诉求?
2. 我不认为认识的终极指向所谓的规律, 因为即使我们掌握了所有的规律(包括规律的规律?),仍然解决不了规律为何存在的问题。
3. 当我们自以为对XX的认识越来越清晰,越来越深入的时候,是否已经偏离了XX? 偏执的认识可以激发强烈的情感,聚集思维的资源,引导我们穿越未知。但是新的联系怎样从出人意料的地方生长出来?
4. 维特根斯坦晚年创建了分析哲学的日常语言学派。有人说他变成了星宿派,有人说他发现了新大陆。但是无论如何,自然语言作为人类所创造的思维工具,对人们思维的潜在影响是难以估量的。在人造语言中,借助罗素的类型论我们似乎可以回避问题,但是并无法终极解决逻辑系统的循环依赖。波利亚在数学家中曾经做过一个有趣的调查,询问著名的数学家在思考的时候是否会依赖自然语言,回答各异,但很少有人说严格按照公式进行推理。以我个人而言,思考时更多的是某种似曾经历的意象,而很少是严格的逻辑表述。创造的依据是否是事件之间难以言传的微妙联系,抑或是原始的创造力只是源于错误的巧合?
5. 西方哲学从笛卡尔开始,从本体论转向了认识论。但是是否现在我们已经认清了自己的所在?矛盾的产生是事物内在的真实存在的特点,还是因为认识层面的割裂而人为造成?有多少冲突是因为没有发现协调方式而造成?分析和综合之后我们能够达到什么?螺旋式上升的比喻让我感到有些眩晕。
6. 东方的思维方式不是分析法的,也很难说是归纳法的。这种所谓的整体论难道只是披着神秘外衣的巫术?现在学术界流行的是以西方的思维工具来重新诠释一切观念,我的思想中到底受到各方观点何种影响?难道故老相传的东西都只成了被研究的客体,成了手术台上待解剖的木乃伊?
7.从我们的词汇表中抹去那些词语之后我们将无言以对?例如规律两字。
以上所论的一切都是无价值的,因为其实我只是想问自己一个问题:明天我的灵感在哪里,如何回答。
1. 函数式语言可以合理的看作是泛函分析思想的一种体现,从历史发展的时间上看大概也是具有这种可能性的。在Backus的论文中对函数式语言的一种乐观的情绪甚至扩大到functional algebra can be used to tranform programs and to solve equations whose "unknowns" are programms in much the same way one transform equations in high school algebra。这种信心只能来源于泛函分析和方程论,来自于数学分析学的发展。将函数的函数作为分析对象就构成泛函分析。泛函分析的最核心的思想当然不等价于它所研究的那些无穷维空间,不等价于种种正交基的构造。它的思想核心在于函数的函数具有独立的分析价值,具有脱离数量空间的具体的结构。这也是函数式语言试图推销的一种理念。
2. 最近这些年来一种称为"范畴"(Category)的东西在计算机理论研究中频频出现。范畴论是从同调代数发展而来的一种较新的代数语言,但它显然也不是可以解决任何问题的灵丹妙药。多一种表达方式当然在某种程度上可以增进我们的理解。但是范畴本身只是研究一种基础结构,它本身并没有承载所有的物理事实,基于它不可能对所有的规律一网打尽。不是明白了范畴,就懂了程序。范畴论是一种基础性的语言,有些人致力于基于范畴论来构建数学的其他分支,取代集合论的地位。将计算的本质重新归结于范畴论是无意义的,它不过是对事实的另一种陈述方式。说“函数式语言是基于范畴”是无意义的,因为这和说“所有现代数学都基于集合论”一样。无法发现新的相互作用关系,所有的概念都只是同义反复。不是一拿起数学,就找到了组织。
3. 我对函数式语言并没有什么反对意见。它是非常重要也非常优美的一种技术思想。但是现在一些函数式语言的狂热支持者似乎对函数世界充满了乌托邦式的幻想,一种大一统的世界观让人迷醉,但是它却解决不了现实的问题。所以我说无法认同函数式编程的世界观。作为一种具体的技术工具,问题不在于函数式语言是否体现了计算的本质,而在于它是否向我们提供了称手的兵器。现在我要计算两个小球相互碰撞的问题,我可以操起广义相对论,量子力学啥的开始大干一场,也可以用个牛顿力学小试牛刀,甚至可以只用反射关系摆个等式。但是在绝大多数情况下我们都会说这里面的物理是弹性反射而不是相对论。在理论分析中我们经常使用平面波假设,但只要实际关心的对象不在波包的边缘,没有人会认为平面波不是真实的物理机制。理论物理不是理想物理。在具体的参数设定下,我们只会使用特定的物理学。
对世界的认识并不是非此即彼的。并不是说函数式语言好它就永远都好,要把所有对立面都灭掉。也不是说函数式不好,命令式就必然的好,就必然的能够解决问题。函数式语言的世界观过分单纯而排他,这是我反对的,我同样无法认同面向对象的本体论论调。就像CISC和RISC架构之争一样,最终我们在现实的物理约束下,运行的最好的芯片是两者思想的结合。这是我们面对物理世界的基本态度。
4. 函数式语言中时间是个有趣的概念。命令式语言中因为赋值语句的存在,使得我们可以观测到状态的变化,因此必然要定义时间。而函数式语言是无状态的,可以是无时间概念(对Lazy Caculation的依赖是否体现了深层次上对时间概念的需求?)。有些人认为函数可以看作是相空间中的迁移函数,是与相对论协调的,因而反映了时间的本质等等。相对论主要是解决了物理规律的协变性的问题,在此过程中它使人们认识到了时空之间奇异的对称性。但是广义相对论的表述中时间也是可逆的。真正定义了时间之箭的是热力学第二定律。根据Landauer's principle: 擦除(erase)1比特信息,耗散到环境中的能量至少是k*T*ln2, 或者说熵增至少是k*ln2. 这意味着只要我们对眼前的黑板不停的写了擦,擦了写,就必然无法回到过去。物理世界是复杂的。
5. 如果将状态看作是可以附着在某个对象上的标记,显然状态的存在性便于我们识认概念的唯一性。对象还是那个对象,只是状态标记发生了变化。而如果系统中没有状态,则必然产生了一个新的概念。这在很多情况下是不必要的负担。状态的存在使得系统在局部结构上允许出现非常复杂的变化,函数式编程的拥趸们对此多有诟病。但是从另一个方面上说,状态使得我们可以基于局部信息处理很多问题而不需要把它扩大化为一个全局匹配问题。
6. 函数构成函数似乎是很完备统一的世界。 但是在物理世界中发生的一切却复杂的多。虽然世界可以还原为原子,但是原子构成分子,分子构成宏观物质时,系统的基本性状发生了本质性的变化,并不再是统一的形式。每一个层面上都会产生独立的结构规律。
7. 函数式语言和命令式语言的计算能力相同(可以相差一个任意长度的多项式时间),但是在具体的情形下它们的描述能力是不同的。我所关心的不是语言层面的问题,因为语言本身的能力并不足以解决现实开发中的所有问题。即现实开发中所需要处理的结构问题并不是在语言层面得到充分解决的,这是我们需要做工作的地方。
关于现实中的结构问题,我无意去定义什么万能的描述能力。你可以用微分几何,积分几何,广义变分等等手段去证明圆盘是某种意义下的周长最短的东西,但是这一切对你发明轮子并无本质上的助益。不过可以说说现实中的结构。这里不是要证明某种语言中无法描述这些结构,而是说结构是客观存在的,它并不是要在基础语言层面得到充分解决的。实际上现在的通用语言也是无法有效承载Domain Specific Structure的。
A. ErLang大概是目前世界上应用最为深入的函数式语言了。它确实发挥了函数式语言无显式状态变量的优势。但是它对程序构建本质上的帮助更多的来源于无共享的超轻量级进程模型,相当于定制了一般操作系统所提供的基本服务。微软的一个实验性操作系统项目Singularity, 其中也定义了只通过消息传递发生数据关联的超轻量级进程模型,它使用C#的一个扩展语言,额外增加的功能是消息管道上定义的规格状态机,对消息交互的时空模式进行额外的规约。这里对我们真正有价值的是隔离的单元结构。
B. AOP是程序结构空间中的定位和组装技术。在Witrix中我们规范化了切点处的状态空间,并对AOP进行了偏置处理.这种结构调整大大提高了AOP的可用性,使得它成为Witrix中的核心技术手段之一。
C. 面向对象的继承关系从结构观点上看是两个一维集合之间的覆盖关系。在Witrix中扩展了extends所对应的结构操作,创造了新的结构融合手段。
我习惯于概念层的推演,而且所阐述的东西多数是我们创造过程中的副产品,与业内常见的观念实际上是有着很大差异的。有些人感觉我的文章读不明白是因为没有采用类似的视角,或者还没有独立思考过很多问题。如果只是从业内已经熟知的概念出发试图理解我所写的内容,显然是不可能的事情。所以我常说know something already known.
如果在编制一个新的应用,存在大量代码可能是
myFunc(){
for each x in set
doSomethingValuable(x);
return packedResult;
}
myOtherFunc(packedResult){
for each y in pakedResult
doSomethingOther(y)
}
其实我们真正关心的是循环内部的某个过程,但是我们经常可以观察到它们被某些通用的或者特定的循环(集合遍历)操作所包围着。Witrix的设计方式是强调业务关注点,而把所有的汇总操作尽量抽象完成。比如现在界面上显示一些字段。从抽象的操作上说
for each field in dsMeta.viewableFields
show field.viewer
这一过程在平台代码中实现,它是一个通用的集合操作过程。不同的具体应用只是关心具体字段的展现形式,虽然我们必然需要字段集合,但是它不是我们注意力的重心。
如果考虑到字段在界面上展示有一个布局问题,我们所要修改的是集合内部的结构方式:
某种结构循环方式(dsMeta.字段组成的布局集合)
show field.viewer
抽离出集合,实际上是在最大限度上分离结构问题和内容问题。
结构是可抽象的,是具有独立意义的。这就是Witrix所提出的面向结构的设计视角。不是强调对象的所谓业务含义,不是强调某种通用语言(例如ruby)的灵活的语法结构。在这之间存在着厚重的具有物理意义的可以进行结构分析的技术层。 http://canonical.javaeye.com/blog/60758 http://canonical.javaeye.com/blog/126467
|