软件开发的过程就是一个不断分类总结的过程,软件开发应该遵循代码简单易读,结构清晰明了。新手的问题在于不知该如何分类,总是一股脑的将代码写在主窗体,在按钮的事情里写大量的代码,不区分界面展示,业务逻辑,业务数据和数据库操作。
  开发过程中最常见的业务如对一个数据表内容的增,删,改,将数据放在一个ListView中。很多人都会直接将ADO控件直接放在主窗体,然后在按钮事件里就开始查询表,得到数据级后,直接在数据集的循环里就开始向表格添加了,按钮事件里代码老长。
这个功能应该分成三个部分:数据库操作,业务对象管理,界面显示。
  如表中数据是一个用户清单 TUserInfo
  先创建一个业务类:TUserInfo,然后创建一个业务类容器TUserInfoList
  将ADOConnection ,ADOQuery 都放在TDataModule 里,然后给TDataModule添加 
  function GetList(AList:TUserInfoList):Integer;
  function Delete(AID:Integer):Integer;
  function Save(AUserInfo:TUserInfo):Boolean; 这几个方法。  主界面实现 
  procedure UserInfoToListItem(AItem:TListItem;AUserInfo:TUserInfo);将一行数据显示到表格
  procedure UserInfoListToListView(AList:TUserInfoList;LV:TListView);//显示列表到表格
  procedure LV_DeleteUserInfo;实现将选中的行删除
  然后主界面放置 TActionList,添加对应的:新建,删除,修改的方法。
  然后按钮设置 Action  这样的应用是属于同步应用的,开发要容易一些,只是分成几块后程序结构会比较清晰易读一些。
  
  
  

