欢迎大家讨论。
我感觉Delphi快速开发,在事件中写代码,很容易诱导我们写出,不易维护的代码!
大家都是如何改善的呢?

解决方案 »

  1.   

    我现在想给新人写个一般性的指导原则。我是比较反对直接在事件中写代码的。这样的写的代码又长又难看。
    尤其我们外包收回的程式很难维护。
    一般新手的做法是,画好UI后直接在控件的事件中写代码,程式的员的思考点是从UI用户的操作上入手的。
    我想参考面向对象的方法,把编写代码的思考点转到业务对象的操作上。利用对象和单元文件模块化。
    写好对象的方法后,在思考UI的调用。大家有没有方面的经验最好能标准化,方便外包验收的。
      

  2.   

    我刚总结的欢迎大家指证:撰写易维护易扩展的数据库程序Delphi篇最近一直在抱怨说:外包的程序很滥,一点儿也不易维护,扩展性也不好。但是到底什么是程序的“易维护性”和“可扩展性”?还没有做过比较深入的思考,通过这篇文章对自己的认识做个总结。提供给大家做个讨论的引子。
    易维护性,可扩展性是很模糊的概念我们经常挂在嘴边但是又很难一下子给出个明确的定义,我主要根据自己撰写和维护程序的经验从下面四个问题展开讨论。
    1. 维护中遇到的不易维护不易扩展的程序有什么特点?是怎样制造出来的?
    2. 易维护和易扩展的程序应该具有什么样的特点?
    3. 怎样在实践中撰写出易维护和易扩展的程序?
    4. 在易维护和易扩展的基础上怎样保证程序的质量?
    打开一个程序浏览一下代码,如果发现变量和函数的命名很乱,排版很乱,一个按钮事情翻了三个屏幕还没结束,我就很头痛很反感阅读这样的代码更别说要快乐的去修改他了,如果天天面对这样的工作我这样的人会崩溃的。这样的代码对我来说就很难维护更别说要扩展他了。细数我所经历的难维护的不良代码主要表现在以下方面:
     变量和函数命名不符合大家的习惯(team的规范),命名随便没有意义。
     乱用全局变量而且还在不同的单元中引用。
     代码没有模块化处理一个程序的代码几乎都集中在几个按钮的事件中,导致事件代码过长,处理的逻辑复杂。
     SQL语句到处都是还动态生成嵌套了N层,不知道使用外连接,从来不用参数的方式。
     代码很少处理错误和异常,一个不合法的输入就会崩溃。
    浏览以前我写的代码,很惭愧的发现上面几条都很符合,原来我一直抱怨的东西,自己也一直在制造!有必要来反思我撰写程序的行为了,这样滥的代码到底是怎么制造出来的呢?如何去改进自己撰写方式?
    我发现我大部分的程序是这样的写出的:简单的阅读UC,spec(自己写程序的时候spec可能还是写好程序后撰写的),设计好table(或者了解了已经设计好的table结构),就迫不及待的在Delphi里拖控件画UI,在按钮里写事件,写着写着发现需要一个全局变量,就加一个,过一会发现又要加一个,还要在其它的单元中引用,很快就写好了,能跑起来了。嘿,很高兴!功能都实现了。如果程序的功能很简单这样问题也不大,写好后修改的可能性都很小。如果程序很复杂还需要经常修改。那就惨了!
    仔细的分析我这种开发行为是很有问题的,首先过多的关注UI的操作方式或者说程序的思考点是从UI开始的而不是从实际的业务运作开始其次缺少全局的设计规划,没有对程序做模块化处理,更不要说对模块之间耦合做处理了。要想改善这种撰写程序的方式就需要了解我们所撰写的程序的特点,以及易维护和可扩展的程序特点。
    我们在工厂做开发直接面对用户,有的时候用户需求变动很大时间又紧迫,这样对程序的易维护性和扩展性要求会很高。易维护和可扩展的代码往往表现在代码模块化处理的比较好,模块与模块之间耦合度低(修一个模块对另一个模块影响程度低),模块内部内聚性强(一个模块或者一个函数功能集中单一这样修改起来比较简单),模块的封装和复用比较好,模块与模块之间通过接口交互。这些都是书上的内容在实践中在变量和函数命名都符合大家的规范保证代码可读性基础上如何改善代码的可维护性和扩展性呢。
    参考面向对象的分析和设计方法我们首要要改变自己撰写程序的方式,即把思考点从UI的操作上转移到业务对象的设计和交互上,从全局出发设计各个模块。其次在实际撰写代码时再对模块的内聚性下功夫。
    如何对程序模块化我们可以参考“表现,行为,数据”在逻辑上对程序划分为三个层次(如图一个程序例子)。
     表现:主要是呈现给用户操作的UI,窗体所对于的pas文件中不要写任何业务处理的代码。
     行为:业务对象的行为,集中所有的业务处理逻辑,同时提供接口来响应“表现”层发出的请求。
     数据:DataModual层持有所有程序所使用的数据集,负责与数据库进行交互和事务的管理。我喜欢把所有的SQL语句都写在数据层里面,方便集中修改。
     
    对程序进行这样的模块化处理难点是业务对象分析,因为目前Delphi的数据库程序开发是数据库驱动的不是对象驱动的。这样做会丧失一些Delphi快速开发的优势。但是对后续程序的维护和测试会很方便。
    高质量的程序不是一下就写好的,需要后续维护中不停的重构和测试。这篇文章主要对开发方式的转变进行总结,新的方式的使用还在以后开发中做进一步的验证。参考数据:
    1.《Delphi面向物件编程思想》 刘艺
    2.《面向对象开发实践之路》利瓦伊
    3.《企业应用架构模式》
    4.《代码大全》
    5.《代码重构(VB版)》http://book.csdn.net/bookfiles/1053/index.html
    我收集的资料供大家学习参考。VB和Delphi很像我们可以参考VB的代码重构来改善我们的 代码。
      

  3.   

    delphi很难做这个工作
    事实上晕到死下面的程序好象多少都有这个问题
    程序中最重要的是业务逻辑
    现在的问题是业务逻辑受限于开发语言或者说受限于晕到死的结构而无法独立
    或者说不容易把业务逻辑独立出来单独维护
      

  4.   

    最近在用C# ,刚开始的时候,从数据集中读取数据,转换成业务对象都是用user.name=ds.fieldbyname("name").asstring;
    user.title=ds.fieldbyname("title").asstring;
    这样的方式,看了反射后就写一个通用的方法
    function rowToObject(ds,rowindex,userinfo);通过比较表字段和对象属性字段的方式来直接给对象赋值,
    立刻代码就少了很多。原来每个对象都有一个从数据集中删除数据的方法,最后给每个表都添加了id 自增标识 字段
    写一个方法 function deleteobject(obj) ;搞一个配置文件记录每个类型的对象和表的关系,拼SQL语句就OK了。方法都是总结出来的,写一段时间代码后就要考虑能不能改进,能不能做的更好。当然,你要了解语言本身提供的功能,做一个系统并不是实现就好了,实现只是完成了工作,要想学习提高就要重构。
      

  5.   

    从d6还是d7开始引入了action的概念,建议在action中写事件代码而不是某个控件中
    习惯双击控件然后把所有东西放到事件里都是rad教材惯出来的毛病,一开始就不要搞什么所见即所得,老老实实从console入门,对oo有一定程度了解了再把gui拉出来
    吃快餐又不爱动脑出来的,想不又肥又笨都不现实
      

  6.   


    支持,我也是在總結中重構代碼。要不然出了問題,想請個假都休息不好。
    關鍵是Delphi沒有c#的那種處理方式啊。
      

  7.   

    业务逻辑和界面分离
    业务逻辑修改不影响界面,界面修改不影响业务使用actionList
      

  8.   

    很多问题还是框架的限制
    比如,delphi的事件不是线程,我想在一个事件执行的时候,能并行执行另一个事件,2个事件的代码交替地执行,就无法做到
    如果分别交由一个线程去执行,由会涉及vcl的线程支持问题
      

  9.   

    我目前的想法是,UI层面Form所对应的pas文件不容许写任何逻辑处理代码。更不能包含sql。
    对业务逻辑做模块化处理封装在对象中存在不同的pas文件中。
    尽量不要使用全局变量,不要在不同的单元中引用全局变量。
      

  10.   

    我想討論的是,如何撰寫代碼易於維護,和擴展。
    封裝,繼承啊啥的都是理論層面的,
    我想在代碼面的討論。楼主此话差已!
    理论都是来自于实践,由实践累积而来的。
    举个简单的例子:
    TMan = class
    public
      procedure speak;end;子类:
    TChinese = class(TMan)end;TEnglish = class(TMan)
    end;如果让所有的子类都有新增加一个name的属性,最简单的方法是在父类增加就可以了。
    那么,与你在所有的子类增加name属性是不是更改的更小了呢?
    修改TMan
    TMan = class
    private
      FName: string;
    public
      procedure speak;
      property Name: string read FName write FName;
    end;这个只是最基本的,根据情况不同采用的方法也不同。
    设计模式和敏捷开发等就是在编写千万代码总结出的经验!还有就是看你具体的应用,如果你写的是上位机或者与硬件通讯
    的程序,那么就另当别论了。毕竟面向对象在这种应用下,效率
    没有过程来得高。楼主自己多看多练,多想,慢慢揣摩吧!
      

  11.   

    谢谢你的指教。
    我们目前主要是开发制造业的MES系统,主要是与数据库相关。我们在架构层次上用到了继承等特性。
    当时单支程式比如维护工艺资料,一般都是对数据集做操作。
    这种特性很少用到。
      

  12.   


    在我的Client/Webserver架构里,客户端采用非db的界面控件来显示、编辑当前记录的各个字段,浏览采用dbgrid,数据源是一个类似clientdataset的内存表控件,内存表里的数据按INI@http的方式取自位于webserver的应用服务程序(isapi程序)。
    需要保存非db的界面控件里的内容修改、新增时,自动根据控件的name组成相应的sql语句,通过ini@http提交给应用服务程序(isapi程序)去执行。应用涉及的所有的表,都要有这样的几个字段:
    fid:自动递增id字段(用户不可见);fname:该记录的描述、识别文本;fdeleted:删除标志
    update语句就是根据fid进行定位的
      

  13.   

    我以前写了一个bpl的框架,可以把所有业务等抽象成接口,实现界面与逻辑分离,可以看看这里(有源码),希望和大家交流交流:http://hi.baidu.com/0xcea4/blog/item/54caa91a926e93118718bf45.html