zoukankan      html  css  js  c++  java
  • (转)Delphi 编程规范

    Delphi 编程规范

    【排版规范】

    ----------

      Delphi XE 以上的版本中都有官方的代码格式化工具(Edit -> Format Source),快捷键是 Ctrl + D,用这个工具排版以后的格式就是标准格式了。该工具没有相关的设置方法,我们遵照默认的设置来对我们的代码进行排版。这里对代码的排版规范做一下总结。

    ----------

    1、缩进

      缩进是指在每一级有两个空格。不要在源代码中保留 Tab 字符,这是因为,制表符的宽度会随着不同的用户设置和代码管理实用程序(打印、文档及版本控制等)而不同。

      要禁止保存 Tab 字符,可以通过 Tools -> Editor Options 菜单,在 Editor Properties 对话框的 General 页上,取消 Use tab Character 和 Optimal Fill 复选框即可。

    ----------

    2、页宽

      默认页宽为 80 字符宽。超出这个范围的代码应该在“逗号”或“操作符”的地方折换到下一行,并相对第一行缩进 2 个字符。声明函数时,参数的名称和类型要成对出现,不能分行书写。例如:

    function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar;
      lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
      hWndParent: HWND; hMenu: hMenu; hInstance: HINST; lpParam: Pointer)
      : HWND; stdcall;

    ----------

    3、代码间隔

      各语句元素之间使用空格隔开,以增强程序的可读性。例如:

    A:=1; 应写成 A := 1;

      遇到如下情况,需要添加空格:

      (1) 逗号(,)的后面
      (2) 冒号(:)的后面
      (3) 等号(=)的前后
      (4) 赋值号(:=)的前后
      (5) 运算符(+、-、*、/、andor 等)的前后

      不同逻辑的程序块之间要使用空行分隔,空行起着分隔程序段落的作用,适当的空行可以使程序的布局更加清晰。

    ----------

    4begin ... end 配对

      begin else end 语句应独占一行。相应的 end 语句永远缩进到与 begin 语句相对应的位置。例如:

    if 条件 then
    begin
      ...
    end
    else
    begin
      ...
    end;

    ----------

    5、括号

      不要在“括号”与“括号内字符”之间留下空格。不要在一个语句中使用不必要的括号。例如:

    Random( 100 );
    应写成
    Random(100);

    if (x > 10) then
    应写成
    if x > 10 then

    ----------

    6、保留字和关键字

      如果类型的名称是保留字或关键字,那么它应该全部小写。Win32 API 类型通常全部大写,并且必须遵循在 Windows.pas 或其他 API 单元中的详细类型名称的约定。例如:

    Mytring: string;      // 保留字
    WindowsHandle: HWND;  // Win32 API 类型
    i: Integer;           // 在 System 单元中介绍的类型标识

    ----------

    7、文件头

      建议在所有源文件、工程文件、单元文件等中使用信息化文件头。一个良好的文件头应包含以下信息:

    {*******************************************************}
    {                                                       }
    {       软件名称                                        }
    {                                                       }
    {       版权所有 (C) 2012 公司名称                      }
    {                                                       }
    {*******************************************************}

    ----------



    【命名规范】

    ----------

    1、函数

      函数名总是以大写字母开头,并且总是采用大小写结合的方式,每个单词的开头采用大写,其余采用小写。例如:

    procedure thisisapoorlyformattedroutinename;
    应改成:
    procedure ThisIsMuchMoreReadableRoutineName;

      函数名应该同它的内容相符,一个会导致某个行为的函数应以动词开头。一个用于设置输入参数的函数应以单词 Set 作为前缀,一个用来接收某个值的函数应以单词 Get 作为前缀。例如:

    procedure CreateForm(...);     { Create 动词 }
    procedure SetUserName(...);    { Set 设置 }
    function GetUserName: string{ Get 获取 }

      用正确的“反义词组”命名具有互斥意义的变量或相反动作的函数等。下面是一些在软件中常用的反义词组。

    set         get
    add         remove
    begin       end
    create      destroy
    insert      delete
    first       last
    get         release
    increment   decrement
    put         get
    add         delete
    lock        unlock
    open        close
    min         max
    old         new
    start       stop
    next        previous
    source      target
    show        hide
    send        receive
    source      destination
    cut         paste
    up          down

      在函数或过程的前面填写适当的头信息,例如:

    {-------------------------------------------------------------------------------
      创建:      创建信息,作者,日期
      名称:      FunctionName
      功能:      本函数或过程的主要功能
      参数:      Param1:...
                 Param2:(out)...
      返回值:    类型、值
      说明:      备注信息、调用方法、初始化数值等
    -------------------------------------------------------------------------------}


    ----------

    2、函数参数

      所有函数的参数名称应该符合它们所代表的意义,特别是应该以传送到函数中的标志符的名称为基础。

      在类的方法中,如果一个参数的名称容易和“类中的属性名称”或“系统关键字”相混淆时,则应该在参数名称前添加“A”前缀。“A”前缀按约定表示该参数的名称是与类类型中的一个属性或字段(域)的名称相对应。例如:

    TCustomForm.Create(AOwner: TComponent);
    TCustomForm.SetParent(AParent: TWinControl);
    TCustomForm.SetDesigner(ADesigner: IDesignerHook);
    TCustomForm.AlignControls(AControl: TControl; var Rect: TRect);
    TCustomForm.RecreateAsPopup(AWindowHandle: HWND);

    ----------

    3、变量

      变量名一般以代表该变量类型的小写字母为前缀,常用类型的前缀列表如下:

    i    : Integer;
    f    : Single, Double;
    c    : Char;
    p    : Pointer;
    b    : Boolean;
    uc   : Byte;(UnsignedChar)
    w    : Word;
    dw   : LongWord;(DWord)
    a    : Array, Array of TYPE;
    s    : String;

      以上前缀可以进一步组合成新的类型,自定义的数据类型可以自己规定类型前缀,如果该类型使用较为广泛,可以升级为公司内部的通用前缀。目前已有的内部通用前缀为:

    pid  : PID 变量

      变量名各单词之间以大写字母分隔。例如:

    susername
    应改成
    sUserName

      变量的名称应与使用它们的目的相符。循环控制变量应采用一个单独的字符作为名称,比如 I、J、K,也可以采用更加有意义的名称,比如 UserIndex。逻辑变量的名称应能充分表达准确的真或假的意思。临时变量的取名应合理。

      局部变量用于函数内部,遵循其他变量的命名规则。局部变量加前缀 l_(循环控制变量除外),如 l_UserName。

    ----------

    4、常量(资源字符串)

      常量(资源字符串)的命名应当能够表达出它的用途。如果常量(资源字符串)有类别,则该类别的所有常量必须加相同的前缀,前缀为该类别缩写的小写字母。例如:对于文件打开方式定义的常量:

    fmOpenRead = $0000;
    fmOpenWrite = $0001;

      如果常量没有类别,则常量的默认前缀为 con。例如:

    conProductName = '示例程序';

      如果资源字符串没有类别,则资源字符串的默认前缀为 rs。例如:

    rsFileOpenError = '文件打开失败!';

    ----------

    5、标识符

      标识符的命名应当符合“min-length && max-information”规则。

      较短的单词可通过去掉“元音”形成缩写,较长的单词可取单词的头几个字母形成缩写,一些单词有大家公认的缩写,常用单词的缩写必须统一。协议中的单词的缩写与协议保持一致。对于某个系统使用的专用缩写应该在某处做统一说明。

    ----------

    6、枚举类型

      枚举类型的名称应符合使用它们的目的。该类型的声明应以字符 T 为前缀,以表明这是一个类型。枚举类型中的元素的前缀应包含 23 个小写字符来彼此关联。例如:

    type
      TSongType = (stRock, stClassical, stCountry, stAlternative, stHeavyMeta1, stRB);

      一个枚举类型的实例名称应与不要前缀“T”的枚举类型相同,例如:

    var
      SongType: TSongType;

      如果有更好的原因,则可以赋予该变量更特殊的名称,例如:

    var
      FavoriteSongType1: TSongType;
      FavoriteSongType2: TSongType;

    ----------

    7、数组类型

      数组类型的名称应符合使用它们的目的。该类型的声明应以字符 T 为前缀,以表明这是一个类型。如果要声明该数组类型的指针类型,那么指针类型应以 P 为前缀,并且应立即声明在该数组声明的前面。例如:

    type
      PCycleArray = ^TCycleArray;
      TCycleArray = array[1..100] of Integer;

    ----------

    8、记录类型

      记录类型的名称应符合使用它们的目的。该类型的声明应以字符 T 为前缀,以表明这是一个类型。如果要声明该记录类型的指针类型,则指针类型应以字母 P 为前缀,并且应立即声明在该记录声明的前面。例如:

    type
      PEmployee = ^TEmployee;
      TEmployee = record
        EmployeeName: string;
        EmployeeRate: Double;
      end;

    ----------

    9、类类型

      类类型的名称应符合使用它们的目的。该类型的声明应以字符 T 为前缀,以表明这是一个类型。例如:

    type
      TMyObject = class(TObject);

      一个类类型的实例名称应与不要前缀“T”的类类型相同,例如:

    var
      MyObject: TMyObject;

      类的字段(域)名遵循与变量标识符同样的约定,只不过要以 F 为前缀,以表明这是一个字段(域)的名称。所有的字段(域)都必须是私有的。想在类的范围之外存取字段(域)值,必须通过属性来完成。

      方法的命名应遵循本文档中有关过程和函数的约定叙述。

      属性如果是表示为一个私有字段(域)的存取器的话,那么它的名称应是它们所操作的字段(域)的名称去掉前缀“F”。属性的名称应是名词,不是动词。属性表示的是数据,而方法表示的是行为。数组类型的名称应为复数。一般情况下属性的名称应为单数。

    ----------

    10、项目文件

      Delphi XE 已经支持中文项目文件名了,这个可以根据自己的需要来自由命名。

    ----------

    11、单元文件

      Form 文件的名称应当表达出 Form 的用途,且具有 Frm 后缀。例如,About 的文件名叫 AboutFrm,主 Form 的文件名叫 MainFrm。

      数据模块的文件名应当表达出数据模块的作用,且具有 DM 后缀。例如,Customers 数据模块的文件名叫 CustomersDM.dfm。

      远程数据模块的文件名应当表达出远程数据模块的用途,且具有 RDM 后缀。例如,Customers 远程数据模块的文件名叫 CustomersRDM.dfm。

      通用单元的名称应当表达出它的用途。例如,一个实用工具单元的名称叫 ugUtilities.pas,包含全局变量的单元名称叫 CustomerGlobals.pas。一个项目中单元名称必须是唯一的。


    ----------

    12、包

      包的名称应依照下面的例子:

      “iiilibvv.pkg” - 设计时刻包
      “iiistdvv.pkg” - 运行时刻包

      字符“iii”表示一个 3 字符标识前缀。这个前缀用来表明公司、个人或其它有标识意义的实体。字符“vv”表示为该包所对应的 Delphi 的版本号。包的名称中包含“lib”或“std”的意思是表明这是一个设计时刻包还是一个运行时刻包。

    ----------

    13、组件

      CnPack 插件会自动为“我们所添加的组件”修改前缀信息,我们遵照 CnPack 的默认设置即可。由于 Delphi 的组件在不断的增加,所以,这里只列出部分常用组件的前缀信息(这里的前缀信息可能与 CnPack 不一致,仅供参考)。

    Standard 页

    mm                  TMainMenu
    pm                  TPopupMenu
    mmi                 TMainMenuItem
    pmi                 TPopupMenuItem
    fm                  TFrame
    lbl                 TLabel
    edt                 TEdit
    mem                 TMemo
    btn                 TButton
    ck                  TCheckBox
    rb                  TRadioButton
    lb                  TListBox
    cb                  TComboBox
    scb                 TScrollBar
    gb                  TGroupBox
    rg                  TRadioGroup
    pnl                 TPanel
    al                  TActionList
    ac                  TAction

    Additional 页

    bbtn                TBitBtn
    sb                  TSpeedButton
    me                  TMaskEdit
    sg                  TStringGrid
    dg                  TDrawGrid
    img                 TImage
    shp                 TShape
    bvl                 TBevel
    sbx                 TScrollBox
    clb                 TCheckListBox
    spl                 TSplitter
    stx                 TStaticText
    ctrb                TControlBar
    av                  TApplicationEvents
    cht                 TChart

    Win32 页

    tbc                 TTabControl
    pgc                 TPageControl
    il                  TImageList
    re                  TRichEdit
    tbr                 TTrackBar
    pb                  TProgressBar
    ud                  TUpDown
    hk                  THotKey
    ani                 TAnimate
    dtp                 TDateTimePicker
    mc                  TMonthCalendar
    tv                  TTreeView
    lv                  TListView
    hc                  THeaderControl
    stb                 TStatusBar
    tb                  TToolBar
    clb                 TCoolBar
    pgs                 TPageScroller

    System 页

    tm                  TTimer
    pb                  TPaintBox
    mp                  TMediaPlayer
    olec                TOleContainer
    ddcc                TDDEClientConv
    ddci                TDDEClientItem
    ddsc                TDDEServerConv
    ddsi                TDDEServerItem

    Data Access 页

    ds                  TDataSource
    tbl                 TTable
    qry                 TQuery
    sp                  TStoreProce
    db                  TDataBase
    ssn                 TSession
    bm                  TBatchMove
    usql                TUpdateSQL
    nt                  TNestedTable

    Data Controls 页

    dbg                 TDBGrid
    dbn                 TDBNavigator
    dbt                 TDBText
    dbe                 TDBEdit
    dbm                 TDBMemo
    dbi                 TDBImage
    dblb                TDBListBox
    dbcb                TDBComboBox
    dbck                TDBCheckBox
    dbrg                TDBRadioGroup
    dbll                TDBLookupListBox
    dblc                TDBLookupComboBox
    dbre                TDBRichEdit
    dbcg                TDBCtrlGrid
    dbch                TDBChart

    ADO 页

    adon                TADOConnection
    adoc                TADOCommand
    adod                TADODataSet
    adot                TADOTable
    adoq                TADOQuery
    ados                TADOStoreProc
    rdsn                TRDSConnection

    Midas 页

    prv                 TProvider
    cds                 TClientDataSet
    qcds                TQueryClientDataSet
    dcom                TDCOMConnection
    olee                TOleEnterpriseConnection
    sck                 TSocketConnection
    rms                 TRemoteServer
    mid                 TMidasConnection

    Internet 页

    csk                 TClientSocket
    ssk                 TServerSocket
    wbd                 TWebDispatcher
    pp                  TPageProducer
    tp                  TQueryTableProducer
    dstp                TDataSetTableProducer
    nmdt                TNMDayTime
    nec                 TNMEcho
    nf                  TNMFinger
    nftp                TNMFtp
    nhttp               TNMHttp
    nMsg                TNMMsg
    nntp                TNMNNTP
    npop                TNMPop3
    nuup                TNMUUProcessor
    smtp                TNMSMTP
    nst                 TNMStrm
    nsts                TNMStrmServ
    ntm                 TNMTime
    nudp                TNMUdp
    psk                 TPowerSock
    ngs                 TNMGeneralServer
    html                THtml
    url                 TNMUrl
    sml                 TSimpleMail

    Decision Cube 页

    dcb                 TDecisionCube
    dcq                 TDecisionQuery
    dcs                 TDecisionSource
    dcp                 TDecisionPivot
    dcg                 TDecisionGrid
    dcgr                TDecisionGraph

    QReport 页

    qr                  TQuickReport
    qrsd                TQRSubDetail
    qrb                 TQRBand
    qrcb                TQRChildBand
    rqg                 TQRGroup
    qrl                 TQRLabel
    qrt                 TQRText
    qre                 TQRExpr
    qrs                 TQRSysData
    qrm                 TQRMemo
    qrrt                TQRRichText
    qrdr                TQRDBRichText
    qrsh                TQRShape
    qri                 TQRImage
    qrdi                TQRDBMImage
    qrcr                TQRCompositeReport
    qrp                 TQRPreview
    qrch                TQRChart

    Dialogs 页

    对话框元件实际是以元件形式封装的 Form,因此它遵循Form的命名规则。其类型经由元件的名称定义了。实例的名称与类型的名称相同,但没有前缀T。

    OpenDialog          TOpenDialog
    SaveDialog          TSaveDialog
    OpenPicturedialog   TOpenPictureDialog
    SavePictureDialog   TSavePictureDialog
    FonDialog           TFontDialog
    ColorDialog         TColorDialog
    PrintDialog         TPrintDialog
    PrintSetupDialog    TPrinterSetupDialog
    FindDialog          TFindDialog
    ReplaceDialog       TReplaceDialog

    Win31 页

    dbll                TDBLookupList
    dblc                TDBLookupCombo
    ts                  TTabSet
    ol                  TOutline
    tnb                 TTabbedNoteBook
    nb                  TNoteBook
    hdr                 THeader
    flb                 TFileListBox
    dlb                 TDirectoryListBox
    dcb                 TDirveComboBox
    fcb                 TfilterComboBox

    Samples 页

    gg                  TGauge
    cg                  TColorGrid
    spb                 TSpinButton
    spe                 TSpinEdit
    dol                 TDirectoryOutline
    cal                 TCalendear
    ibea                TIBEventAlerter

    ActiveX 页

    cfx                 TChartFx
    vsp                 TVSSpell
    flb                 TF1Book
    vtc                 TVTChart

    ----------



    【编程习惯】

    ----------

    1、函数

      函数的功能要单一,不要设计多用途的函数。多用途的函数往往通过在输入参数中有一个控制参数,根据不同的控制参数产生不同的功能。这种方式增加了函数之间的控制耦合性,而且在函数调用的时候,调用相同的一个函数却产生不同的效果,降低了代码的可读性,也不利于代码调试和维护。

      源文件中必须有被调用函数的显式的函数原型说明。

      函数尽量只有一个出口(Return),避免从循环语句中引出多个出口(Exit)。

    ----------

    2、函数参数

      在定义函数时,如果函数有参数的话,相同类型的参数一般要求放在一起。例如:

    procedure Foo(Param1, Param2: Integer; Param3: Integer; Param4: string);
    应改成:
    procedure Foo(Param1, Param2, Param3: Integer; Param4: string);

      最常用的参数应当作为第一个参数,按使用频率依次从左到右排。输入参数位于输出参数之前。将通用的参数放在特殊参数的前面。范围大的参数应当放在范围小的参数之前。排序有可能有些例外,比如事件的处理,类型为 TObject 的 Sender 参数经常放在第一位。

      当一个参数为 Record、Array、ShortString、或 Interface 并且在函数中不被改变时,应将其标识为 const 类型。这将提高程序的效率。其他类型的参数也提倡这样做,虽然不能提高程序的效率,但有助于调用者对参数的理解。

      调用函数时,全局变量不能作为函数的参数。

    ----------

    3、变量

      如果必须的话,在刚进入函数就应初始化局部变量。

      指针类型变量必须初始化为 NULL。

    ----------

    4、常量

      源文件里不能出现无意义的数字,所有数字都用常量代替。常量定义时应该有相应说明。

      如果在模块中有提示信息之类的字符串,则应把该字符串定义为资源字符串。

    ----------

    5、名称的冲突

      当两个单元中存在名称相同的函数时,如果你调用该函数,在 uses 子句中排在后面的单元中的函数将会被调用。为了解决这个问题,要在调用该函数时写上相应的单元前缀。比如:

    SysUtils.FindClose(SR);
    Windows.FindClose(Handle);

    ----------

    6、全局变量

      使用全局变量是不推荐的。但是,在某些时候还是必须使用,而且它们也只应在必须使用的时候才使用。在这种时候,你应努力只在一段上下文范围内使用全局变量。例如,一个全局变量只应在一个单元的 implemntation 部分内是全局的。如果全局变量只对某个对象有用,比如 Form1,则应该将其声明为 TForm1 的数据成员,以便提高效率和统一管理。如果打算在多个单元内使用全局数据,你应将它们移到一个单独的公共单元中,然后被其它所有单元使用。

      全局变量可以在 var 子句中直接初始化为一个值。记住,所有的全局数据会自动初始化为 0,因此不要将全局变量初始化为一个“空”值比如 0nil''、Unassigned 等等。这样做的原因是因为未初始化的全局数据在 exe 文件中不会占据任何空间。未初始化的数据被存储在一个虚拟的数据段,它在应用程序启动后被分配在一段内存中,而初始化的全局数据则在硬盘的 exe 文件中占用空间。

    ----------

    7、浮点类型

      不推荐使用 Real 类型,因为它的存在只是为了向前兼容早期的 Pascal 代码。在通常情况下对于浮点数应当使用 Double 类型。Double 对处理器和总线而言是做了最优化处理的,它也是 IEEE 中定义的标准数据格式。只有当需要的范围超出 Double 所定义的范围时才使用 Extended。Extended 是 Intel 定义的类型且在 Java 中不支持。只有当浮点变量的实际字节大小有其意义时(比如当使用另一种语言编写的 DLL 时)才使用 Single。

    ----------

    8、变体类型

      通常不建议使用 Variant 和 OleVariant 类型。但在只有运行时刻才能知道数据类型的程序中,则必须使用这两个类型,这种情形多出现在 COM 和数据库开发中。OleVariant 使用在以 COM 为基础的编程中,例如自动化和 ActiveX 控制,而 Variant 则使用在非 COM 的编程中,这是因为 Variant 能够有效地保存 Delphi 的原生字符串,而 OleVariant 会将所有的字符串转换为 Ole 字符串(即 WideChar 字符串)且没有引用计数功能,它们永远通过拷贝来传递。

    ----------

    9、类类型

      当你不希望一个方法被派生类重载时,则应当使用“静态方法”。

      当你希望一个方法能被派生类重载,则应当使用“虚拟方法”。如果类的方法将被多个派生类直接或间接地使用,则应当将其定义为“动态方法”。例如,某一个类含有一个被频繁重载的方法,并且有 100 多个派生类,则应将该方法定义为“动态方法”,因为“动态方法”可以减少内存的开销,而“虚拟方法”会消耗大量内存。

      “抽象方法”只能在那些从不允许创建实例的“抽象类”中使用。Delphi 不提倡使用“抽象方法”,而提倡使用“空方法”来代替“抽象方法”。例如:

    constructor TObject.Create; virtual; abstract{ 不提倡 }

    constructor TObject.Create; virtual; { 提倡,这个方法什么也没做,它的作用和虚拟方法类似 }
    begin
    end;

      所有存取类的方法都只能出现在类的 privateprotected 部分。属性存取方法的命名应遵循函数和函数的约定规则。“属性读取方法”必需以单词 Get 为前缀。“属性写入方法”必需以单词 Set 为前缀。“属性写入方法”的参数名称应为 Value,并且它的类型应是它所操作的属性的类型。

      尽管不是必须,但还是建议您使用“属性写入方法”来访问代表私有字段的特性。

    ----------

    10if 语句

      在 if ... then ... else 语句中最常发生的行为应放在 then 子句中,而其它发生可能性较小的行为应放在 else 子句中。

      尽量避免使用嵌套的 if 语句,在这种情形下应使用多个 if 语句来判断各种可能。

      不要使 if 嵌套超过 5 层。应该用其它方法使代码更加清晰、明了。

      不要在 if 语句中使用不必要的括号。

      如果在 if 语句中有多个条件需测试,这些条件应按计算强度由少到多的顺序从左到右排列。这样做能使编译器在编译代码时获得布尔估算逻辑的捷径,从而使你的代码获得最佳的优化。

    ----------

    11case 语句

      在一个 case 语句中各个独立单元的情况常量应以数字或字母顺序排列。

      每一个 case 单元的动作行为应保持简单而不应该超过四到五行代码。如果所要执行的动作过于复杂,则应采用独立的过程或函数。

      case 语句中的 else 子句只有当需要缺省行为或处理错误时才使用。

      case 语句应遵循其它结构的缩进和命名约定。

    ----------

    12while 语句

      在一个 while 语句中不建议使用 Exit 来跳出循环,尽量仅使用循环条件来跳出循环,必要的时候可以使用 Break 跳出循环。

      在一个 while 循环中所需要的初始化工作应位于 while 循环前面,而且不要被其它无关的语句隔开。

      任何结束后的处理应在循环之后立即进行。

    ----------

    13for 语句

      只有当循环次数已知的情况下才能使用用 for 语句取代 while 语句。

    ----------

    14repeat 语句

      repeat 语句的使用同 while 语句一样,并且遵循同样的通用方针。

    ----------

    15with 语句

      with 语句应小心使用,避免过度使用 with 语句,尤其在 with 语句中要小心使用多个对象或记录,以免使程序员感到困惑并难以发现问题所在。例如:

    with Record1, Record2 do

      with 语句遵循本文档所说明的命名约定和缩进的格式规则。

    ----------

    16、包

      运行时刻的包应只包含“其它构件包所要求的单元或构件”。另外,包含“属性、构件编辑器和其它只为设计的代码”应放入到设计时刻包中。注册单元应放在设计包中。


    ----------

    17、结构异常处理

      异常处理大量使用在错误纠正和资源保护方面。这就是说一旦资源被分配,必需用一个 try ... finally 来保证该资源被正确的释放。这种异常的保护也是指在一个单元的 initializition、finalization 或一个对象的 constructordestructor 中进行资源的分配和释放。

      try ... finally 的使用

      任何情形下,每一次的分配都应跟随一个 try ... finally

      try ... except 的使用

      只有当“在异常被触发而你想执行一些任务”时才使用 try ... except。通常,你没有必要为了只是简单地在屏幕上显示一个错误信息而使用 try ... except 语句,因为这会被 Application 对象自动执行。如果你想在 except 子句中执行完一些任务之后调用缺省的异常处理,使用 raise 来重新触发异常到下一个句柄。

      try ... except ... else 的使用

      try ... except 中的 else 子句不建议使用,因为它会打断所有的异常,包括那些你没有准备的异常。

    ----------

    18、代码调试

      可以使用“条件编译语句”帮助调试:

    {$IFDEF DEBUG}
      i := 100;
      ShowMessage(IntToStr(i));
    {$ENDIF}

      也可以使用“消息编译语句”帮助调试:

    {$MESSAGE '提示,编译会通过'}
    {$MESSAGE HINT '提示,编译会通过'}
    {$MESSAGE WARN '警告,编译会通过'}
    {$MESSAGE ERROR '错误,编译不会通过'}
    {$MESSAGE FATAL '致命错误,编译不会通过'}

      这样在编译过程中,会在 Delphi 的输出窗口中输出指定的文本,双击输出的文本,可以快速定位到语句行。其中前两种方法作用相同。

      也可以使用“断言”帮助调试:

    Assert(List = nil, '长度不匹配!');

      建议广泛采用断言,以增强程序的调试功能。断言是一种用于调试的条件判断,它表示程序执行到某一点时必须满足的条件,若条件不满足则引发 EAssertionFailed 异常。在调试环境时,设置编译参数 Assetions 为 On,正式版本中设置 Assertions 为 Off 。

      也可以使用“调试输出语句”帮助调试:

    OutputDebugString(PChar(S));
    OutputDebugString('输出提示信息');

      这样在调试运行阶段,执行到上面的代码后,会在 Delphi 的输出窗口中输出指定的信息。

      调试 Delphi 自身的单元文件的方法:

      如果要调试 Delphi 自身的单元文件,可以在工程选项中设置:Project -> Option -> Delphi Compiler -> Compiling -> Debugging -> Use debug .dcus(勾选即可)

      如果只想调试部分 Delphi 单元文件,可以将需要调试的 Delphi 单元文件添加到工程中来,这样在调试时,就可以对指定的单元文件进行调试,而不会跳转到其它 Delphi 单元文件。

      跟踪代码的方法:

      下断点时下在 begin 位置(而不是 begin 之后的代码位置),然后 F7 单步进入,这样可以捕获进入过程前的初始化部分,准确跟踪代码走向。还可以通过调用堆栈(Call Stack)窗口来查看代码的走向。

    ----------

    19、可读性

      编程首先考虑的是满足正确性、健壮性、可维护性、可移植性等质量因素,最后才考虑程序的效率和资源占用。一条语句只完成一个功能。复杂的语句阅读起来,难于理解,并容易隐含错误。变量定义时,一行只定义一个变量。保持代码的简单化是软件工程化的基本要求,不要过分追求技巧,否则会降低程序的可读性。

    ----------

    版权说明:作者:张颖希PocketZ's Blog
    出处:http://www.cnblogs.com/PocketZ
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    若本文为翻译内容,目的为练习英文水平,如有雷同,纯属意外!有不妥之处,欢迎拍砖

  • 相关阅读:
    关于ADO.NET参数化查询的提问
    PushSharp的使用
    关于WCF的一些知识点
    关于Expression表达式树的拼接
    设计模式-策略模式
    jq图片展示插件highslide.js简单dom
    JS实现手机访问pc网址自动跳转到wap网站
    CARVARS 圆形进度条
    vue-router的几种用法
    vscode 超好用的前端插件
  • 原文地址:https://www.cnblogs.com/PocketZ/p/2983074.html
Copyright © 2011-2022 走看看