>第一篇-正确书写代码</P>- ]% D( W5 y; ?' S& V9 U8 P5 c
>1. 简介</P>$ x* L2 O" @! m/ I% x
>2. 书写干净的代码</P>' m% Z" C/ i/ q. g( ?# B
>3. 使用异常及异常处理能力</P>
>4. 使用记录(logging)机制</P>3 T8 T2 q' h0 A0 c" x% ^
>5. 结合使用记录机制与类的异常处理机制 </P>
>6. 处理您代码外产生的异常</P>
>7. 你的回合</P>
>8. 版权说明</P>- Q1 R2 U6 ^ A" h( |+ B7 c
>简介
>书写干净的代码</P>
>首先而且也许是最重要的一点是书写干净、可读的代码是极其重要的。能够在写完一段代码后回顾一下并给它加上注释来说明这段代码用来做什么和为什么这么做,将会省去你以后跟踪代码的无数个痛苦的小时。也许你会多花一点时间来书写,但当你花过N小时来跟踪那些难以捉摸的BUG时,你就会同意多花点时间来让程序代码可读是多么值得了。(你本可以很容易完成除错的)。如果没有这么做过,我建议你停下来,读读另一篇Scott的精彩文章-代码的风格(大家需要的话,将会尽快翻译)。</P>
>使用异常及异常处理能力
>所以他们决定….,okay,我们需要一个新的机制,一个你不能忽略的。但你可以处理,定制(自定义 customize)。异常就此出现了。想要一个特殊的错误类型标志?容易的很,定义一个新的异常类型(不过是一个类,没别的),抛出来(产生这个异常)。完了。</P>
>例子:</P>
>class MyException# B! a# n- P, R
>
>接着还有更多的内容。如果你希望对某个异常做些什么,又不希望异常就此消失,你可以重新抛出(产生)这个异常。它将继续向后寻找新的catch()过程来处理它。我不能说我经常这么做。但最好应该知道,就象“抛出”一样简单。就是这样,throw将带着已经被你处理过的异常继向后寻找另一个catch来处理它。</P>
>最后而不是最不重要的 (这部分不包括在标准规范中,倒更象是Borland专有的增加版)就是 __finally 声明,使用一个 __finally{ } 模块,你可以指定不管有否异常产生都将运行的代码。这里是清除你通过new方法分配的局部变量及将所有应该设定回正常状态的标志复位(例如将一个等待状态的鼠标指针复位成正常状态)的最方便的地方。</P>
>呸,太多了!休息一下吧,有空可以看一看C++Builder帮助中的Exception类, (所有E开头的,你会注意到它们都是从Exception类继承来的。这也是定制你自己的异常类的好练习!) 当你回来时,我们将进入下一步旅程。</P>5 j9 [4 D$ `( O. E, u' t$ n
>使用记录(logging)机制</P>/ F" v) |2 l' M M4 U
>您不可能总是使用除错器来除虫,有时你没法依靠内建除错器的力量,所以有时你将不得不求助于其他的除错手段来调试程序。(典型例子如:NT服务、ISAPI/CGI程序、实时应用程序…等等)此时您将不得不求助于我们这样经验丰富的程序员才会谈到的老式的除错/调试技术。例如产生使用某种记录(logging)机制来看看程序的头巾下面到底发生了什么的念头。幸运的是,有许许多多的现成的机制可以让我们的这项工作变得容易些。这里我将谈到我所偏爱的三种方法,你也可以将您自己的方法email给我,我会考虑加入这一部分。</P>
>Okay 先说第一种,(调试/除错输出字串)OutputDebugString。幸运的是Microsoft已经为我们实现了一个非常广泛的调试/除错子系统。包括实现您自己的调试/除错记录系统的机制。程序在一个调试/除错进程内运行的时候,OutputDebugString将它的参数(一个c string)输出到调试/除错器的输出上下文,若调试/除错器没有运行,OutputDebugString就被忽略。如果没有弹出消息的时候,OutputDebugString在终端上也可以很好的运行,当你分发给客户前别忘了移去它(通过 #ifdef DEBUG…#endif’),程序可以运行的更快一点。“Wow,又好又容易!”你也许会说“但当程序不能在调试/除错器内运行时,该怎么办?”</P>
>请牢记,这只是我的观点,基于一种观念的评价,我个人使用Gexperts的dbugint.pas界面来调试/除错。这是个非常优秀的独立的小程序。如果愿意,您可以将它分发给你的客户们。如果没有这么做,象OutputDebugString一样,如果没有安装,它实际上就什么也不做:)(它将注意终端是否已经安装在机器上)。要使用dbugint.pas的话很容易,将它加入你的工程并加上 #include "dbugintf.hpp"(因为是pascal文件,你必须将它加入你的工程以便C++Builder编译器生成hpp头文件。)然后你只需使用SendDebug(“要送到记录中的字串”);或者你也许想更灵活些,还有SendDebugEx-增加一个消息类型参数来调用TmsgDlgType(详细说明参考VCL在线帮助),SendMethodEnter, SendMethodExit, and SendSeparator 等等(十分自解释的名字)。只是别忘记加入必须的package包,若你打算将此终端(Gdebug.exe)其给你的一些最终用户的话。Gexpert可以从<a href="http://www.gexperts.org/" target="_blank" >http://www.gexperts.org/</A> 获得并且是免费的。</P>
>第三种我要指出的是,这也许是最难的选择-实现你自己的记录控制台。可没有你想的那么简单!你也许首先会想到“扔个Richedit控件在form上,将它设为只读的,然后开始记录,对吗?” 错!理论上挺好,但实践呢,使用RichEdit控件来记录将降低程序的运行速度、使内存破碎,丢失、通常会在10分钟内使整个机器慢下来!!(要说明白为什么得花上点时间才行,但我向你可以保证)。所以你所需要的是计划好你的记录机制的需要,并开始计划一个定制控件若你想要个彩色的图标的话。还有一个选择,需要做点工作,但可是非常有效。就是使用一个ListBox控制来记录,并将Style属性设为lbOwnerDrawFixed,这样句柄将会自绘。(这也是Gexperts和它的Gdebug console所做的)。要做许多工作,但哈哈,如果你想做…</P>8 H6 Z8 c: `( m1 _* C6 i
>结合使用记录机制与类的异常处理机制2 e: o8 }2 T! N6 E
>try $ a1 i: q2 P- ~+ C5 @# s& U U
>Okay,是时候回顾一下了。ClassName()方法是如何帮助我们的?不想每次都只得到一个“Exception“串就完了吧?难道是因为将E声明为一个异常?不对。这是VCL比较酷的部分,任何从Tobject继承来的类能够自动知道其自身的类型、其基类的类型、等等许多有趣的信息,你可以察看Tobject的帮助。所以尽管我们使用的是Exception &E,E.ClassName()将会找出我们得到的异常的实际的类名(译者注:C++的多态性)。这些好处的代价就是可执行文件的体积更大了,几乎所有的C++Builder/Delphi程序员都会发现这一点。(No Pain, No Gain)没有痛苦,就没有收获.他们说….</P>3 h- Q* M+ j8 w/ t- j' f/ Y
>Xiphias增加了TstringList的AddingLine方法,SavetoFile方法是另一种记录(logging)的有效形式。最后应该保证你的应用程序总是写记录文件(logfile),或这每次捕捉到异常时重写记录文件。</P>
>处理您代码外产生的异常| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |