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

2006年3月25日

1. 对象的一个特性是局域化。每一个对象函数(非静态函数)都是在对象的上下文中调用的,因而隐含假设了一定的环境信息,这些信息以封装的形式被使用。
   一个具体的体现是函数的命名,如果没有对象,我们必须给函数进行全局命名,例如 find_friends, find_users, find_departments, 而在对象的环境下,我们可以抽象出一个采用局域化命名的接口 IQueriable.find(),实现系统的深度分解。
   在对象成员函数的内部,我们通过统一预定的名字(this指针)来访问对象环境中的变量。而在 jsplet web框架中的action和前台jsp中,我们通过thisObj变量来访问后台逻辑对象的上下文,而不需要知道对象的具体名称 (objectName)。

2. 对象的另一个特性是静态化。我们从面向过程走向面向对象时,我们思维中的图像出现了一个重大的变化:在面向过程的程序中,我们想象中存在的是一个个动态的处理过程,它们在时间轴上按照一定的顺序依次执行。而在面向对象的图景中,我们考虑的主要是一个静态化的世界,系统分解为对象,而对象是同时存在于我们的思维中的。这里一个重要的技术手段就是成员函数。例如我们编写一个成员函数getChildren(), 这个函数的语义是返回一个数据变量,概念上它是静态的,但其内部实现其实可能是很复杂的,非常的动态化:可能需要查询数据库,可能需要校验权限等等。
理想的情况下,我们可以利用成员函数封装可以实现对象图的遍历。例如  x.getParent().getChilldren(), 在微软的COM模型或者Sun的JavaBean标准下,我们可以写成
x.parent.children。
特别注意这里的属性语法原则上是与时间无关的,即在同一个时刻我们认为这些属性同时存在着,是一个静态的关系。而以下的调用出现了明确的步骤,因而明确引入了时间因素
ITree parent = node.getParent();
if(parent == null)
   return null;
List children = node.getChildren();
return children;

在witrix平台的tpl模板引擎中使用的EL(Expressin Language)表达式语法会自动处理函数返回值为null的情况,因而维护了对象图的语义,不需要中断调用过程来进行异常处理,是简化界面编程的一个重要方面。

这里顺便提一句:人的思维是倾向于静态化的,但现实世界却是在不断的变动中的。正所谓不变的只有变化。Von Neumann体系结构强迫我们在最细节处引入变化过程,很多时候是过分的负担。我们需要的是识别出各种可以静态描述的部分,集中精力于那些真正需要随需应变的应用。

posted @ 2006-03-25 11:36 canonical 阅读(789) | 评论 (0)编辑 收藏

    关于DSL(Domain Specific Language)的确切含义纷争很多,但是其核心观念还是很明确的。DSL的关键是使用领域特定的概念,即它的概念系统中具有一些非General Purpose的基元。但是这种所谓非General Purpose仅是就诠释层面而言,它所指的并不是DSL对应的形式系统。例如,在物理学中声波(sonic wave)无疑是对原子系统的集团运动模式的一种抽象,基于wave概念的声波方程可以看作是对应于原子系统的一个特定领域的DSL。从声波系统是无法逆推出原子系统的所有行为的,但是理论上量子力学在形式上同样可以采用wave描述,而它却可以构成对原子系统的诠释。
   
    DSL因为基于Domain概念,可以提高理解性是应该的,但是现实中的大多数DSL仍然存在大量技术性的形式要求,它们是很难让非计算机领域的业务人员掌握的。期待业务专家使用DSL在目前多半只是一种不切实际的幻想。但是如果认为DSL就是更甜的代码也并不适当。搜索google的时候我们使用的查询字符串也是一种domain specific language, 很多人都会使用""和-等语法结构。

    DSL应该关注用的层面(what), 而不是how-to,how-to是DSL的实现问题。从what到how to是我们希望通过DSL解析器屏蔽起来的内容,而不是DSL本身需要表达的内容。

posted @ 2006-03-25 11:24 canonical 阅读(708) | 评论 (1)编辑 收藏

    目前的框架设计中,引入元数据(metadata)已经是必然的事情,jdk5.0的annotation机制也为metadata的物理驻留位置提供了新的选择。常见的一些元数据设计方案中往往是元数据直接驱动系统的展现甚至运行过程(例如普元EOS),大有完全取代程序代码的趋势,这无疑是对元数据概念的一种滥用。一般在界面层所使用的元数据其实类似于某种新的界面描述语言,即某种特定目的的DSL(domain specific language). 但这种描述一般是不完备的, 一旦遇到扩展情况, 往往需要很多额外的工作。
    实际上并不是所有信息都要在独立的xml 中描述, 前台模板页面本身就可以是一种元数据, 前台元素之间的关联已经隐含表达了多种关系, 不需要把这些关联再在额外的xml文件中重复.  比如说一个数据集展现在页面上的时候需要支持几种操作,即对应的需要显示几个按钮. 在witrix平台的tpl模板中, 我们的调用方式大概如下
        <ui:EditTable pager="${pager}" dsMeta="${dsMeta}">
        <buttons>
          <ui:RemoveRowButton/>
          <ui:EditRowButton/>
        </buttons>
        </ui:EdiTable>
    操作集合这一信息仅在模板中表达一次.  实际上很多时候, 不同的界面我们需要展示不同的操作集合, 它本身并不一定是数据集内在的性质. 数据集的属性只能是支持全部操作的集合, 它并不需要直接对应到界面上. 对于多个界面我们需要尽量共用一个meta配置.

    在witrix平台的元数据方案中,关键是采用pull mode, 由前台模板系统驱动, 模板决定使用何种资源(包括元数据),而不是由元数据驱动整个系统的展现。当一个元数据条目不适用的时候我们可以忽略它,但是仍然可以使用元数据配置中的其他部分。这与我们的jsplet web框架的设计是一脉相承的。

    元数据的驻留形式本身也是很有意思的问题。假设现在我们需要描述如下信息:本字段采用input框显示,它有一个参数value. 它的meta形式可以如下,
       <inputor type="TextInput">
          <arg name="value" />
       </inputor>
    我们也可以选择如下形式
       <inputor>
        <input type="text" value="${value}" />
       </inputor>
    第二种方式的特殊之处是它选择了与html规范本身兼容的表达形式,即寄生于html格式之中。这种设计的好处在于我们只需要一个通用的模板引擎,而不需要任何特定于该控件的解析器,就可以产生最终所需的文本输出。这种元数据表达方式更重要的地方在于它是导向更高复杂性层次的自然途径。例如我们现在需要一种更加复杂的自定义控件来显示该字段,则
       <inputor>
        <ui:DateInputor value="${value}" />
       </inputor>

    在元数据的设计中,适可而止永远都是我们需要铭记在心的核心原则。对元数据描述的范围要适可而止,不要试图包罗万象。例如,在界面元数据的设计中不要对于数据供体有任何假定。一个前台表格,无论它的数据是数据库中的一组记录, 还是通过pop3协议收取的一组信件,应该都不影响它对于meta的使用。元数据引擎所能够直接理解的粒度也要适可而止。在witirx平台的元数据方案中,viewer和inputor等配置段其实是由tpl模板引擎负责解析的,在DataSourceMeta的解析器并不能识别其中的细节,它也不需要识别其中的细节。

posted @ 2006-03-25 11:19 canonical 阅读(1053) | 评论 (2)编辑 收藏