banq请进,我发现你的JdonSD与我的openis非常类似

我发现我的很多设想在你的JdonSD中都能找到对应的思路,因此贴出我的openis文档,希望你与你交流。

openis 系统开发文档(1)
系统的历史、目标与方案的选择

1.0版
2004-01-16
庄表伟

一、历史
1、PHP版本,最初的试验
在2000年6月左右,我开始使用PHP为公司开发门户网站,当时有一个最初的设想,
来源于各种各样的“栏目”,在一个门户网站中,存在各种各样的栏目,每一个栏目都
有不少的文章,栏目还包括子栏目,子栏目下也可以 包括不少的文章。以往的设计
都是为不同的栏目设计不同的表,定下不同的字段,为了这些不同的表和字段写不同
的程序。于是我就考虑,能不能只用两个表来表示这所有的信息,栏目表、内容表。
无论哪个栏目的内容,都放在一个表里,这些内容的不同的字段,我通过一个包含了
各种冗余字段的内容表,来存放不同的内容。这样的设计当然是不符合数据库设计与
经典的软件开发的思路的。当时也遭到了一些反对。但是这样的好处就是,我可以写
一个统一的访问栏目与内容的函数层,整个网站的开发,不再需要考虑数据库结构的
设计,也不再需要写不同的数据库访问程序,项目的焦点,就直接集中于表现层,开
发的进度大大加快。至于系统的效率,当时确实没有考虑。

2、Java版本,命名为iMIS
在具体的应用中,我发现,不但栏目需要加子栏目,内容也可能需要加子内容。比
如BBS中,栏目就是板块,帖子就是内容,但是每一个帖子也可以有多个跟帖。不但栏
目是树状的,内容也应该是树状的。另外就是相关性,某一篇新闻的相关新闻,也需
要有所记录。
于是在新的开发项目中,我将栏目与内容统一命名为节点(Node)。 每个节点都可
以跟子节点。节点与节点的区别就是节点类型的不同。不但内容发布的信息是节点,
用户群组与 用户也是节点,产品类别是节点,具体的产品也是节点。只要能够想到
的信息,都是某种节点。节点与节点的 关系也有很多种,比如厂商节点与产品节点
存在“生产”关系,新闻节点与新闻节点存在“相关”关系,用户节点 与内容/栏目节点
存在“权限”关系等等。
这个系统被命名为iMIS,也就是集成管理信息系统的意思。这其中含义包括四个方
面“数据集成”,“应用集成”,“管理集成”,“界面集成”。但是这个系统并没有完成他
的命名所预定的目标,就已经完成了当时需要开发的项目的目标:)在公司来说,就不
再支持后续的开发了。

3、openis,一个全新的开始
一个全新的系统,不与某个具体的项目挂钩--虽然与具体的项目挂钩能够得到公
司的支持。2004-01-10开始。

二、目标
1、提高开发速度
最重要的目标就是提高开发速度,终极的目标是系统对于用户来说是“立等可取”的。
开发的过程变成修改的过程,而对于系统的修改成为常态。使得软件工程师与客户之间
能够直接交流,不再经过咨询人员的“低效率翻译”,也不用“UML”之类的高科技使用户
望而生畏,而是提供一种双方都能直接理解的需求定义的方式。
2、降低学习成本
无论是软件公司,还是使用软件的政府与企业,都不需要更多的学习,而是能够通过
一些简单的讲解,就能理解和应用。
3、规范开发流程
通过使用openis,在软件公司实现规范的,合理的,科学的开发流程,在清晰定义的
结构中,每个人都能明白自己的任务和目标。
4、提供整体方案
一方面在openis能够覆盖的范围内(Web上的管理信息系统),各种项目都能在一个
整体方案中得到实现。
另一方面,通过openis,能够整合现有的各种应用,进而对于用户显示出一个整体。
5、不断提高系统的性能
性能不是最重要的选择,但是必须在openis的开发过程中,不断提高。

三、方案的选择
1、同时支持java与.NET
java程序员与.NET程序员,都需要一套快速开发平台。
2、java而不是j2ee
j2ee华而不实。
3、ASP.NET而不是ASP
ASP对于扩展性的支持,远不如ASP.NET,另外C与java的类似性,也是选择.NET的
原因。
4、jsp+taglib≈C#+ASP.NET
ASP.NET的服务器控件是一种非常好的Web开发方式,jsp+taglib,能够基本实现类
似ASP.NET的服务器控件。
5、数据库作为主要存储方式
有很多人试图开发自己的存储方式与算法,但是这不划算,而且不太可能超过数据库
的性能。
6、提供一套完整的对象模型
这套模型目前要能够支持信息发布,内容管理,工作流,事务处理,以及版本控制。
而且在java与.NET中,应该用法一致。

