用三层建立数据平台模型以 加快/简化 数据库应用程序开发之设想(妄想?)的探讨(300分)

  • 主题发起人 Another_eYes
  • 开始时间
A

Another_eYes

Unregistered / Unconfirmed
GUEST, unregistred user!
这几个月一直有个想法萦绕于脑海中, 现提出一些不成熟的思路望大家探讨.
. 实现难度如何?
. 执行效率如何?
. 扩展性如何?
. 有无先例?
. 值不值得做?
1. 想法的产生
由于一直在做MIS, 对编程中烦琐的数据库关系操作与调试深恶痛绝, 对日后的修改与
维护的工作量恐惧之至. 一直想找一种一劳永逸(当然是不可能的)的解决方法. 没有一
劳永逸的解决方法, 退而求其次, 想找到一种能大幅度降低工作量的方法.
主要想要解决两方面问题:
(1) 能大幅度降低编程难度: 最好所有工作只需操作一个表, 那样就没有编写数据库程
序时要考虑的各表关联所产生麻烦(特别是修改,添加或删除记录时).
(2) 能大幅度降低日后的升级与维护工作量, 最好能做到全部远程维护与升级(包括全盘
替换成新系统).
2. 主要目标
(1) 通用中间层: 中间层实现所有表间逻辑关系, 数据库牵涉多个关联表的修改, 添加,
删除应用由中间层自动分析关联关系, 自动对多表进行操作. 由于是通用的, 所以可以
针对不同实际应用(别拿臭鸡蛋打我, 并非不可能!)
(2) 独立客户端: 所有操作牵涉的只有一个简单的"表", 编程时只要考虑怎么对这个"表"
进行操作, 至于这个"表"中具体某个字段在真实数据库中处于哪个库哪个表或者完全
是个计算字段(甚至是另外某个表?), 在开发客户端时完全不必考虑, 也就是说在开发时
完全不必关心真实数据库究竟是什么样的, 真实数据库在开发客户端时是不可见的.
客户端开发时只要集中精力考虑客户端所要实现的应用逻辑与用户界面. 好象蛮适合
多组同时开发(或者分包开发)哦.
(很象是痴人说梦吧?)
3. 实现思路
(1) 中间层
既然要做通用. 我考虑的是建立一种中间层模板(借用word模板的概念), 不同的应用只
要根据具体应用对模板进行最小程度修改就能高效快速地完成任务. 那么, 首先我们要
做的就是提取所有应用的共性, 实现这个共性后再对特殊应用特别处理.
其实不管什么应用, 对数据库的操作无非查询, 修改, 添加和删除(哦, 还有备份, 不过这
也可以归入查询里面).如果我们有了很详细的数据库设计方案, 那么我们就可以知道
各表的关系(废话). 如果将这些表结构与表间关系记录到一个自定义结构的文件中, 再
由中间层程序对这个文件进行分析, 就能在客户端提出请求时明确得知需要具体操作
哪些表.
说白了, 中间层就是个解释器, 它解释客户端的请求, 根据表结构与表关系定义文件产
生SQL提交数据库服务器, 然后将结果合并成一个(或多个)数据集返回请求者. 这样,
针对不同应用只要定义不同的表结构与表关系文件就能实现大部分的通用了.
(2) 客户端
待续......
 
eYes大虾的想法也许是可以实现的,但我想这回很难,而且中间层要做成通用的,
那一定很庞大,我也做过一点(也不少)mis系统,我也说说自己的一点感受吧:
1、一般的管理系统都有操作员管理的模块,我做了一个之后,后来的都可以在
这个的基础上该一点就可以了,于是,我想吧他做成一个通用的,以后只需要
修改其中的参数(其实是要适应用户数据库权限的字段),就可以了。一般来说,
是可以的了,但毕竟用会的需要有是很奇怪的,有的只需权限分级个级别就可以了,
有的要以数据的输入,修改,统计。。。等来分开权限,而有的以功能菜单来分,而
每一功能菜单下,有分权限。。。。。。所以,我想,通用只是对于一定的范围来
说的。。。。。。范围太广,就变得不好用了。
2、〉〉“独立客户端: 所有操作牵涉的只有一个简单的"表", 编程时只要考虑怎么对这
个"表"进行操作”,我想这应该是很好的想法,能让人不用考虑表的主从关系,各种
关联,那正太好了,Delphi5的巢状数据表功能为这方面实现提供了可能。
3、“通用中间层: 中间层实现所有表间逻辑关系, 数据库牵涉多个关联表的修改, 添加,
删除应用由中间层自动分析关联关系, 自动对多表进行操作”,
根据我自己的做法,我很多时候都不愿吧对数据的操作做在中间层,而是做在数据库
后台,用存储过程,触发器等去实现,吧但方便,效率也高!而且,我觉得用数据库
(我用的是Ms sql)后台去实现,是很容易维护的,特别对于C/S,B/S模式。
4、生产(经营)不同产品的厂,就需要不同的功能,不同的模式,例如化工厂,由于产品
的特殊性,他有仓库,但往往产品不经过库,就直接到各部门的,我们分析时,觉得
以“货单”当作仓库是最方便的。。。。。。可能你们不知道我在说什么,我的意思
说,“往往通用就是不好用”,通用的中间层,会限制了程序员的思想做出最合适的
程序。
5、数据库的设计很重要,应多从这方面考虑问题。。。。。。
 
Another_eYes,我一看见你的帖子就关注并且添加到收藏夹了。呵呵
我也是从去年初入行以来,一直在做MIS,困惑之多,令我看不清前进的方向。
我为了解决编程所遇到的复杂关系和烦琐的维护问题,自己正在慢慢地建立各种
各样的模型。
1. 关于客户端用户界面,我摸索出了两套模型,但没精力实现。(回家就想睡觉)
2. 关于Another_eYes说的通用中间层,我觉得一心一意想着做成“通用”往往不能如愿,
分析各种各样的应用后,总结几种常用情况,给出解决方案,形成模型。(就象很多大
商家说的:“首抓集团用户,再考虑散户”)
3. 关于客户端远程自动升级的模型,我总结了两套方案:第一套很简单,就是服务端提供
一个最新版本查询功能,客户端访问并自动安装新版。不过只实用于局域网。第二套
针对广域网,自动更新于无声无息之中,不过用户如果知道有这种功能的话一定感觉
十分可怕。这套方案还没有头绪。
4. 关于xujiancai的操作员权限,我现在做的所有MIS都是用一个操作权限字段搞定所有
权限需求。其实我这个权限字段实际上就一个集合,如“A权,B权,C限”等等。然后我
在代码中用一个通用的 Operator 类。该类的方法主要有:
Op.Login(Name, Pwd), Op.Logoff, Op.HasPrivileges({A权,C限, ...}), ...
Another_eYes, 有空去SEE聊天室,我想找你多多请教。
哎,打字太累,我也待续....
 
我不支持使用存储过程,没有别的原因,不通用。
我觉得中间层是个好办法。赞同Another_eYes。
 
你们都伟大
 
三階我的理解還很膚淺﹐我為一家鞋廠做一個兩階的生管系統﹐所有的判斷工作都
放在客戶端﹐用很復雜的左連接把資料拉出來﹐供顯示和用戶的異動修改﹐更新用
updatesql,在QUERY的onupdaterecord里做統一的判斷﹐比如對于某個field,如果
oldvalue=null而newvalue<>null,則是新增﹐updatesql1.setparam(nkInsert);
...依此類推。自動判斷是新增﹐異動還是刪除﹐不知eyes的通用是不是這個意思
另﹕eyes好久不見了﹐你上次說做的東西做好了么?以后有好多東西要請教你
 
所以我说一起试试做个自由版的国产ERP嘛!不是不可能的!
 
其实,类似的想法很多人都想过吧,但做起来就没那么容易,我想说两点:
1.“通用中间层”不能用MIDAS了,必须用DCOM+OLE Server(COM Server)的方法,客户
端把SQL语句(可能是零碎零碎的条件什么的)传给它,由它解析,然后提交给数据库服务
器。
2.客户端主要负责传命令。但这里有个矛盾,就是如果要客户端传的命令越简单,
就要中间层的业务逻辑越多,通用性就越低,反之易然。
 
>> “通用中间层”不能用MIDAS了,必须用DCOM+OLE Server(COM Server)
我就用MIDAS,关DCOM什么事啦?我用MIDAS还可以选用 DCOMConnection 或
SocketConnection 呢!
客户端应该是由界面对象调用服务端的实体对象,它不知数据库的任何内容,
只知道服务端给它提供的服务,不该传什么SQL语句之类的。
 
》客户端应该是由界面对象调用服务端的实体对象,它不知数据库的任何内容,
》只知道服务端给它提供的服务,不该传什么SQL语句之类的。
这样写就不必用MIDAS了,呵呵。
 
我看EYES的想法很有创意,如果有兴趣可以组织一个研发小组,大家通过INTERNAT交流。
等到想法成熟后,把它制成应用软件发行也算终有所成。
 
http://download.china.com/zh_cn/software.php?id=1194
中华网下在的一个三层数据库工具,谁用过?
 
