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

  • 主题发起人 chinaplate
  • 开始时间
恩,感谢
 
顶一下 不错
 
楼主的工作成果很有价值,是一个很好的三层开发示范,做中大型项目也很值得一试的!但在基于Delphi开发中较好融合这种方式需要的工作量比较大,主要是数据难绑定、代码量大。 开发导航 www.fullit.cn
 
3. 简单地应用XML作为数据缓存

XML是复杂且功能强大的。在.net/j2ee项目中,都借助XML实现强大的功能。诸如DTD,
XMLSchema,DOM,SAX,XSLT,XPATH等名词就够令人眼花缭乱的。但我从一开始就小看它了,
在我的c#项目中,我直接把自定义的容器类序列化为XML,就作为系统的工程文件了。
那时,XML是透明的,我根本不关心它的存在。

在此物业项目中,XML也是被大材小用,仅仅作为一个缓存,换换句话说,它就是作为
一个存数据的筐子,这个筐子在各个层次之间传递数据,起到承上启下的作用。有了XML
数据,在我的UI层,几乎看不到DataSet的影子,我一直不喜欢绑定机制,现在连DataSet
也不用了。

把数据放入XML这个容器中以后,各层次之间的功能将非常清晰。从存储层中得到数据
放入XML中,交由业务层进行整理,再传到界面层中按一定的方式显示。反过来,也一
样。这样的方式对处理批量的数据提交时,尤为方便。如本系统的大量的抄表记录,收费
单等。

在业务类的基类,包含一个TXMLDocument对象FXMLData,就是说,每个业务类对象,除了
放在Query中以外,还放在了XML容器中。

每个具体的业务类在构造函数中,都将xml容器的初始结构建立好
node:=FXMLData.AddChild('tables');
subNode:=node.AddChild('house');
subnode.AddChild('fields');
subNode.AddChild('rows');
通过两个成员函数实现数据从xml到query的转化
function LoadFromCurRow():Integer;override;
function SaveToCurRow():Integer;override;

如收费单的录入
1。用户若要收水电费,则从抄表记录表中得到需要收费的水电表码等细节;
2。用户若要手物业费、卫生费等,则从收费设置表中根据各种情况计算收费的相应金额;
3。把各种收费明细插入到收费单业务类的rows节点中;
4。业务类向存储类提交请求,并把xml数据传过去,存储类遍历所有的rows节点,插入DB中。
这样做的好处,就是FORM中可以随意的设计来增加收费单的明细,而不必一直考虑着什么时候
Query进行Post,什么时候进行Update了。

由上面的说明和前一节的逻辑分层,我的观点是:
学要学难的,用要用简单的。
用简单的实现作为撬杆,才能撬开那些复杂的,庞大的技术难关。

(未完)
 
to yyblake:
正如我上面刚提到的,我一直不喜欢用绑定,经过这个项目后,在我的FORM中,甚至几乎是
看不到DataSet的影子。(不是没有,比如我还用dbgrid进行列表)
 
delphi面向对象是没错的。用delphi分层和java/.net是有区别的。java和.net都能有反向影射机制。什么逻辑层,视图曾等等能够在不改动任何代码只简单的改配置文件就可以。
delphi毕竟落后一代了。没有办法做到java和.net这一点。
 
to jxyghm:

是的,我也感觉到了Delphi用这样的分层的局限性。只是因为一些原因,我在
一段时间内要同时使用delphi,c#,java,而我不想在切换语言时有太大的思路
跳跃,所以我尽量的把delphi,c#,java看作是同样的东西,同等使用。

在做这个项目时,迁就了Delphi很多东西,没法向c#/java一样表达的自然。
 
呵呵,你的数据持久层有点落后哦,可以参考 Macrobject DObject:
http://www.macrobject.com/en/dobject/index.htm
http://www.macrobject.com/cn/dobject/index.htm
这才叫真正的持久层啊:)

呵呵,另外:
inc 相当于宏(替换/扩展)啊,只不过 Pascal 的 inc 强制要有另一个文件来实现罢了。
所以通过 inc 来分别实现编译控制(比如编译成 dll/exe )实在是一件非常简单的事啊。

Delphi 其实也很强大,好好发掘发掘吧:)
 
写的很好,学习:)
 
4. 统领全局的Singleton对象
GOF的设计模式看了N遍,忘了N遍,大多数东西,都因为自己的内力不够只记住了名字。
但忘不了的就是这个最简单的Singleton模式了:)

系统中一般都会有一些类似全局变量的东西,我以前就把这些全局变量或公共函数都定义
在一个单元文件中.自从知道了Singleton之后,我就用它来代替这个单元文件了。(或许
有人会认为这个单元文件完全可以代替Singleton,我认为也对,见仁见智吧)

以前看过几个用Delhi实现的Singleton模式,当时好象没弄明白,或者感到他们实现的
复杂,我就按自己的理解实现了。Delphi最大的缺憾就是没有static data member,我只好
用了一点非OO的东西,在implemetation中定义一个不属于类的变量来模拟static。
代码大致如下