看了你的设想,感觉不错,不过有一些问题恐怕需要引起你的注意。
1. 一般来说一个软件项目中,栏目的数量大致是10^3以下,而信息的总量就差异大了,大的可以达到10^8以上,所以所有的信息都放在一个表里可能会有很大的性能问题,同时很难针对特定类型的信息进行sql优化。
2.栏目和栏目之间、信息与信息之间以及栏目和信息之间的关联关系可能要另立一张表来存储,便于双向索引。
3.栏目和内容都作为节点来处理的话,在与域模型元素作映射的时候可能颇费周章,因为业务模型中,栏目和内容是两个截然不同的概念,两者之间有着很大的差异,举例来说栏目结构相对固定而内容就相对易变;栏目多呈树状结构,而信息多呈扁平结构(或者两层,如帖子)。
4.比较适合内容管理,但未必具有普适性,工作流就不适合此模型,你的目标太多,恐怕会影响openis的开发。

谢谢你的关心,我前面贴出的是文档的第一部分,第二部分,因为看见没有人关心,因此也懒得再贴出来了。

你考虑的这些问题,有些我已经在上一个版本解决了,有些是打算在openis里解决的。

下面贴出的文档的第二部分,最后的几节还没有写完,因为觉得自己的考虑还需要整理。

openis 系统开发文档(2)
系统的特性

1.0版
2004-01-16
庄表伟

一、统一信息访问
在openis中,信息分为两大类,一类称为“节点”,另一类称为“关系”。具体的节点
与关系的说明,将在概念模型中描述。这里的“节点”可以是任何类型的信息,例如数
据库中的一条记录,一个本地文件,一个FTP能够访问的文件,一个HTTP能够访问的文
件,一个Web Service的返回结果等等。
访问这样的信息,有统一的路径,类似URI,规则如下:

协议[.子协议]://[用户名]:[密码]@地址[:端口]/路径/节点名或表达式[.节点类型][操作][?[参数1][&参数2]]

例如:
file://local/c:/temp/info.xml
这样就能访问一个本地的XML文件
db.mysql://192.168.1.31:3306/mysql/user/id=1.user
这样就能访问192.168.1.31下的mysql数据库,其中的mysql库user表,id=1
的记录,这个记录取出来之后,作为user类的对象
core://192.168.1.31/info/news/nnodeid=1.news
这样就能访问192.168.1.31下的核心数据库中/info/news/路径下的nnodeid=1
的记录,这个记录取出来之后,作为news类的对象
core://192.168.1.31/ntreeid=1&nnodeid=1.news
对于核心数据库,可以只用treeid与nodeid定位一个节点,取出之后,作为news
对象
http://192.168.1.31/news/index.php
ftp://tiger:123@192.168.1.31/temp/temp.xml
这不用解释了吧

db.mysql://192.168.1.31:3306/mysql/user/id=1.usermodify?username=jack
将user表中的id=1的用户名改为jack

下面详细解释一下。

1、协议.子协议
访问任何信息都需要通过协议,http,ftp是我们常见的协议,file协议是用于访问
本地文件或者某一台局域网服务器上的共享文件。db代表了数据库访问协议,访问不同
数据库的jdbc作为子协议。core代表核心数据库,可以采用更加快捷的方式访问。
目前打算支持的协议有:
core
db.*
file
http
ftp
https
socket
smtp
ldap

2、用户名与密码
访问大多数的信息,都需要用户认证,或者以匿名的方式访问。

3、地址与端口(略)

4、路径
路径的概念来自文件系统,所有树状结构的信息,都可以通过路径访问。而对于关系
型数据库,则需要作出约定,用“库名/表名”表示。

5、节点名或表达式
对于文件系统,文件名即可以定位一个节点,而对于关系型数据,则需要表达式,约
定为只包含关键字段的表达式。否则可能查出多条记录。另外,一个文件的扩展文件名
并不是节点类型。

6、节点类型
系统提供一个基础对象Node,其他类型的节点继承Node对象,可以命名为NewsNode。
当不指定节点的类型时,就认为这是一个缺省的Node对象。