续昨:
(2) 客户端: 客户端的目的是为了能最大程度简化开发, 所要解决的一是如何做到完全
与数据库无关(完全不知道数据库具体结构与表的安排), 二是向中间层发送什么命令.
既然我们能在中间层设计一个表结构与表间关系的定义文件, 客户端当然也是用这个
办法: 设计一个记录开发时能访问的所有"字段"的文件(可以是个纯文本文件, 作为开发
客户端文档的一部分). "字段"之所以要打引号, 因为这里的字段跟具体数据库中的
字段名完全无关, 它只是中间层允许这个客户端能访问的数据库字段的别名, 大体如下结构:
name=DataType, Read/Write
name=DataType, Read/Write
......
这里的name是一个有具体含义的名字: 比如"帐号", "密码", "姓名", "性别"....(中间层
的定义文件中也定义过的别名)
DataType是数据类型
Read/Write表明是是否能读/写
需要说明的一点: name并不表示具体数据库中的字段名, 它可能在中间层解释时会
被替换成a表的a1字段, 也可能对应b表的b1字段, 甚至它可能是具体数据库中不存在
的, 由中间层分析对它的读写而决定查询/修改具体某个(某几个)表. 这点和Delphi的
property相似. 我们只要保证各个name都是为唯一的就可避免中间层解释时的二意性.
上述定义文件其实也是中间层定义文件当中的一部分, 是简化了的部分, 完全可以由
中间层定义文件根据不同需求自动生成, 对不同客户端只要提供不同的文档就能防止
这个客户端程序开发时访问不必要的内容. 对分布式开发大有好处.
基于上面设计, 客户端传送的就不是SQL了, 而是自定义格式的命令.
大致考虑了一下: 这个命令格式可以包含以下几部分:
1. 操作类型: 查询, 添加, 修改, 删除, login, logout等...
2. 请求者ID, 或者请求者用户名与密码 (从安全性角度考虑需要这部分, 中间层每次执行
操作前都对此进行检查)
3. 需要的字段
4. DATA部分 (用于返回查询结果, 提交修改等, 其实这部分可以就是TClientDataSet.Data)
由上可见, 我们客户端用的还是TClientDataSet, 区别是请求的发送不同, Delphi的
ClientDataSet是通过TClientDataSet.provider连接远端数据库的, 我们是直接调用
TClientDataSet.AppServer里面的一个自定义函数实现数据传送的,它返回的那个
Variant值直接赋值给ClientDataSet就能在本地操作这些数据了(也就是说, 我们的
ClientDataSet.Active永远是False, 我做过实验, 可行). 提交也一样(只是顺序相反).
4.难点:
由上面思路可以得知, 最大的难点在于中间层那个解释器中关于表关联的分析上,
根据用户请求, 如何决定哪些表需要相连及如何相连. 因为一个表可以通过多种途径
与另一个表关联, 因此, 如何决定通过哪条途径关联表进行操作是难点中的难点.
这部分与定义文件格式定义关系很大, 比如,我们可以在定义文件中以特殊格式填写表
间关联关系以方便解释器进行分析. 这里我的考虑还不成熟, 目前无法提出一个具体
方案. 欢迎有兴趣的同仁提出宝贵建议.
5.效率考虑:
由于中间层对所有请求都需要进行解释然后再执行, 速度 上肯定会有所下降, 下降幅度
到底有多大我也心中无数. 不过我想, 中间层增加的这个解释器, 其实就是一个简单的
字符串分析过程. 在目前的机器条件下, 这些时间消耗应该可以忽略不记.
另一个就是内存开销, 由于要解释, 必须将前述的那个定义文件以特定格式加载并常
驻内存, 我简单计算了一下: 如果一个系统有100个表, 每个表有20个字段, 按定义一
个字段80个字节算, 那么需要大约150~160k, 再加上表间关系也算150~160k, 那么就
需要300~400k, 如果每个连接都需要增加这么多内存的话, 那么实用性就大成问题了.
如果通过共享内存实现, 技术上是否可行不得而知(我从来没做过). 执行效率, 存在
冲突隐患我更是无法估算
综上所述:
我的思路不是直接的两层Client/Server, 也不是真正意义上的multi-tiered. 如果实现的话,
整个系统开发工作的重点将转到开发前的数据库文档设计上, 而不是中间层或客户端
的如何编写. 不论实现效果如何, 从对规范软件设计这点讲还是大有好处的. :)
 
我今天头晕脑胀的,只对这句话产生了一点联想:
>>基于上面设计, 客户端传送的就不是SQL了, 而是自定义格式的命令.
安全性如何?
SQL 本身的安全性就堪忧,按上述做法的安全性又如何呢?
 
精髓就在这里:客户端传送的就不是SQL了
如果大家做MIS做多了,就深有体会为什么要这么做。不过我在想的自定义命令格式
有没有必要公开,其实大家掌握了思路,可以各自创新嘛!
不传SQL语句反而让我感觉安全性更好控制一些。其实安全性不应当是这个时候深入
考虑的,因为现在是做核心骨架(灵活性要好)的时候,如果考虑这个又担心那个,
必将在表层徘徊不进。
 
另解释一下:
Another_eYes 上次提过, 要将 TClientDataSet 看做 TRemoteServer + TStringGrid
而并不仅仅将它限于传一个 TTable 或 TQuery 的控件。
请这样理解:
TList 是一种一维的基本数据类型
TDataSet 是一种二维的基本数据类型(而且行列可变)
当它只有一条记录的时候,它如同一个结构体(type Record),而且还带 FieldCaption 呢!
当它只有一个字段的时候,它如同一个附带Constraint的TxxxList
... (请联想)
如果大家理解透了这种概念, 会发现TClientDataSet用处之巨大。也会理解 MIDAS 与客户端
传不传SQL语句一点关系也没有了,因为那只是 MIDAS 中一种最简单的用法而已。
 
对Another_eYes的问题我一直在想,我们的三层用oracle+SocketConnection+ActiveX.
中间层一点也不通用(每个客户端都有对应的SERVER),
有时我怀疑,这就是三层的应用程序吗?
大家看看有没有好办法.
 
顶部