分享
 
 
 

分布式环境下对具有对象类型的属性的对象的添加、删除及修改

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

分布式环境下对具有对象类型的属性的对象的添加、删除及修改

1. 问题描述

要讨论问题首先要把问题说清楚才好讨论,下面是我们所要讨论的问题的描述。注意,我们这里不讨论对象传输时的marshal及unmarshal问题,总之,对象能够在网络上传输(比如通过RMI或WebServices等)。

1.1 问题

有时候对象的逻辑结构比较复杂,它不但有整型、字符串型等基本类型的属性,还包含对象类型的属性,对于处于分布式环境下的此类对象,进行对象的添加、删除及修改。

1.2 需要考虑的各个要素

对于这个问题,有以下几个方面需要考虑[K1]

l 从业务逻辑的角度来看,由于此类对象就是应用程序应该处理的一个单元,所以,对于对象的操作应该是原子化的。而从用户操作的角度看来,应该在一个界面中就提供操作整个对象的能力,当然包括其下层对象。

l 如果服务器提供支持,允许客户端自己控制事务,那么,客户端可以保证自己所做的操作的原子化,但服务器要维护这个客户的状态;并且客户端在事务之间(已启动事务,但尚未提交或回滚)有可能由于某种原因失去于服务器的连接,服务器要处理这种情况有一定复杂度。

l 一般来说,为了提高吞吐量及容错性,服务器应该尽量是无状态的。

l 如果把整个对象信息包装在一个方法调用中传给服务器,那么对象定义可能会相当复杂,或者带来许多冗余工作(后面会逐一分析)。

1.3 示例

这里是一个例子,Application对象包含下层对象Parameter,如下图

注意此图只是用来表示对象间的关系,并不是对象的准确定义。

1.4 难点所在

当添加或删除此类对象时,问题不大。问题是,当用户对对象的下层嵌套对象做了修改以后,应该以何种方式把改变传给服务器,服务器应该以何种方式抽取对象的改变信息,并把改变更新到数据库。

2. 可选解决方案

对于此问题,我们有以下实现方法,下面逐一分析。

2.1 把对对象的操作拆分开

我们可以在用户界面上把对对象的操作拆分开,每一次方法调用只操作对象的一部分,要么是对象的基本信息,要么是其下层对象。此时对象本身只定义基本信息,其下层对象通过调用服务器上的方法取得,如以下伪代码(java风格):

//Parameter的类定义

class Parameter {

private String id;

private String name;

private String description;

//省略了getter和setter方法

}

//Application的类定义

class Application {

private String id;

private String name;

private String description;

private String definition;

//省略了getter和setter方法

}

//服务器上定义的方法,此处略去可能抛出的了异常

………………

public Application[] getApplications();

public void addApplication(Application app);

public void updateApplication(Applicaton app);

public void deleteApplication(Application app);//或者只传id

public Parameter[] getParamForApp(String appId);

public addParamToApp(String appId, Parameter param);

public updateParamForApp(String appId, Parameter param);//也可能不需要传入appId

public deleteParamFromApp(String appId, Parameter param);//

………………

2.1.1 优点

l 逻辑清晰,实现起来已很简单,用户的每个操作,都能很快得到反映,不会出现数据不一致的现象。

2.1.2 缺点

l 服务器接口上定义了大量小粒度的方法。

l 与服务器交互频繁,每次仅传输少量信息。

l 把逻辑上的一个对象人为的拆开,强迫用户做多次操作,不友好。

2.2 删除下级对象然后重新插入

由于用户所关心的仅仅是结果,我们只要保证用户操作成功后,对象的状态是用户所需要的状态就行了,用户不会关心我们是怎样实现的。所以,我们可以把对象定义成符合其逻辑定义,当需要更新对象时,仅对对象基本信息做update操作,对下层对象则采取先删除所有下层对象,然后在根据传入的信息重新生成一遍的方法。如以下伪代码:

//Parameter的类定义

class Parameter {

private String id;

private String name;

private String description;

//省略了getter和setter方法

}

//Application的类定义

class Application {

private String id;

private String name;

private String description;

private String definition;

private Parameter[] params

//省略了getter和setter方法

}

//服务器上定义的方法

………………

public Application[] getApplications();

public void addApplication(Application app);

public void updateApplication(Applicaton app);

public void deleteApplication(Application app);

………………

使用此方法,客户端会暂时维护对象修改后的状态,于服务器端的交互会少些,但用户的操作不能马上得到反映,可也不会出现用户所做的工作被丢掉的现象;比如,系统中已经有一个name为appOne的Application,用户又修改某个别的Application的name属性为appOne, 并对此Application做了许多别的修改(比如添加了许多Parameter),假如业务上不允许有同名的Application存在,那么当用户确定提交其修改时,系统可以给出提示,告知用户不能使用此名字,用户可以按照提示把name属性改为合适的值后再提交,其对Application所做的其它修改不会丢失。

2.2.1 优点

l 保留了对象逻辑上的完整性

l 逻辑清晰,实现简单,对对象的修改和添加对象很相似。

2.2.2 缺点

l 虽然不会出现大量小粒度的方法调用,但可能会在网上传输许多冗余信息。比如,仅修改了某个Application的10个Paramater中的某1个的description属性,实际的修改可能仅有十几个字节的数据量,却要在网上传输整个对象的信息。

l 对数据库进行的密集的操作有可能会大大降低应用的吞吐能力。如果对象类型的属性比较多或对象嵌套层次比较深的话(就是说涉及到数据库里多张表),服务器在操作数据库时会锁住多张表,其它对相关表的访问请求(可能来自其它客户端或其它应用)被阻塞,导致效率大大降低。