7、操作
不同的节点类型支持不同的操作,其中Node对象中有一个缺省的show操作,如果操作
省略,就代表调用show操作。

8、参数
与不同的操作有关,可变

二、节点
统一访问标识的是一个特定的节点,不同的节点可以有各种不同的属性,任何类型的节
点,都可以转化为核心数据库中的一条记录,如果一个项目不需要集成外部的数据和文件,
则单纯的核心数据库就可以满足大多数开发需求。每一个信息节点,包含以下信息:
--------基本字段
ID号
路径
父节点ID
名称
标题
创建者ID
创建时间
最后修改者ID
最后修改时间
子节点最后ID
类别
状态
-------扩展字段
n个varchar字段
n个int字段
n个datetime字段
n个float字段
-------内容字段
一个CLOB
一个BLOB
-------打包字段
一个CLOB

我们对于一个节点,通常有这样几个方面的查询需求,一个是对基本字段的查询,一个
是对于不同的节点可能产生的含义不同的查询,还有就是通过一个节点与其他节点的关系,
查询其他节点。从其他应用集成进来的信息,除了需要查询的字段我们放入扩展字段之外,
其他的就打包入一个CLOB字段中。

三、关系
任何节点之间都可以存在关系,整个系统允许数目不限的关系种类。每一种关系只存在于
两个节点之间,多于两个节点的关系,总可以转化为多个两个节点之间的关系。
例如:相关新闻,管理权限,项目与工作,BBS里的一篇文章在精华区中的位置等等

关系分为对等关系与不对等关系。相关新闻这样的关系就是对等的,而管理权限,意味着
某个用户对某个节点有管理权限,关系的左边是用户类节点,右边是普通节点,就不能交换。

可以通过操作取得某个节点的某一类相关节点。

四、操作与工作流
每一个节点都可以允许多种操作,但是在不同的状态下,这个节点所允许的操作是不同的。
我们可以用两个表来表示:
操作状态表:表示经过某个操作后,这个节点可能将处于的状态。
+---+---+---+---+
||状态1|状态2|状态3|
+---+---+---+---+
|操作1|*|||
+---+---+---+---+
|操作2||*|*|
+---+---+---+---+
|操作3|||*|
+---+---+---+---+
状态操作表:表示在某个状态下,这个节点允许的操作。
+---+---+---+---+
||操作1|操作2|操作3|
+---+---+---+---+
|状态1||*||
+---+---+---+---+
|状态2|*||*|
+---+---+---+---+
|状态3|||*|
+---+---+---+---+
通过这样两个表格,我们就可以完全清楚的定义一个节点的所有操作的相互依赖关系。如果
我们进一步定义,在某一特定的时刻,某个特定的用户能够对这个节点有什么样的操作权限。
则一个工作流的定义也就已经完成了。
在简单的情况下,我们可以假设一篇新闻,有是否被推荐两个状态,当一篇新闻被推荐时,
将无法被修改,而只能对其进行撤回操作,在未被推荐时,才能进行修改和删除操作。图表如
下:
操作状态表:
+--+--+---+
||推荐|未推荐|
+--+--+---+
|推荐|*||
+--+--+---+
|撤回||*|
+--+--+---+
|修改||*|
+--+--+---+
|删除||*|
+--+--+---+
状态操作表:
+---+--+--+--+--+
||推荐|撤回|修改|删除|
+---+--+--+--+--+
|推荐||*|||
+---+--+--+--+--+
|未推荐|*||*|*|
+---+--+--+--+--+
而对于更加复杂的状态流转情况,这样的表格同样可以胜任。在操作状态表中,一个操作可
能到达的状态有多个,这就需要在具体的节点中通过程序来实现了。

五、历史、版本与事务控制
对于一个节点进行各种操作之后,可能改变这个节点的状态,这个节点的上一个状态如果需
要,可以存入另一个历史记录库中,历史记录表与核心表完全相同,但是增加一个字段,既原
本那个节点的ID号。
添加与删除的操作,则彻底改变了一个节点的存在,因此需要一个系统级的历史记录表。
如果在历史记录表中,也体现出树状的结构,就可以记录一个节点的不同版本,成为一个版
本树。
当我们进行事务操作时,只要一次事务中的每一个操作都在历史表中记录了上一次的节点状
态,则这次事务就是可回滚的。无论这个事务跨越了多少个不同的表、文件、甚至服务器。