解决方案 »

  1.   

    关于用Delphi开发的一些基本的套路。1.源文件,Dcu文件和最后的编译好的程序放在不同的目录2.窗体单元都用WinXXXX的方式命名,Win做为前缀,窗体类都用Tfrm_XXXX的方式命名,Tfrm_做为前缀3.窗体字体都设置成宋体,小五4.使用一个 TDataModule 来放一些公用的控件,如 TImageList,不要在每个窗体都放TImageList整个程序
    用一个就可以了,否则会造成图片重复,编译后的程序变大,TImageList如果放置的是16*16的图标,则命名为
      img_1616。5.TDataModule 一般命名为 DMApp,做为系统中主要的一个公用单元。放置一些TADOConnection ADOQuery等非可初控件。6.所有的按钮事件都使用 TActionList 如有用户添加,用户删除的功能,创建 act_UserAdd,act_UserDelete这些对应的 TAction。引用 DMApp单元的 img_1616给每个 TAction 设置图标。7.按钮功能,右键菜单,工具栏都指定自己的 Action属性。8.如果某个地方需要指定调用一个功能,如要调用刷新,来重新显示用户清单,则用act_UserRefresh.Execute;的方式来调用,不要调用某个按钮的 btn_UserRefresh.Click。9.调整工程的dpr工程文件,让 DMApp单元先加载,dpr工程文件中除去DMApp单元和主窗体外,其它的窗体创建代码全部删除掉。也可以通过 Project->Options->Forms 来进行调整。10.如果有其它子窗体,如有子窗体A来完成用户编辑的功能,单元文件是 WinUserEdit,窗体类是 Tfrm_UserEdit。如果窗体是要 ShowModal 使用,则将系统生成的var  frm_UserEdit: Tfrm_UserEdit;  删除。给Tfrm_UserEdit添加类方法
    class function CreateWinUserEdit(User:TUser):Boolean;实现代码如下class function Tfrm_UserEdit.CreateWinUserEdit(User:TUser):Boolean;
    var
      form:Tfrm_UserEdit;
    begin
      Result:=False;
      form:=Tfrm_UserEdit.Create(Application);
      form.SetUserInfo(User);
      form.ShowModal;
      Result:=mrOK=form.ModalResult;    
    end;其它创建想创建 Tfrm_UserEdit 窗体时使用 Tfrm_UserEdit.CreateWinUserEdit(User);的方法,根据返回值做下一步的操作。11.如果子窗体是 Show的方式打开,并且不能重复打开,则将系统生成的var  frm_UserEdit: Tfrm_UserEdit; 放到implementation 下面。给Tfrm_UserEdit添加类方法
    class function CreateWinUserEdit(User:TUser):Boolean;实现代码如下implementation 
      var  
        frm_UserEdit: Tfrm_UserEdit; class function Tfrm_UserEdit.CreateWinUserEdit(User:TUser):Boolean;
    begin
      Result:=False;
      if Not Assigned(frm_UserEdit) then
         frm_UserEdit:=Tfrm_UserEdit.Create(Application);
      frm_UserEdit.SetUserInfo(User);
      form.Show;  
    end;procedure Tfrm_UserEdit.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action:=caFree;
      frm_UserEdit:=nil;
    end;12.关于数据库操作,将TADOConnection 放在DMApp单元中。如要返回用户列表,在DMApp单元中实现function DMApp.DBGetUserList(AList:TList):Integer;
    begin
      执行SQL,返回生成User放到 AList对象中,返回总的个数。end;如果想要使用数据库绑定,则在DMApp单元放置一个ADOQ_User:TADOQuery;实现function DMApp.DBGetUserList:TADOQuery;
    begin
      执行SQL,返回数据集。
    end;使用的原则是:将和界面无关的功能放在 DMApp单元中,这样可以整个程序都共享,实现一些方法来封装数据库的操作,不要在
    窗体单元中写的到处都是SQL语句。13.要想程序不出错,那就不要将所有的代码分在一起,就象工厂不能所有人都在一个房间里干活一样,分层次,分类,代码结构清晰了
    就不容易出错。设计就是从不同角度分类,分组,最后得到一个最好的组织方式。不要因为窗体少,就感觉能随便写,一个良好的习惯和套路让你不会过多的时间纠缠于解决一些基本的错误。结构清晰的你才能想得明白。
      

  2.   

    软件开发的过程就是一个不断分类总结的过程,软件开发应该遵循代码简单易读,结构清晰明了。新手的问题在于不知该如何分类,总是一股脑的将代码写在主窗体,在按钮的事情里写大量的代码,不区分界面展示,业务逻辑,业务数据和数据库操作。
      开发过程中最常见的业务如对一个数据表内容的增,删,改,将数据放在一个ListView中。很多人都会直接将ADO控件直接放在主窗体,然后在按钮事件里就开始查询表,得到数据级后,直接在数据集的循环里就开始向表格添加了,按钮事件里代码老长。
      

  3.   

    界面 和 业务逻辑 真的能分的很开?
    比如,100个用户,但是不能列出100行
    因为
    A用户只能看到其中的40行,但是只能编辑其中的30行(本人或下属录入编辑的),每行的m列可以显示,其中只有n1列可以编辑。本人录入编辑的可以维护的列数 与 下属录入编辑的可以维护的列数还不一样。
    业务逻辑可以千奇百怪。
      

  4.   

    TDataModule应该还要细分,一个公共的,包括数据连接和共用的Data,其它每个分类是一个TDataModule(这个分类可以按照自己的业务情况进行设计,比如采购模块是一个TDataModule)个人觉得多了一个步骤,主界面实现的上面3个功能,可以直接写在TActionList里面
      

  5.   


    有可能并不是一个界面中去显示数据,在有的界面可能是显示+编辑,有的窗体只是显示。
    所以将业务对象到列表的展示独立出来,要是写到 TAction 中,另一个界面中又得写一遍。
      

  6.   

    软件开发的过程就是一个不断分类总结的过程,软件开发应该遵循代码简单易读,结构清晰明了。新手的问题在于不知该如何分类,总是一股脑的将代码写在主窗体,在按钮的事情里写大量的代码,不区分界面展示,业务逻辑,业务数据和数据库操作。
      开发过程中最常见的业务如对一个数据表内容的增,删,改,将数据放在一个ListView中。很多人都会直接将ADO控件直接放在主窗体,然后在按钮事件里就开始查询表,得到数据级后,直接在数据集的循环里就开始向表格添加了,按钮事件里代码老长。
      

  7.   


    这样说的话就好理解了,不过这种情况我都是写在Common单元里面
      

  8.   

    顺便问一下,delphi有操作sqlite3的封装库吗?
      

  9.   

    基于MVC的设计模式就比较好。呵呵~
      

  10.   

    对于未知问题,不同领域其解决方法流程类似,可以相互参考。
    数学的方法:归纳 猜想 验证 总结
    工业的方法:计划 实施 检查 总结处理 (PDCA循环)编程的方法,更多地采用问题分解的方式,其处理流程也没走出类似的PDCA循环。
    一、规划:
    1)分析  分析问题,将问题分解为不同的子问题,衍生出各种类,构筑问题域的层次及其类体系。
    2)模拟运行 依据类体系,模拟各种问题是如何分布在各个类中的,各个类是如何分工合作,从而解决各种各样的现实问题。
    3)抽象接口 通过虚拟模拟运行,规划各个类之间的接口,定义好各个类的内在职责。
    4)工作规划 将各种类及其要实现的目标及初步接口,分发到具体的开发人员中,编写长远工作计划及阶段工作计划。
    二、按阶段工作计划落实编码 将各种类接口用具体的编程语言实现。
    三、按工作规划检查与测试编码质量。
    四、每阶段总结,并且进行对象抽取共享,同时不断完善与充实共享的函数库与类库。对优秀的对象给予推广。将好的经验写出来(解决各种问题的好的方法或方式,也就是模式抽取),在团队中共享。其中,构筑解决问题的类体系,实际上就是问题建模。这些过程实际上是存在于我们每一次编程之中,我们经常忽略最重要的问题规划阶段,而直接编程测试,将最后的总结抽取摆在重要位置,即在工作中总结经验再用于工作中,不是说这样不好,而是仅仅这样还不够好,习惯于缺少问题分析规划这一步,不利于长远发展,只能小打小闹。
      

  11.   

    其实如果能做到逻辑访问接口化(接口、抽象类均可),逻辑接口的获取工厂化、配置化,自然就把这两层的依赖很好的分开来了。当然之后界面层是直接绑定数据,还是MVC什么的,就是另外一回事了。
      

  12.   

        放假的时候做个DEMO,这只是对初学者,不知应该做的朋友有点用,基本的原则就应该知道不要将所有代码放在一起,初学者最容易这样做了。
        所以提出一些基本的规则,只要遵守就有了基础的界面,业务,数据分离的架构了。
      

  13.   

    项目进行过程中,有若干debug信息需要打印。之前都是统一一个rootCatogry输出,将日志级别调整到debug后,会输出框架的很多debug代码,导致日志文件非常大。知道log4j可以将不同的包下的日志输出到不同的位置,在网上恶补了一下log4j的基础概念之后,得到了一个可以暂时使用的方案。 Log4j配置中分为logger、appender、layout等几种元素,其中appender、layout的配置网上介绍比较多,不再赘述。通过对logger的定义,可以做到上述的需求。 Logger的定义需要指定级别,appender等。rootLogger是所有Log的父log,除此之外,还可以自定义若干logger。logger的继承关系是根据名称的前缀匹配决定的,如logger a为logger a.b的父log。在父log中定义的属性可以在子log中被覆盖。 如果在代码中通过Logger.getLogger(this.getClass)的方式得到Logger对象,就可以做到不同的包的日志做不同的处理。如定义logger org.apache.struts的级别为INFO,Logger com.mypack的级别为DEBUG,就可以做到不看框架复杂的DEBUG信息,同时自己写的类中可以使用log.debug()输出调试信息。 另外,我现在使用的方式是只定义了两个appender,所有的logger共用,在使用的时候会出现:log4j:ERROR Attempted to append to closed appender named [A1].
    log4j:ERROR Attempted to append to closed appender named [A2].这样的错误信息。经过google发现可能是由于共用appender所致,具体原因还没有找到。 刚开始做项目,关于日志管理的理解还很初步,欢迎指教。
     ==============================================================关于log4j:ERROR Attempted to append to closed appender named [A1]. 之前的配置文件没问题,增加了一个logger之后无论怎么改,都会出现这个问题。最后无奈,将配置文件完全复原,竟然还是有这个错误。这是个web项目,突然想到将tomcat中webapp文件夹下部署的文件夹完全删除再重新部署,问题竟然解决了!然后重新配置多个logger,都没有问题。 不禁想到一句名言:对于此类不能用常理解决的问题,我们统统归结为人品! 粘贴我的log4j.properties如下:  #定义2个输出端
    log4j.rootCategory=INFO,A1,A2
    log4j.logger.edu.tju=DEBUG #这一句为新添加的,将我自己的类的日志级别调整为DEBUG级别,顺便秀一下母校天津大学^_^
    #定义A1输出到控制器
    log4j.appender.A1=org.apache.log4j.ConsoleAppender
    #定义A1的布局模式为PaternLayout
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    # 定义A1的输出格式
    log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %-5p [%c] (%t) %m%n
    #定义A2输出到文件
    log4j.appender.A2=org.apache.log4j.RollingFileAppender
    #定义A2输出到哪个文件
    log4j.appender.A2.File=./hrms12319.log
    #定义A2输出文件的最大长度
    log4j.appender.A2.MaxFileSize = 10000KB
    #定义A2的备份文件数
    log4j.appender.A2.MaxBackupIndex = 3
    #定义A2的布局模式为PatternLayout
    log4j.appender.A2.layout=org.apache.log4j.PatternLayout
    #定义A2的输出模式
    log4j.appender.A2.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %-5p [%c] (%t) %m%n
      

  14.   

    MVC,M(Model);V(iew);C(control)。
      

  15.   

    Good good study ,day day up ..,,