l 在特定情况下,此方法可能会导致复杂的处理或干脆不可行,比如,如果应用中有别的地方引用了Parameter对象,数据库中一般会定义外键,此时,更新Parameter的属性是合理的,但对Parameter的删除操作会失败,从而使更新操作失败。

2.3 标记所有相关对象的增、删、改状态

我们可以标记所有相关对象的当前状态,提供一种‘增量式的更新’方式。目前许多开发环境中提供的数据操作控件,一般都有batch模式,可以缓存对数据的操作,然后在真正提交时一次更新到数据库,以PowerBuilder的DataWindow为例,其内部有四个缓冲区(primary,deleted等),并且每行数据都相应的状态记录(new,modified等),我们也可以采用类似的方式。如以下伪代码:

class Parameter {

private String id;

private String name;

private String description;

private int status;//0:None, 1: New; 2: Modified, 3: Deleted etc.

//省略了getter和setter方法

……………………..

/* use this method to get XML format String which indicate update information of this object

@return a XML format String.

*/

public String getChangeInfo() {

}

}

//Application的类定义

class Application {

private String id;

private String name;

private String description;

private String definition;

private Parameter[] params

private Parameter[] deletedParams

private int status;

//省略了getter和setter方法

…………………

/* use this method to get XML format String which indicate update information of this object, here the information include information of subordinate classes.

@return a XML format String.

*/

public String getChangeInfo() {

……………………………….

}

}

//服务器上定义的方法

………………

public Application[] getApplications();

public void addApplication(Application app);

public void updateApplication(String changeInfo);

public void deleteApplication(Application app);

………………

使用此方法,对象的定义会复杂一些,因为对象要能够表明有那些下层对象被删掉啦,以上的例子中的对象定义仅为演示用,并不是最好的定义方式,比如,你也可以定义另外一个数组专门存放被修改过的Parameter等。

注意服务器上updateApplication方法的定义,此时,我们也可以传递的是一个XML格式的字符串,其中指明了对象的更新信息;其实,我们当然也可以传递一个Application对象,这样,我们也不会像第二种方法一样出现不能工作的情况,因为,服务器可以从对象中取得那些下层对象是应该更新的,那些是真正应该删除的。但如果仅仅修改了某一个下层对象的某一个简单属性的话,传递整个对象仍然会带来相当的冗余。比较好的方法是仅传入必须的修改信息,对于没有改动过的下层对象的信息,根本不再网络上传送,这里假设是使用XML来实现的。下面给出一个XML的例子:

<Application status = '2' id = '00001' name = 'appOne' description = '' definition = ''>

<ParamInfo>

<Deleted>

<param id = 'param009'/>

<param id = 'param005'/>

</Deleted>

<Modified>

<param id = 'param003' name = 'ParamThree' description = 'Changed'/>

</Modified>

<Added>

<param id = 'Server control' name = 'Other' description = ''/>

<param id = 'Server control' name = 'Another' description = ''/>

</Added>

<

/ParamInfo>

</Application>

这段XML片断表明,id为‘00001’的Application其基本信息被修改了,因为status为2,所以更新此Application应更新时应更新其基本信息,另外,此Application有两个Parameter对象(其id分别为‘param009’和‘param005’)被删除啦,用户修改了一个Parameter,并另加了两个新的Parameter。

注意到此Application的status所指明的状态是指的其基本信息,如果status为0并不意味着Application对象的下层对象也没改变。戏法人人会变,各有巧妙不同,这里标记信息的定义及XML的schema的定义都有很大的弹性。

2.3.1 优点

l 保留了对象逻辑上的完整性

l 几乎没有冗余信息(这里用‘几乎’是因为XML标记本身是冗余信息,虽然数据量很小)

l 无须多余的数据库操作

l 如果对象定义的再复杂一些(比如定义一个Parameter的原始数据数组),用户甚至可以不用和服务器交互就回到对象原来的状态

l 灵活,弹性大,可扩展性比较强。

2.3.2 缺点

l 实现起来会比较复杂,潜在的犯错误的可能也就比较大。

3. 结论

好了,分析过了,是该做结论的时候了,我们的结论是——没有结论^_^ 所谓模式也是在特定情况下的对于特定问题的解决方法。已有了那么多经典模式,如果我只需要写一个‘Hello, World’程序的话,我还是会不使用模式,就是说,以上各种方法,我们应当根据手上问题的具体情况来决定具体选用那个。

一般来说,现在我们手上的工作,优先级比较高的是要短、平、快,我们需要尽快把东西搞出来,所以在条件允许的情况下,我们应该首选第二种方法。对于此方法的缺点,如果应用的规模大到这真的成了问题的程度的话,我们可以通过要求提高网络带宽及数据库服务器硬件的性能来克服^_^

第三种方法是最优雅的解决方法,如果你是完美主义者,或者想培养自己做科学家的品质的话,你可以优先选用此方法。对于我们普通俗人,只有在使用第二种方法不能接受的情况下才应该使用此方法。

第一种方法打破了对象本身的完整性,可能会惹恼‘上帝’,一般来说,不提倡使用,但某些应用模式下,有可能只能使用这种方式,而且用户也已对这种操作模式习以为常了,比如,用户界面是基于浏览器的瘦客户端,那么这时候也无需犹豫,就用这种方法好啦。

End of this document

[K1]压力要素

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有