六、运行时服务器
1、统一节点访问接口
2、节点缓存与关系缓存
3、事务支持
4、日志服务
5、分布式访问支持
6、权限控制

七、TagLib

八、系统配置

非常不错,你这个思路我一直有,但是感觉现在的技术还不能很好实现,AOP是我非常关注的,也许等AOP一个相对成熟成品出来后,我觉得可以动手做了。

目前JdonSD框架是基于J2EE的一个开发框架,主要是解决很多人抱怨的J2EE多层结构开发成本高,EJB难以使用等问题。

对于JdonSD框架,我目前的想法是:我不希望做个完美的框架或平台,只是想随着我的实践,做一个可以帮助我自己的工具框架。

纳入工作流是我下一步要做的,目前思路已经成熟,借鉴了SAP的Business One中批准件设计,再结合J2EE新的技术,我非常有把握,因为之前帮助别人做了一个准工作流项目,但是没有上升到框架中,现在可以动手了,可惜就是没有时间。

关于树形节点,我已经有一个EJB组件解决它,所以涉及树形结构我都复用这个组件。

我一直纳闷Slide这个内容管理组件的设计思路到底是什么?虽然网站内容管理非常适合设计成框架,但是研究这么长时间下来,再参看国外的一些系统,如www.estore.com,通过浏览器对网站内容管理做得多好,可是市场不大,这里面有些问题在里面,我一直没有明白,所以暂时放弃这方面的努力。

对于openis我非常支持,我会在有时间时,做些工作。


一、DB的统一 VS 接口的统一
使用节点进行简化,操作是方便了些,我觉得还是有可改进之处,如果让我来做,我想我会是这样:
数据库,还将是多种表,至少栏目、内容表是分开的,不同特色的栏目表也是要独立出来的。
对于操作,提供给业务层的操作可以用DAO的方式封装一下,形成统一接口,比方一个基础操作类:Node,然后,也许有针对一些特色栏目的操作,那么你就写Node的子类:Directory.
DAO后面直接用jdbc或是hibernate都行,这些适用于不同对像的操作类也可以用工厂方法封装一下(如果封装,那么Node就要做成一个对所以操作都通用的接口)。
这样做相比原先,我觉得效率肯定是有很大提高,然后业务层的调用操作也方便。

二、权限控制
我注意到了你的权限模型中的两个地方
1.控制到表:db.mysql://192.168.1.31:3306/mysql/user/id=1.user
2.控制到表中某一记录的操作:db.mysql://192.168.1.31:3306/mysql/user/id=1.usermodify?username=jack
首先,一个业务操作是要涉及到多个表的,对于这种情况你如何处理。我也有过这种想法,但因为多表的控制,我放弃了。
对于2,控制到记录,用这种描述是否太过精细,如果user表中有10000记录,可能的操作有view,edit,delete,lock,又设定可以对他操作有level:5人 level2:10人, level3:10000人,level为大版主(all permittion),level2为小版主(自已版块的lock),level3为用户(自已记录的view,edit,delete)。就算采用通配符描述,用于权限控制的总记录也将达:5+10×1000+10000×3 这样的管理方式会导致记录膨涨很厉害。
我觉得对于权限的控制,url的与db的应分开。
url的权限的特点:请求从browser而来(系统外部),对于一个带参url请求,返回:允许 不 允许。
对于一个DB操作(比方,查):请求从server的jsp,servlet,ejb。。而来(系统内部),对于一个操作可能涉及多个表,返回:结果集中的一部分(一部分也可能少到0,这种情况就和url权限相同了)。
对于url用你的那种没问题,对于DB的就得硬编码或sql匹配(权限较简单的情况,门户网站可以采用)。如果非得硬编码也没什么,将系统框架设计好,代码一样清晰。
至于,协议细到ftp,http,https,端口之类,好像没什么必要,对于我权限系统来看就是一个url,透明的。

三、工作流与状态以及事务等等
没这么故意复杂化吧:),这种门户性的东西好像没有什么必要,个人愚见。

首先非常感谢你这么认真的看我写的文档。以前一直没有人这么认真的和我讨论过。
我们可以好好的讨论讨论。

