请大家关注,提高能力的必经之途!! 让我们动手开始实际的来接触设计吧!!!(0分)

  • 主题发起人 主题发起人 djflying
  • 开始时间 开始时间
D

djflying

Unregistered / Unconfirmed
GUEST, unregistred user!
大家都在讨论一些概念的问题,我拿一个实际的事情作例子大家来帮我出出主意,讨论一下!
这是一个非常普通的常见的用户登陆过程,在这个过程里会用到两个窗口与用户打交道,
一个是用户登陆窗口(loginForm),一个系统管理员用来管理用户资料的(adminForm),另有一个类TUserManage管理用户
我想这么来看待整个过程:TUserManage看成一个如同openfiledialog的东东,他封装整个用户
登陆过程,用一个execute方法提供一个完整的用户登陆过程,而不是平常那样由几个窗口和一系列
过程来构成一个分散的用户登陆过程,这样避免以后整合代码时,其他人也要了解整个用户登陆过程
中的系列关系。其他程序员只需面对经过了一个登陆过程后的用户信息进行编码,
而无须了解从哪个窗口或什么地方可以返回得到需要的用户信息的,整合代码的时候只需运行一个登陆过程
然后用得到的用户信息进行他们的处理。
具体处理有这么一个问题:
有一些与数据库打交道的方法,如GetUserInfo、AddUser之类的方法,我是将他看成
TUserManage所拥有的能力还是将他看成LoginForm具有的能力?也就是说是Tusermanage.adduser还是
loginForm.adduser.
一般应把adduser看成TUserManage的方法,因为loginForm是Tusermanage用来与用
户打交道的工具,我想他不应具有通用用户登陆过程中的具体方法,他只应具有得到用户的输入并发送一个添加
用户的请求的能力,具体添加用户的过程是Tusermanage的事情.loginform应调用TUsermanage.adduser
需要把adduser方法设为公共的,但添加用户纯粹是一个用户管理事务的内部处理,其他模块都不需用到,因此
他不应该作为Tusermanage的一个向外提供的服务,也就是说adduser应该Tusermanage的一个内部使用的方法,应
设为private或protected,怎么解决这个矛盾?
这个例子过程相当简单,就算不考虑这么些,就作那么几个窗口,然后这个ok钮里写一些处理,那个cancel钮里写一些
处理都可以完成任务,但希望大家进行一些程序结构设计上的考虑,和如何设计清楚的程序执行路径和形象化思考程序
模式的方法.这个例子很小,比较容易归纳和总结一些,它反映的程序设计理论可能只是一点,但我想一点点在实际程序编制
中积累就能真正的掌握设计模式/软件方法的思想和怎么去应用它们.
小弟在这里抛砖引玉,希望大家帮我计划计划,任何各种各样的方案和想法都行,也欢迎大家出题目来讨论!!
也可探讨一些学习的方法啊!
 
[brown]但添加用户纯粹是一个用户管理事务的内部处理,其他模块都不需用到,因此
他不应该作为Tusermanage的一个向外提供的服务,也就是说adduser应该Tusermanage的一个内部使用的方法,应
设为private或protected[/brown]
为什么要这样呢?我把datamodule看作一个中间层,调用中间层提供的服务不是很正常的吗
Delphi的VCL封装并不是完全面向对象的,Delphi开发人员指南上的数据库篇有详细的例子
 
数据库编程的东西做得不多,简单地说说我的想法:
根据 OO 的观点,loginForm, adminForm 都应该是 TUser 内部 protected 的东西,
不对外公布的,可以由 Login/Manage 方法来调用,TUser 可以有 UserName, Password
两个 read/write 属性,一个 UserType readonly property,Login 方法可以由任何未
知用户调用,用户登陆完成以后,给出 UserType 的值, Manager 和其他的方法则要在
调用前检查 UserType,可以设一个 TUser 的全局对象,当程序中需要检查用户权限
的时候检查 UserType

 
940801不简单啊,几句话把我说的大堆东西说的清清楚楚。
我想的也是那样,问题的重心不在于具体数据库怎么操作或窗口怎么做,而在于定义功能的提供路径
和定义对象的范围。
可是我所提到的问题还没有明确解决,就是adduser这个功能代码块是属于Tuser还是属于loginform呢?
虽然我们把loginForm和manageForm看成TUser的内部相关元素,可他仍是一个独立的类型,在delphi里
好像不能设置TloginForm为TUser的友元,因此LoginForm不能象一个Tuser的方法那样直接使用TUser的其他
内部方法。是否就直接将TUser的内部方法公开呢?那样的话除了loginForm可以看到
的话,其他所有人的看到了,好像不太好吧。怎么解决这个问题呢?或者避免这个问题呢?
另外:940801,你的《向天再借五百年》找到啦? 能不能给我也发一份啊,呵呵!
djflying@sina.com
 
