完成了一个物业管理软件,想谈谈自己的一点体会。1.对delphi的看法 2.所谓的三层 3. 简单地应用XML作为数据缓存 4.统领全局的Singleton对象

  • 主题发起人 chinaplate
  • 开始时间
5.接管所有的异常

最初接触Exception也是在Delphi中,那时很不明白,一个函数将它的执行完成情况通过
返回值传上来就OK了(象众多的WINAPI函数一样),干嘛还引入这个异常机制呢?
当时的异常的使用也仅仅限于文件的读写,数据库的提交等。事实上,等我开始用JAVA时,
因为强制使用异常,才体会到异常的用处。

使用异常或使用函数返回值来表示函数的完成情况又是面向对象和面向过程的区别之一。

使用异常的好处,就是被调函数执行出了一点问题时,只管抛出相应异常,不关心谁来处理,
如何处理这个异常;而函数的调用者,扑捉到执行用的异常时,自己如果能处理,则处理,
将其消化,否则,继续把异常向上抛。

也是为了调试程序和程序交付后的维护的需要,我想让异常能具有下面的功能:
1.记录异常发生的时间;
2.记录最初抛出异常的类名及函数名,以及当时程序环境的描述(主要是象sql语句一样的敏感语句);
3.发生异常时的函数调用堆栈;
4.发生异常后,能将异常的详细信息(包括上面3点)记录DB或某个日志文件中,通过记录的日志,
我可以在系统交付后能跟踪程序执行的出错情况,能进行相应的错误修复。

不过,很遗憾,因为时间关系,功能4我并没有实现。

我把异常按严重级别分为几类,异常被扑获后,进行了响应的处理。
我最初的设计是写一个自定义的抽象异常类继承自Exception类,然后派生出每个“严重级别”
的异常类,其它实际的异常都从这里继承,做到象JAVA异常一样的见名知意。最后,考虑了一
下本系统规模和时间,就只写了一个类,“严重级别”就作为了这个类的一个成员变量。

程序实现大致如下
-----------------------------------------------------------------------------
type
TExceptLevel=(elMsg,elIgnore,elCanTry,elJustAlarm,elSerious);

TExceptionEx=class(Exception)
protected
FLevel: TExceptLevel;
FVendor: string;
FNum: string; //异常号 或 异常名
FInfo: string;
FTime: TDateTime;
FCallStacks: TStrings;
procedure SetInfo(const Value: string);
procedure SetLevel(const Value: TExceptLevel);
procedure SetNum(const Value: string);
procedure SetTime(const Value: TDateTime);
procedure SetVendor(const Value: string);
public
property Num:string read FNum write SetNum; //异常号 或 异常名
property Level:TExceptLevel read FLevel write SetLevel; //异常级别
property Vendor:string read FVendor write SetVendor; //异常产生者
property Time:TDateTime read FTime write SetTime; //产生异常的时间
property Info:string read FInfo write SetInfo; //异常信息
property CallStacks:TStrings read FCallStacks ; //异常处代码的详细信息,以及调用路径
public

Constructor Create(Aex:Exception;ANum:string;ALevel:TExceptLevel;AVendor:string;Ainfo:string;ACallStack:string);
Destructor Destroy();override;

procedure AddCallStacks(funInfo:string); virtual;

end;

implementation


procedure TExceptionEx.AddCallStacks(funInfo: string);
begin
Self.FCallStacks.Add(funInfo);
end;

constructor TExceptionEx.Create(Aex: Exception; ANum: string;ALevel: TExceptLevel; AVendor, Ainfo, ACallStack: string);
begin
Self.HelpContext:=Aex.HelpContext;
Self.Message:=Aex.Message;

Self.FNum:=ANum;
Self.FLevel:=ALevel;
Self.FVendor:=AVendor;
if Ainfo='' then Self.FInfo:=Aex.Message
else Self.FInfo:=Ainfo;
Self.FTime:=Now;
Self.FCallStacks:=TStringList.Create();
Self.FCallStacks.Clear();
Self.FCallStacks.Add(ACallStack);

//TODO:可在此出将异常记录到日志文件中

end;

destructor TExceptionEx.Destroy;
begin

FreeAndNil(FCallStacks);
inherited;
end;

...

-----------------------------------------------------------------------
几乎在所有可能出现异常的代码中,都加上异常不扑获代码

try
{some codes}
except
on ex:TExceptionEx do begin
ex.AddCallStacks('TAcHouse.SelectHouseMeter()'); //填加调用函数名称
raise ;
end;

on ex:Exception do begin
raise TExceptionEx.Create(ex,'ex_unknown',elSerious,'TacHouse.SelectHouseMeter','无法得到码表信息','TacHouse.SelectHouseMeter()');
end;
end;

在最顶的界面层,根据情况显示异常
try
{some codes}
except
on ex:TExceptionEx do begin
TPM.GetSelf().ShowMessage(ex);
end;
end;

//ShowMessage是自定义的对话框,可以显示我的异常,用户一般只看到简单的提示信息,通过点击
“详细”按钮,能看到异常的所有详细信息。

现在看来,这个类写的有点罗嗦,有些地方应该简化一些。
(未完)
 
