数据库的事务处理对类层次设计的影响,请大家来讨论一下。(300分)

D

dedman

Unregistered / Unconfirmed
GUEST, unregistred user!
在最近的开发中,我们系统的类是根据传统的数据源驱动而建构的(且称作元类),
对于具体的逻辑实体则根据需要设计相应的“子元类”。
目前问题出在元类这边,我们从“元类”抽象得到”基元类“,主要是把对数据库
的相关物理操作放在这一层,包括增删改查和数据库的事务递交。而元类间存在聚合关系。
| 基元类 |
/ /
/ /
/ /
|元类1| <>---> |元类2|
此时在基元类会有一个过程commitdatasets(datasets: array of TDBDataset)
对所有的相关数据表提交。也即是元类1要提交时必须把元类2 相关的datasets也一起提交。
怎样较好的处理这个需求,想听下大家的意见。
(另: Decorator模式好像无法满足这种需求。)
 
我认为你不应该把数据库操作放在基元类中,而是由另外的类来操作数据库,并
提供相关接口。
而你的子元类应该是处理业务逻辑的。
你可以定义一个数据包装类,子元类根据业务逻辑生成一个数据包装类,
然后将该数据包装类和相应的操作传递给进行数据操作的类。
我们通常习惯将处理业务逻辑的对象称为
BO(business object)
而将操作数据的对象称为OP(object pre????,对象持久化,我记不清怎么拼了)
这样整个系统的构架为
ui
|
------------
bo<->bo<->bo
| | |
------------
|
op
------------
|
database
一个bo是对应一个具体的业务逻辑的,
然后在通过UI(user interface)层的调用,
就可以实现比较好的对象组合机制。
bo设计的关键是使对象耦合最小化。
我觉得如果你设计的子类之间的耦合度太大的话,
那你就应该在此基础上再抽象出一个基类来处理。
或者更进一步进行对象分解,并使对象间的接口标准化。
 
facade模式怎么样?
 
TO 小猪:其实目前我们系统的框架基本是这样的,元类就是子元类的包装类,
而基元类负责的就是对数据库的操作,不过对于业务逻辑操作及物理操作的分离,
不知有没更具体的意见,特别是区分的原则。
如果把对数据库的操作下放到元类,显然可更方便控制,但增加代码的重复及
以后维护的复杂性。 对于再抽象出一个基类,我也建议过,不过仍被上级以上面理由驳回。
其实如果DELPHI有静态变量,在基元类定义一个静态的DATASET数据组,可能实施
起来方便很多。
对于FACADE模式,再考虑下。
 
区分逻辑操作和物理操作很简单,
比如业务上增加一笔订单,从业务的范围考虑,我应该需要的是一个
add的操作,这应该由业务对象完成。
但是,业务对象如何实现add的操作呢?
它应该根据业务逻辑生成一个数据封装类,然后传递给负责数据库操作
的类,要求根据传递的数据执行一个insert的sql操作。至于这个sql是什么样子,
业务对象就可以不用关心了。
可能facade是比较好的选择。
 
将类改为“接口”interface的形式。
 
正在改进设计,主要集中于物理操作与业务逻辑的分离。
用接口,我想一下。
 
小猪说的是典型的3层设计,将业务与物理分离。我认为:
1、模式是应用在业务层的,业务对象的抽象类有一个Execute(),业务对象之间又有聚合关系,
也就是一个业务对象的Execute可能如同宏命令,包括了一组其他业务对象的Execute,
所以这种情况类似于Command模式。
2、执行物理操作时,其中只要有一个失败,整个就要Rollback。这就需要设置物理对象的
事务类型,是require a transaction、support a transaction还是其他的。这样,
当业务对象调用相应的物理对象失败时,就能实现是整个rollback,还是不影响。
3、我对facade还不熟,提不出意见。
 
to ansern:
多谢关注。
不过把EXECUTE作为宏命令,则很难把公共的实现移到顶层, 因为此时很容易出现递归调用
该方法, 编写起来多了些顾虑。
 
如果基类有这样的接口就比较好办了:
TBase = class(XXX)
private
Relative :TBase ;
...
...
public
Constructor Create(Relative :TBase) ;
....
procedure Excute ;
proceduredo
Excute ;dynamic ;abstract ;
end ;

procedure TBase.Excute ;
begin
do
Excute ;
if Assigned(Relative) then
Relative.Excute ;

end ;
在使用的时候,这样做:

AObject := TXXX.Create(TXXY.Create(TXYY.Create(TYYY.Create))) ;
.....
AObject.Excute ;
其实使用decorate模式,不知道能不能满足你的需求???
 
to darkiss:
其实我们就是用DECORATOR模式,但由于物理层与业务层偶合太大,控制起来很烦。
你的实现方式与我们目前实现很相似。不过在CREATE方面我们采用PROTECTED
定义方法动态创建。而在EXECUTE方面,为了避免递归调用,EXECUTE有些许不同。
procedure TBase.Excute ;
begin
do
Excute ;
if Assigned(Relative) then
Relative.DoExcute ;

end ;
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
650
SUNSTONE的Delphi笔记
S
S
回复
0
查看
660
SUNSTONE的Delphi笔记
S
顶部