Form 虽然在 Delphi 的可视化设计中地位很重要,但在 OO 中它也和别的对象没什么区别
TLoginForm 只是 TUser 为了实现登陆人机界面的一种选择而已,它只是 TUser 的一个内
部的东西,外面的对象根本不知道有这个 Form,它们只需调用 Login 方法就可以了,
TUser 的 Login 方法在创建并显示 TLoginForm,TLoginForm 不需要知道谁调用的自己,
它只需和用户交互,取得用户输入的 username, password,它不需要知道如何检查
UserName, password 是否正确,可以由 TUser 给它传递一个检查函数,它调用就可以了
其实你的问题的关键还是你做 Delphi 做面向过程的编程太多了,以致于影响到了你对
TForm 的认识,面向对象的时候,不要把 TForm 看得太重要,它和 TEdit 一样,人机交互
用的而已
type
TCheckFuction = function(const UserName: string;
const Password: string): boolean of Object;
TLoginForm = class(TForm)
FUserName: string;
FPassword: string;
.....
property UserName: string read FUserName;
property Password: string read FPassword;
property CheckFunction: TCheckFunction read FCheckFunction write FCheckFunction;
end;

TUser = class
FUserName: string;
FPassword: string;
......
end;

procedure TUser.Login;
var
LoginForm: TLoginForm
begin
LoginForm:= TLoginForm.Create(Self);
try
LoginForm.FCheckFunction:= CheckUser;
if LoginForm.ShowModal = mrOK then
begin
FUserName:= LoginForm.UserName;
FPassword:= LoginForm.Password;

end;
finally
LoginForm.Free;
end;
end;

function TUser.CheckUser(const UserName, password: string);
begin
....
end;

btw: 我就是看了你的留言后才过来看看我能不能帮你什么忙的,呵呵,[:D]
 
LoginForm 也可以这样定义
UserName: string read GetUerName;
function GetUserName: string
begin
Result:= edtUserName.Text;
end;

这样更简练
 
此外我对你的建议是多读 VCL 源码,多写一些控件,OOP 的能力就会有很大的提高
随之也可以提高 OOD 的能力
 
Thanks!多谢940801的建议!!
我的想法也差不多,可是我过于强调“有两个窗口了“,换一种方式来述说问题吧,有个
大的对象(比如一个公司),它拥有真正的资源(比如功能代码或调度安排的能力),有一个小的对象(比如客户
服务部),它负责一些工作(比如和客户打交道),现在有一个客户来做生意,公司开始运转,
公司命令客户部开始跟客户接触,客户部在工作的过程中需要一些比如将客户入档的事务,
客户部没有直接填写档案文件的权利,它只能发送一个请求给公司让公司调度(所以它拥有
一个property CheckFunction),而公司不是任意人的填写档案的请求都接受执行的,只有公司内部的相关部门才有请求这个操作的能力(
所以它给客户部分配资源LoginForm.FCheckFunction:= CheckUser,可以执行客户部的请求)。
940801您看这样来理解行不行?
//附:
//在以前的编程过程中,往往是我写完大量代码之后,却不能说清楚为什么要这么写,这么写的好处到底
//在哪里,只是参照一些类的编写模式进行模仿,有时候是生搬硬套,写完之后用起来觉得不好临时再改
//,效率反而不高。我想大家可能都有这种经历吧,尽管这一步是提高水平的有效方法,但我认为模仿和接触
//只是接近一个领域并熟悉其中的问题的方法,而要能够掌握这个领域还需要归纳和分析其中的道理,做到有前瞻
//力,能够走最有效率的路去达到目标。
//经过了几个月的困惑,慢慢的有了一些对于程序设计方面的思考,但缺乏实际应用的经验,在此小弟把我
//心中想到的全部都写了出来,希望大虾们给予指点,随便怎么说都行,只要各位大虾开口就行。
 
数据库编程我做的很少,提不出什么好的意见,
但我觉得你又有点走向反面了,对
于 LoginForm,我们封装一个 CheckFunction,提高它的可移植性
但你做的是程序,不是控件,既然 TUser 可以全局共享,
就没必要对于别的模块,每个都配一个 CheckFuncton 了。
设计好程序中各个对象需要处理的数据和可以完成的操作后,对象之间就可以
互相协作了
 
登陆就登陆吗 搞的这么隆重 又不是诺曼底登陆
 
不错,940801讲的很好,正是我要的!谢了~
希望多一些像他这样的人。不过大富翁确实很好 !
 