delphi也是面向对象的语言,所以编写它的类也是很容易实现的
 
dreamfly
3、分层的坏处
分层的坏处在于增加软件的广度复杂度,如果需求分析不到位,经常更改,则分层明显要增加成本和复杂度。
------------------------------------------
似乎不太对。分层恰好是把改动量做到最小。一般只改业务逻辑层就可以了。不分层是全部要改。
 
好帖子,顶起来
 
dreamfly
3、分层的坏处
分层的坏处在于增加软件的广度复杂度,如果需求分析不到位,经常更改,则分层明显要增加成本和复杂度。
------------------------------------------
似乎不太对。分层恰好是把改动量做到最小。一般只改业务逻辑层就可以了。不分层是全部要改。
不要听人家忽悠,需求变动产生的修改,通常首先反映在界面上,多数情况业务逻辑和界面同时都要改,你说是复杂了还是简单了?
 
学习,我再顶
 
Tassadar.对于改动业务逻辑而不改动界面我是有有体会的。不是别人忽悠我。改界面可以不改业务逻辑。该业务逻辑又可以不改界面。当然全需要改的时候不是没有。但是毕竟比不分层改起来清晰
 
[:D]
我是DELPHI的新手`
看你们吵的这么热闹`
我也凑哈``
却跟不上你们的话题`[:(]
 
6. OO与DELPHI

为什么要OO呢?我的回答是:为什么不00呢?
为什么为了技术而技术呢?我的回答同样是:为什么不呢?

当对用户的需求调研完毕,呈现在设计人员面前的是一系列功能的集合。
然后就需要决定这些功能由谁来实现,如何实现。也就是说,如何设计系统
中的涉及的对象,及其方法。

OO的设计有两条主线。纵线叫inheritation,即继承体系。横线叫delegation,
即代理体系。整个系统就是这两条主线的纵横交织。

从纵线上讲,将功能分配在父类或子类中,父子配合来完成一定的功能。父类
是“接口”,一般定义抽象的方法或部分实现的方法,子类具体实现这些抽象
的方法或扩展父类的方法。即刘艺所引用的“上德无为,不察其用;下德为之,
其用不休”。使用者Client只通过父类的引用来操作这个继承体系,多态性表现
在Client中。在Client基本不变的情况下,很容易的扩充整个继承体系。

从横线上讲,一个对象的功能应尽量简单,稍复杂一点的部分功能可以代理给
其它对象类实现。换句话说,你想给某人一封信,你肯定不愿意亲自去送,所以
你把这个功能代理给邮局。“代理”实现了功能的集中,你集中精力写信,邮局
集中精力送信。代理的在程序中的一个表现就是分层,UI集中精力于描述同用户
打交道的方式,而将具体的功能实现代理给业务层。分层肯定带来一定的代码量,
但当使用业务层的UI对象越来越多后,代码量及对其的维护工作量将比设计一个
庞大臃肿的UI对象来说要少的多。即使不是这样,单凭“集中精力”这四个字,
也体现了分层的优势,付出的工作量代价也是值得的,哪怕是一个人写程序。

所有的功能就这样纵横得分配给各个对象。对象被实例化后,立体的生活在内存中,
对象之间相互配合,共同完成功能。内存中的对象是有生命的,它们相互尊重,
各司其职,内存中就应该是胡哥所倡导的和谐社会的样板。

大多数的设计模式都是由这一纵一横交织而成。目前,论坛的舆论好象集中讨伐
模式及OO的滥用上,我认为,只要高悬用户需求这个原则,滥用一点也无妨,下次
改正也就是了。

回到DELPHI上来,DELPHI号称VB杀手,DELHI设计了一些东西,使初学者可以很容易
的象使用VB一样使用DELPHI。其实熟悉了OO的一些基本设计,再理解DELPHI,可能
就会更清楚了。如abstract,dymamic,virtual,overload,inherited,class function,
这样的语言元素也就会应用自如了。

Delphi可以说是OO的超集,但在OO阵营,DELPHI7明显落伍了。(我未用过DELPHI2005)
我在使用中,有下面的注意事项:
1.删除每个新的FORM中interface中自动定义的Form变量,每个Form在使用时定义和
初始化;
2.同样删除在.dpr文件中的不需要的Form的定义及实例化语句;
3.变量和函数应该都定义在类中;
4.一个单元文件中定义一个类;
5.谁将一个对象实例化出来,谁就必须负责销毁这个对象,反过来说,不能销毁一个
不是自己实例化出来的对象;
6.具体到方法的实现上,一个原则就是,根据方法的命名,是自己的工作就要干好,不
是自己的一定不要染指;
7.D7没有static data member;
8...(希望朋友们补充D7中用OO的注意事项)。
 
用了一年多delphi,继续学习中
 
我是应届生,好多东西还不明白,所以你说的我都还不够明白,
大哥,你可不可以写一篇面向大众的,相对于我们刚起步的人的学习文章,你的心得之类的啊?
谢谢了,我继续关注你。
 
好贴! 顶
 
DELPHI 就是好呀`
I LIKE IT!
 
我学习,好,顶
 
大富翁里就是热闹,像个集市,什么都有,好,继续
 
顶.有收获
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
顶部