引言
在JavaEye潜水多年,这是我第一次发帖。我想在这里介绍一下我最近几年的编程实践,一套比较另类的技术。如果详细地写,恐怕篇幅太大.所以我尽量压缩篇幅,如果阅读时有跳跃的感觉,权且把它当作一个提纲而不是一篇文章。具体的细节,可以在讨论中展开。如果有人愿意尝试,我可以考虑把现有的代码修改后开源。我的奢望是,你读完以后,你会同意,或者部分同意,Java其实也可以很简洁,Java其实也可以很动态,Java其实也可以很高产。
这一套东西,我不知道怎么称呼它,所以我甚至不能给这篇文章起一个满意的名字,也不知道放在哪一个版块合适。它是数据结构,设计模式,构架(architecture),REST框架(framework),还是一种SOA技术?反正都沾边。它到底是什么,还是由你们来告诉我吧。也许它比较另类,其实也未必,最近坛子上就有许多类似想法的讨论。比如:
[讨论]Java中的ActiveRecord实现(我实现了一点儿)以及
一种Java Web框架的设计和实现,大家觉得能够快速开发吗?但是我在这里介绍的,是比较成熟的技术,用它实现的系统已经运行好几年了。
不管它叫做什么,它的核心在于认识数据,尤其是元数据,通过将数值与元数据分离,构造出一个普适的,弱类型的,开放的,动态的数据结构/数据模型/数据容器,(形容词的意义会在后面明了)。在它的基础上,借助XML技术(Schema, XSLT, XPath, ...)而开发出来的一整套技术。技术的实现上,借用了SAX 2。但你的项目可以完全不用XML。
我这里说的元数据编程,和通常的元数据编程,不是一回事。通常所说的元数据编程,是将代码中人机对话(对机器的指令,把 J2EE容器看成是特殊的虚拟机)的内容分离出来另行处理的代码生成技术。我这里说的是利用元数据简化数据模型,简化编程,降低系统耦合,增强系统稳定性和动态性的技术。
感觉国内XML的应用不多,此文也可以看作是对XML应用的介绍和推动。其实在Java 6以前,Java平台就已经支持脚本语言了,我都已经用了五年了,这个脚本语言就是XSLT。XSLT就是我们项目中的DSL。网友testhubo在
主题: 提问:使用策略模式的烦恼,要实现208个类 中提出的问题,如果用XSLT的话,不用那几十几百的类,只要一个XSLT文件就搞定了。单从可读性和维护性上讲,就比那几十几百个类 要强太多了。而且可以动态修改,动态部署,连J2EE容器都不必重启。
数据、元数据及注解
什么是数据(Data)?大概每一个软件人对此都是再熟悉不过了。比如下面的例子,可能是(静态类型)程序语言中最简单的数据形式了。
java 代码
这样一条简单的语句说了些什么?它无非是引入了一个变量,变量的数值是1.81,变量的物理意义是身高,单位是米,变量的类型是float。这是人人都知道的东西,有什么可说的?别急,貌似简单的事物,未必就那么简单。
为了简化我的表述,我要引进我的数学模型。说数学模型好像挺唬人的,但它其实就是初中代数第一课介绍的数与数轴的概念。上述的语句,可以看成是一种数学描述,它定义了数轴上的一个点。对于抽象的数学问题,我们不必关心这个点(数值/value)的物理意义,但我们的程序是要解决具体问题的,因此我们要强调它的物理意义,所以数轴上标明了身高(米)。这里的要点是:height(身高)是数轴/物理量的标签,而不是数值的标签,它表明数据的物理意义。所以我们可以说它是描述数据的数据,也就是所谓的元数据。不仅物理量的名字是元数据,物理量的单位,物理量的精度,定义域的范围等等也是元数据。
我们现在来看看这个类型--float,它又是什么东西?它告诉我们,身高的定义域是实数域。从这个意义上说,它也是元数据。从人机对话的角度看,这个float也是我们写给机器的注解--annotation,它告诉机器如何处理这个变量。
这个最简单的例子告诉我们,任何有意义的数据,都可以分解为数值(value)和元数据(metadata),元数据是描写数据的数据,它提供数值的Context。以人机对话为目的元数据叫注解 (annotation)。
元数据与数据模型
我们面对的概念和事物,往往不是仅仅用几个孤立的简单变量就可以描述的,通常需要一组互相关联变量来描述。比如,要粗略地描绘一个人体的大致形态,我们可以用身高和体重来描述,比如身高1.81米和体重82.5公斤,这里的身高和体重是想关联的。相应的数学模型是一个由身高和体重构成的二维空间,上面的实例,身高1.81米和体重82.5公斤, 可以记作(1.81, 82.5)。这种有序数组的形式,假定了横轴是身高,纵轴是体重。如果我们将空间转置,横轴是体重,而纵轴是身高,它应该不会引起任何逻辑上和物理上的变化,所以数学上可以不必区分空间和它的转置空间。但是在编程上,任何不必要的假定都是硬码(hard code),而硬码就是程序的硬伤。为了避免这个硬伤,我们必须排除那个序而直接将数值和它意义绑定,记作(身高:1.81,体重:82.5),它和(体重:82.5,身高:1.81)等同。
这样的一个数学/数据模型,在编程中怎样实现?通常有两种实现方法。一种是利用通用数据结构,像散列表(Hash,Hash Table),一种是构造专用数据结构,在OO语言中就是类。两种实现方法,孰优孰劣?可能所有的人都会同意,散列表模型肯定是一个有缺陷的数据模型,那么它的缺陷到底在哪里?在现实中,尽管人们知道散列表是一个有缺陷的模型,却总有人不断地企图用散列表来做数据模型,究竟是哪一点吸引人们这样做?这些是我想要搞清楚的问题。
我们现在把Hash模型和正统的OO模型作一番简单的比较,看看它们究竟有什么异同。先作静态比较,看它们在模型不变(需求不变)的条件下是否具有相同的数据表达能力。
Hash模型:
java 代码
- Map body = new HashMap();
- body.put("height", 1.82);
- body.put("weight", 85.2);
OO模型:
java 代码
- class Body
- {
- float height;
- float weight;
- Body(float height, float weight)
- {
- this.height = height;
- this.weight = weight;
- }
- ...
- }
- body = new Body(1.81, 85.2);
单从数值的角度看,二者的表达能力是等价的。但是我们在前面说过,编程语言中的变量,不仅仅包含了数值的信息,还包含了元数据信息。从元数据的角度来观察,我们就可以看出二者的差别:Hash模型丢失了元数据。比如在上面的Hash模型中读取身高,你在模型中找不到任何有关身高的元数据,它的元数据储存在程序员的大脑里。这是Hash模型的致命弱点。
再看动态比较,我们要观察的是在需求变化时,模型是否需要跟着变,就是观察模型对于需求扰动的稳定性。新的需求是,仅仅用身高和体重来表达人体还不够,我们还要加上性别特征。很容易看出,Hash模型是稳定的,它不需要任何新的数据结构或者修改任何数据结构就可以适应需求的变化。而OO模型必须修改,所以是不稳定的。人们不时地想用Hash模型来代替OO模型,也就是因为这个原因。
比较的结果:Hash模型对需求扰动是稳定的,柔韧的(flexible),通常我们说它是动态的,它的根源在于Hash模型是开放的,自适应的。在Hash模型中,我们可以轻易地引入新的维度来开拓领域空间。但是Hash模型是不完备的,它丢弃了元数据。OO模型是完备的,它把元数据对数据的约束“固化”在类型的定义里。但是,OO模型是封闭的,易碎的(fragile),对于需求扰动的是不稳定的。这是静态类型语言的通病。我不自禁联想到固件(firmware)。静态的类型,就像固件,也许可以叫它固码。
现在的问题是,有没有可能找到一个开放的,动态的数据模型来代替,哪怕是部分代替僵硬易碎的OO模型?在给出我的答案之前,让我们再来考察两个各具特点的数据结构:Tree和ResultSet。
在常用的数据结构中,树是另一个具有开放性质的数据结构。树形结构的一个特点就是它的嵌套性或者叫自相似性,那是一种由简单元素产生复杂结构的特性。HTML/XML就是很好的例子。在设计模式中,树的这种自相似的嵌套叫作复合模式(composite pattern)。我看中的是树的这种以自相似的嵌套来表达复杂结构和关联关系的能力。
在常用的数据结构中,ResultSet也许是唯一的包含有(分离的)元数据的数据结构。ResultSet看上去就像一个滚动的散列表+元数据表。它给我们一种启发,数值和元数据是可以适当分开的,我们可以给上述的Hash模型加上元数据的内容,克服Hash模型丢失元数据的缺点。如果我们走得更远一些,我们会发现数据和元数据不必终身绑定,在实用中元数据是可以延迟加载(lazy load)或者根本不加载的,这给了我们许多应用上的灵活性。同样在实用中,如果我们用遍历列字段(column)的方法而不是直接指名道姓的方法,我们甚至不必知道字段的名字。这是Hash模型的有利于开放性和动态性一个特点。
一个兼顾Hash, Tree,和ResultSet特点的数据结构,就是我要构造的数据结构。首先,它必须具有Hash的开放特性,只有是开放的,才可能是动态的。开放性也导致了数据容器的相似性,一个类型,以不变应万变。其次,它必须具有Tree嵌套特性。嵌套性提供了构造复合结构的能力。树的每一个节点(Node)都是一个散列表,或者滚动的散列表(像ResultSet那样),并且像ResultSet那样携带相应的元数据表。我把这个数据结构命名为数据集(DateSet)。从数学的角度看,一个散列表(名值对集合)就是线性空间中的一个矢量。一个滚动的散列表,就是一个矢量的序列。数据集就是矢量的一个实现。矢量的基本性质,并不因为空间维数的变化而变化,这就是上面说的开放性和相似性。矢量的某个分量,可以是有结构的,是一个子空间,这就是上面说的嵌套。这种与线性代数的比拟,我们在后面还会遇到。
关于数据集的细节和应用,请看《元数据、开放数据模型及动态系统--形而下学篇》。
分享到:
相关推荐
高中政治课程中的这一部分主要探讨的是唯物辩证法与形而上学两种哲学观念的对比,以及它们在看待世界和事物时的区别。唯物辩证法强调联系、发展和全面的观点,而形而上学则倾向于孤立、静止和片面的看法。以下是这些...
《论马克思哲学实践形而上学》这篇文档探讨的是马克思哲学如何对传统形而上学进行创新和改造,特别是在德国古典哲学的基础上构建实践形而上学的理论。形而上学,源自亚里士多德的《形而上学》一书,是探讨存在本身...
"形而上学的哲学演变" 形而上学是一门古典哲学的核心部门,在西方哲学史上曾经长期占据着统治地位。然而,形而上学的问题在二十世纪以来不知有多少哲学家宣称形而上学已经被彻底清除了,但人们直到今天却还是一而再...
历史与形而上学的关系,在费希特整个学说中是一个十分微妙的问题。一方面,他想要确保具体历史存在的合理性;另一方面,他又不愿让自身陷入特定的事实中。费希特从人类理性的、整体的历史出发,将具体的历史内蕴于先验的...
【高中政治教学计划集锦7篇】是一份旨在帮助教师制定高效、有针对性的高中政治教学方案的资料。教学计划旨在提升学生对政治学科的理解,尤其是马克思主义哲学的基础知识,包括世界观、人生观以及辩证唯物主义等内容...
从看似公正,不受偏见的角度来看,卡尔纳普声称能够通过“逻辑分析”一劳永逸地消除所有形而上学。 一方面,我们认为,就Carnap的分析严格来说是合乎逻辑的,这使得形而上学没有受到影响。 另一方面,我们认为,就他...
伦理学和形而上学是哲学的两个重要分支,它们探讨的是人类生活中的基本问题和存在本质。伦理学关注的是道德规范、价值判断以及行为的正当性,而形而上学则研究宇宙的根本原理、实体的本质以及知识的可能性。 在伦理...
一般系统论的发展和应用标志着科学思维范式的转变,系统论的提出,不仅在科学技术领域产生了积极的影响,更提供了一种新的系统思维方式,对于克服形而上学思想和笛卡尔主义在学术界的影响起到了有益的作用。...
笛卡尔与形而上学.doc
这篇初中文艺美学论文主要探讨了分析美学的衰落以及形而上学的复兴。分析美学起源于60年代,受到了欧洲大陆学派、美国实用主义学派以及内部以罗蒂为代表的哲学家的批评。分析哲学家尝试从知识论角度澄清形而上学的非...
【高中政治综合探究:坚持唯物辩证法反对形而上学】 高中政治课程中,"坚持唯物辩证法反对形而上学"是重要的哲学概念。唯物辩证法是马克思主义哲学的核心组成部分,它从物质世界出发,认为世界是普遍联系、不断发展...
它的基本形而上学是“纠缠融合”:这是受高维(HD)量子计算(“量子大脑”)启发的宏观纠缠概念,其中任何数量的纠缠波函数都可以与神经元高度相关。喜欢在他们中间发信号。 从这种纠缠的角度来看,战争和战争本质...
通过深入理解《五行》,我们可以更好地把握儒学如何从孔子的仁学出发,经过《五行》的过渡,最终在孟子那里形成了更加系统和完整的形而上学体系。这一过程体现了儒学不断演变和发展,适应不同时代需求的智慧和生命力...
辩证法和形而上学是哲学领域中的两种基本思想方法,它们在看待世界和理解事物发展方式上存在着根本的差异。辩证法源于古希腊哲学,并在马克思主义哲学中得到了深入发展,而形而上学则通常被视为一种静态、固定的世界...
《综合探究坚持唯物辩证法反对形而上学》的学习教案主要探讨了唯物辩证法与形而上学在看待世界和事物发展方面的基本分歧。唯物辩证法是马克思主义哲学的重要组成部分,强调联系、发展和矛盾的观点,而形而上学则常常...
总的来说,坚持唯物辩证法反对形而上学,就是要培养我们系统思考、动态观察和全面分析的能力,以适应不断变化的世界。在高中政治课程中,通过探究性学习,让学生主动参与讨论和思考,能够更好地理解和掌握这些哲学...
【辩证法与形而上学的对比】 辩证法与形而上学是两种截然不同的世界观和方法论。辩证法强调事物的普遍联系、运动发展和矛盾对立统一,而形而上学则倾向于孤立、静止和片面地看待事物。这两种思想形态在哲学史上有着...
《五行》是儒家文献中的一篇重要篇章,它在儒学形而上系统的构建中扮演了关键角色。这篇文献揭示了儒学形而上体系的内在结构,是连接孔子与孟子思想的重要桥梁。《五行》的思想体系既继承了孔子以来的儒家精神,又为...
形而上学唯物主义+辩证唯物主义.docx