啊,美好的假期,足睡了2天整的,嗯啊〉。。
用户登陆只是一个例子,希望用一些实际的例子可以实在的体会设计
我认为这个例子的重点在于功能的归属以及一种资源-请求的的关系。实际工作中很难一下
便设计好各个类的基本框架,如果经验不丰富的话,经常到后面开始编码了又来修改以前的
类结构,并不是不能实现后期的功能,而是
 
觉得以前的类的结构和类的框架不是很适合后面的需求,所以加以稍稍修改.当这种问题多了
以后,会带来整个类结构和框架的逻辑意义不再清晰,因而后期的编码越来越慢,大家权衡利弊
之后,要么做一次大的改动,重新整理程序框架,使之清晰化并更加符合后期的需求,要么让
程序员继续往下编码,只不过花费更多的精力去理清先前的程序逻辑结构.这两种方法的本质
在于让程序有一个统一的理解模式,程序的实际代码有多繁复并不是很重要,关键在于它的运行
模式是否清晰,即使类的接口有了变化,只要它的基本模式没变,仍然能用统一形象化的语言描述的话,那么
它的维护成本也不会很高.
 
界面和逻辑是要分开的.TFORM是属于界面部分的.
 
-_-!
要是我的话会这么做。
type
FLoginMethod= function PermitPass(UserName, PassWord: string): Boolean of Object;
登陆窗口对象声明一个这个类型的变量。
具体的实现方法由TUser来实现,创建登陆窗口对象的时候指定用哪个方法来验证身份。
 
好久好久没来大富翁了!最近作项目赶的特别紧。不过总算有了一些闲暇了。
时间过的飞快,一溜眼就过了大半年,在这段时间里我又转到使用java开发项目。接触了java
后,有一种顿醒的感觉。不同的语言千差万别,各自应用于不同的环境和领域,为各种不同的目标
服务,无法简单说他们的好怀。然而java之于我看来,在帮助一个程序员培养面向对象的程序思想
和掌握一些设计模式,有着极大的帮助。因为我从dos下c走到vc、pb、delphi、vb,然后刚好在一个
开始考虑程序设计方法和软件开发过程的时候接触到了java,感觉特别明显,java的设计结构明显的
非常清楚,他天生就面向对象,天生就包含了许多好的设计模式,而且整个框架全部向你开放,可以
学到很多好东东。还有一种语言smarttalk,好像也是一种比较好的语言,因为java得设计也参照了它
可惜我没用过。以前有许多程序设计的困惑在翻看java类库的源代码时得到了解答,因此现在回过头
来看原来的问题,有一种前所未有的清楚感。
说了许多废话,我也不是热衷于评论语言的好坏。抒发一些感想罢了。
回到这个贴子的正题。当时我还不能清晰的归纳我遇到了什么问题。其实问题的实质在于设计类的使用
安全性。假定adduser/deleteUser功能由TUserManage最终提供,用户管理界面层将使用TUserManage来完
成用户的添加用户的要求,但是我不希望addUser/deleteUser功能对其他也需使用TUserManage类的模块开
放(譬如项目组由许多人共同开发,如果addUser功能开放的话,其他模块的程序员就有可能自己制作后门
来访问用户数据库,当然这样想好像太妨人了一点,但实际上这种风险是存在的,还有许多类似的情况为了
加强程序的健壮性,避免可能的程序员的误操作,需要对类进行设计以在编码、编译阶段就杜绝可能的错误发生)

解决的办法之一:把所有的addUser之类的操作放到另外一个类TOperations里面,将之作为一个素材类,这个类
不发布出去,然后针对不同的模块发布别的不同的类,这些类包装了素材类,但针对不同的模块开放不同的功能。
办法之二:在TUserManage里作检查,也就是使TUserManage具有判断谁有权使用资源的能力,不过这样的话,
TUserManage就与申请资源的类关联了,使其耦合度增加,不大好。
不知各位有没有碰到这种情形,大家都出来谈一谈解决的方案吧!
还有,大家也讨论一下各自遇到的与控制类使用安全沾边的情形和模式。我目前所知道的几种带有这种目的的
模式如下(模式后面的描述只述说其为控制类使用安全带来的好处):
singleton模式:为了控制类的实例之允许生成一个,该模式可以扩展适应需对类的实例进行管理的情形;
factory模式:为了使大家使用统一的工件,避免项目中可能出现不一致;
使用类代替枚举类型:保证参数一定是定义的枚举中的一个,还有...一下子忘了……-……
大家再说说吧!
 
我觉得我们在分析的时候,应该考虑那些对象是实体,那些是操作类。
我觉得不应该把登录这样一个业务逻辑放到一个实体中去作为一个操作,而应该放到一个操作类中。
 
学习中,收藏!
 

Similar threads

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