--------------------------------------------------------------
type
TPM = class(TObject)
public
//程序名称
AppName:string;
Version:string;

//对话框标题
BoxTitle:string;

//数据库类型
DbType:string;

//数据库连接对象(并不在此类中实例化)
ConnObj:TAdoConnection;

Login:TLogin;

private
constructor Create;
public
destructor Destroy;override;
class function GetSelf: TPM;

procedure Release();
end;

implementation

var
u_self:TPM;


class function TPM.GetSelf():TPM;
begin
if u_self=nil then u_self:=TPM.Create;
Result:=u_self;
end;

constructor TPM.Create;
begin
Login:=TLogin.Create();
end;

destructor TPM.Destroy;
begin
FreeAndNil(FLogin);
end;

procedure TPM.Release();
begin
FreeAndNil(u_self);
end;
--------------------------------------------------------------------------
TPM.ConnObj在系统入口处指向一个已经实例化并成功连接的TAdoConnection对象。
在任何想使用数据连接,版本号等“全局量”的地方,只需要简单的引用
TPM.ConnObj,TPM.Version。在系统登录窗口将用户的登录名,权限,登录时间赋值到
TPM.Login对象中,会使得基于用户、角色的处理变的清晰简单。

TPM含义为Program Manager,它作为一个Singleton对象,在任何需要的时候都会已经
实例化了,并且该类只有一个对象在内存中。事实上,我的系统还用它完全接管了
messageBox的显示,异常的处理。它就象一个领导一样,背着手,在系统的各个模块
之间走来走去。

(未完)
 
to dreamfly1024,

嘿嘿,是的。有人批评我的这个项目是为分层而分层,很坦白地,我个人认为也是。
因为我现在只是强烈的感到要分层,必须要分层,但我如何实现分层,从流行技术上讲,
我还是很空白的:)
这个项目的分层的实现很大程度上是,闭门造车,自己凑出来的。或许这个项目会成为
我的反面教材。(不过从用户的角度来讲,它是成功的,因为我的需求做的足够细,功能
实现的足够好)

所以,我现在正研究hibernate,spring的东东,希望能有些突破。
 
把从别的帖子的回复帖你这儿,呵呵,也很贴切哦:)

========================================
热闹:)

我不得不说几句:
1、分层这个东西的来源
分层首先来源于西方软件工程的进展,以及分布/发布的需求。
另外,分层也是一种模块化手段,是纵切的一种扩展。
2、分层的好处
在软件工程很成熟的情况下,分层起到非常好的分解任务的作用。
另外,西方的需求分析很到位,所以其需求更改情况更少,所以分层对他们来说几乎没有什么副作用。
3、分层的坏处
分层的坏处在于增加软件的广度复杂度,如果需求分析不到位,经常更改,则分层明显要增加成本和复杂度。
分层在小项目中的滥用,也是要避免的。
4、分层的替代方案
分层仅仅是众多抽象方法的一种,完全可以用其他各种替代方法达到相同的目标,比如模块化(呵呵,听起来挺土?)等。

楼上谈到 O/R Mapping 了,呵呵,这个东西是几乎所有分层中最为成熟的层了。
请参见:
http://www.macrobject.com/en/dobject/index.htm
http://www.macrobject.com/cn/dobject/index.htm
 
楼上的兄弟,想问一下,o/r mapping如何应用到分层中?我就是对这个不太了解,也没有看到这方面的书籍,以前写过三层的不过用的是stock.现在想用dcom,感觉又麻烦.有时感觉有没有写三层的必要.
 
同意dreamfly1024,的说法
如果一个程序一百个人在写,坚持支持分层
如果二、三个人在写,分层是自找麻烦
程序的架构好才好维护,并不是分层了就好维护了
 
打击你一下:
通常“编译开关”用来控制一下不同的版本(修改.inc的默认值即可),的确简单有效。
但象你文中所说,把一个Exe文件编译成一个DLL,不知道要定义多少“编译开关”的默认值,这将使你的程序变得非常不可读,不信你数一下它的.inc文件中的定义开关个数,然后全文搜索一下,数量一定吓死你,代码跳来跳去,工程文件就跳过一大段,单元里面的引用又跳过一大段,可读性可想而知。(估计是练习使用“编译开关”的,呵呵)

正确的方法是:
把你要写在DLL的部分独立出来,在Exe与DLL中都引用即可。
 
学习了。
 
to 黄耀彰,
那些程序是我以前一个同事写的,代码中确实存在很多编译开关。
我没看明白他的程序的思路,就够打击我的了:)但我的感觉,他的程序的确精彩。
 
同意 黄耀彰:
编译开关和宏(或 inc)一样,尽量避免滥用,要用在恰当好处的地方,
如果用的到处都是,确实有违好的编程风格。
 

Similar threads

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