>一、DB的统一 VS 接口的统一
>使用节点进行简化,操作是方便了些,我觉得还是有可改进之处,如果让我来做,我想我会是这样:
>数据库,还将是多种表,至少栏目、内容表是分开的,不同特色的栏目表也是要独立出来的。
>对于操作,提供给业务层的操作可以用DAO的方式封装一下,形成统一接口,比方一个基础操作类:Node,然后,也许有针对一些特色栏目的操作,那么你就写Node的子类:Directory.
>DAO后面直接用jdbc或是hibernate都行,这些适用于不同对像的操作类也可以用工厂方法封装一下(如果封装,那么Node就要做成一个对所以操作都通用的接口)。
>这样做相比原先,我觉得效率肯定是有很大提高,然后业务层的调用操作也方便。

在我的这个设计里,所有的信息都是节点,节点与节点之后,除了存在基本的父子关系之外,还存在着各种可能的其他关系。所有的节点都可以存放在同一个表里,也可以分成N个表。比如说,某个节点,定义自己的子节点的TreeID,然后有一个CoreTree表,定义这个TreeID所在的Table,他们可能是在同一个表里,也可能在不同的表里,甚至可能在不同的数据库,甚至服务器上。

还有一种节点的访问方式我没有写出来,类似于J2EE的JNDI,访问一个节点,只需要给出一个“/aaa/bbb/ccc/ddd/eee”这样的路径,至于这个路径在哪个服务器的那个数据库(甚至不是数据库)的哪条记录,都是无关的。

>二、权限控制
>我注意到了你的权限模型中的两个地方
>1.控制到表:db.mysql://192.168.1.31:3306/mysql/user/id=1.user
>2.控制到表中某一记录的操作:db.mysql://192.168.1.31:3306/mysql/user/id=1.usermodify?username=jack
>首先,一个业务操作是要涉及到多个表的,对于这种情况你如何处理。我也有过这种想法,但因为多表的控制,我放弃了。
>对于2,控制到记录,用这种描述是否太过精细,如果user表中有10000记录,可能的操作有view,edit,delete,lock,又设定可以对他操作有level:5人 level2:10人, level3:10000人,level为大版主(all permittion),level2为小版主(自已版块的lock),level3为用户(自已记录的view,edit,delete)。就算采用通配符描述,用于权限控制的总记录也将达:5+10×1000+10000×3 这样的管理方式会导致记录膨涨很厉害。
>我觉得对于权限的控制,url的与db的应分开。
>url的权限的特点:请求从browser而来(系统外部),对于一个带参url请求,返回:允许 不 允许。
>对于一个DB操作(比方,查):请求从server的jsp,servlet,ejb。。而来(系统内部),对于一个操作可能涉及多个表,返回:结果集中的一部分(一部分也可能少到0,这种情况就和url权限相同了)。
>对于url用你的那种没问题,对于DB的就得硬编码或sql匹配(权限较简单的情况,门户网站可以采用)。如果非得硬编码也没什么,将系统框架设计好,代码一样清晰。
>至于,协议细到ftp,http,https,端口之类,好像没什么必要,对于我权限系统来看就是一个url,透明的。

你看到的这个访问方式,不是一个权限模型,而是信息的统一访问描述。也就是说,当我知道这个信息之后,我会如何去访问(或者说操作)它。

至于权限不是在这里表示的。在我看来,权限也就是节点与节点之间可能存在的关系的一种。
基本的描述是这样的(节点A---节点B---操作1---条件)
这个描述的意思是:如果符合条件节,点A能对节点B进行1号操作。
这个条件可以是一个逻辑表达式,也可以是一个自定义的函数。

当一个节点要对另一个节点进行操作时,我们可以查询一个关系表,如果我们能够找到一条记录,是关于这两个节点的定义的,那么我们就使用这个定义。如果我们不能找到这条记录,那么我们就会去找节点B的父节点(一级一级的往上找),如果找不到,再找节点A的父节点,这样的权限定义,就不会出现你设想的“定义膨胀”的情况。

至于你说的db与url的权限分开,我不能同意,因为他们应该在一个概念体系里得到表达。至于多表查询的情况,那并不是单点操作的概念,本来也不是一般意义上的权限定义的范畴。

在我的设想中,跨越多表的查询,应该自己去写SQL,而跨越多个库,多个服务器的查询,应该另外定义树状查询语言,在内存中进行。

>三、工作流与状态以及事务等等
>没这么故意复杂化吧:),这种门户性的东西好像没有什么必要,个人愚见。

我设想的框架并不只是门户呀。再说随着项目的复杂度的增加,应用与应用之间的界限也会模糊,内网与外网之间的分别也会模糊的。