叶子的家

~●    ~●  ~●          ~●   ~●~●                           ○
    离成功还很远,距离长着叻,Fighting!
posts - 38, comments - 602, trackbacks - 17, articles - 1
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

我在最近的一个项目(WinForm)中遇到一个这样的问题,下面对问题陈述:
        某工资计算模块的界面很复杂,8个DataGrid分别和8个DataSet绑定,还有一大堆的TextBox关联另外两个DataSet里面的数据。更新界面的某一地方的数据,其他数据源相应的地方会变化。不谈论对需求分析到设计的好坏,在这样一个复杂的UI下面,处理数据同步问题令我好担忧。在最近的测试过程中,发生莫名奇妙的错误,找不到错误源,简直郁闷至死!主要是在某些情况下,数据变得不同步了,根本经不起“猴子测试”(在界面上乱点),悲哀至此,下定决心把关键部分重写。
        在重写过程中,我就发现了一个重要的问题:控制界面的逻辑和处理业务数据的逻辑应各自独立,就算界面显示数据有错误,但实际的数据仍是平衡的。
        举例:在DataGrid中,一个CellValue从10 -》100,差值(新值和旧值相减)是90。我们要根据这个差值去处理其他数据的同步。
        首先,问题是我们如何取出这个差值,开始我的做法是:DataGrid提供一个事件:ValidatingEditor。这个事件在输入的新值到写入数据源之前提供一个验证,在这里我们可以用EventArgs里面的新值和当前的值进行比较,得出差值。如果差值符合要求(业务逻辑),则把这个差值更新到各个相应数据源中去来保持数据同步。如果差值不符合要求,则提示错误信息,并还原原值。咋一看,什么问题也没有,逻辑也清晰,大家也觉得是吧?
        在测试过程中,问题就出现了,往往是输入一个新值后,“其他数据源”也同步了,但是回头一看,旧值还是旧值,新值并没有填充到“本数据源”中去,why?找了很长时间,虽然我们最终找出问题出在控件本身上面,但是如何从根本上杜绝这类问题的发生呢?
        就上面这个例子来说,我们找差值去同步数据的时候,在是写在ValidatingEditor这个事件上面的。如果在这个事件的处理过程中发生了一些我们异想不到的异常(可能是控件本身引发的或者是我们自己引发的),就会造成数据出错。所以进行了以下改造:
        考虑到如果ValidatingEditor验证成功,必然会引发一个CellValueChanged事件,这里可以肯定数据源是被改变的了。所以,在ValidatingEditor只负责数据验证和提示错误信息,验证不成功CellValueChanged不会被引发,如果成功,在事件CellValueChanged得到差值去同步各个数据源。注意:取差值时,尽量不要获取控件提供的值(上面是从EventArgs去取的),而直接数据源本身去取,这里就一定保证了数据的平衡性。我是这样得到差值的(DataSet某Row):

decimal v = (decimal)pdRow["PayMoney", DataRowVersion.Proposed] - (decimal)pdRow["PayMoney", DataRowVersion.Current];

这里就算控件本身发生问题而导致数据显示错误的话,但我们实际上的数据也是正确的(平衡)。只要在同步完毕之后,调用:

dataGridView.UpdateCurrentRow();

界面和数据源保持一致了。上面可能是特例,但是原则我认为应该这样做。希望对各位有启发。~ ^^

Feedback

#1楼    回复  引用  查看    

2005-06-29 16:42 by 小陆      
界面控件之间最好不要有业务联系, 各个控件应该通过业务模块间接产生联系.

#2楼 [楼主]   回复  引用  查看    

2005-06-29 20:42 by 绿叶      
我这里说只是数据同步上的处理,业务逻辑是分开来的。但是如果规定死界面层不能有任何业务逻辑的话,是不好的。以前在做Java的时候,那个模式死得让人呕血。界面层是可以接受些简单得逻辑得,规定得太死反而不利。

#3楼    回复  引用  查看    

2005-06-29 20:56 by 补丁      
同意掺杂简单逻辑
非要把逻辑全封装到业务逻辑层有时候徒然增加了复杂度,也就变相增加了维护难度

#4楼    回复  引用  查看    

2005-06-30 09:43 by 懒狮      
同意,其实业务逻辑与界面层的划分,个人理解可能有所不同,但本人以前做项目时,遵循的原则就是简单逻辑,例如数据验证、确认等应该划分到界面层,不规入业务逻辑,业务逻辑专指专业业务。

#5楼    回复  引用  查看    

2005-06-30 11:16 by 小陆      
参杂了具体界面控件的代码, 一般都是不可复用的. 将业务逻辑和界面混杂在一起的结果就是, 这些业务代码要在项目中不断复制, 然后再稍加修改. 一旦产生变更, 是很痛苦的.
界面必须和业务分离的原因在于, 界面的需求变化程度是大于业务逻辑的, 并且界面不可复用, 难以测试.

#6楼 [楼主]   回复  引用  查看    

2005-07-01 01:48 by 绿叶      
to 小陆:
你说的是对的,业务逻辑和界面糅合在一起确实是乱78糟,但是有时候是可以牺牲这方面的一点,简单的逻辑不必要分离得太过清楚。你说界面改变后,修改是很痛苦得,但是往往在如果太注重层次化,你是要花更多得维护作为代价的。

#7楼    回复  引用    

2005-08-19 10:45 by 月吻长河 [未注册用户]
MVC设计模式就是很好的方案。

#8楼    回复  引用    

2005-09-09 16:54 by stdafx [未注册用户]
错误, 这种情况下 MVC 不是最好的方案, 而是 PAC.

#9楼    回复  引用    

2006-06-27 11:27 by hu [未注册用户]
我们现在的项目 就是要实现 界面和业务分离
还专门成立了GUI组
我从一开始就反对这么作
界面怎么可能跟业务分离呢?
根本做不到吗?
天方夜谈

#10楼    回复  引用    

2006-06-27 11:30 by hu [未注册用户]
还有MVC
不说了

#11楼    回复  引用    

2006-08-15 15:15 by nicolas185@gmail.com [未注册用户]
MVP

#12楼    回复  引用    

2006-08-17 15:35 by 阿潘 [未注册用户]
支持mvp,我也用,简单逻辑都放在p了

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
 
另存  打印