注意:
  通常我可以愉快地连续编程5-6小时。在好的日子里、我也可以愉快地写作这么长的时间。但有时我会感到厌倦。在那些场合下,我就会找到自己喜欢的技术人员写的一本书或一篇文章,然后只阅读看起来像是包含有重要的或有趣信息的一章。看完之后,我可能连着几个月再也不看它了,也有可能下一次休息时又会拾起它去读一下。
    有时,我可能会发现其中的一部分吸引了自己的注意力,或者确实想弄明白其中的内容。在这样的情况下,我会连续花几天时间闲话3、4章。但是,我还是很少把一本技术书籍从头到尾全部看完,这大让人感到策缩了, 特别是对于那些长达1000页或者页数更多的书籍来说更是如此。
    花1小时左右的时间来阅读一本好书可以给我的头脑充电。读完后,我就又可以继续编程或写作了,而阅读一本参考手册或是一本指南一两个小时,则会使我精疲力尽。我发现读这种书要比自己编写代码或写文章更困难。这意味着我根本就不会去读那些书,它们只会在书架上落满尘土。>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>    本书的主题来源于George Sand说过的一句话,我一直把它钉在我的书桌上:“简单性是这个世界上最难获得的东西;它是经验的最终界限,也是天才的最终努力目标。”
    每本书都需要一个主题,本书的主题看起来可能同它面向的读者相矛盾。我说过这本书是针对中级和高级程序员的,但我的主题是“尽一切所能,让程序尽可能的简单。”
    经常会听到这种说法,编程不像是一门科学,而更像是一门艺术。如果编程是一门艺术,那么我们就必须找出它所基于的美学原则。根据我的意见,核心的原则就是简单性。美丽可以通过几种不同的途径获得。我最喜欢的一条途径就是遵循简单性的道路。
    在编程世界中,几乎所做的单独的每一步部是简单的。说到底,编程是一个非常简单的职业。之所以看起来困难,是因为它需要把许多非常简单的过程组合起来。两个简单的事情要比-件简单的事情稍微复杂一点。二十件简单的事情就明显要比一件简单的事情复杂多了。对于大多数人来说,把一万件简单的事情放在一起就很复杂了,当然,有少数人例外。
    在一个典型的程序中,成百上千个独立的片段合在一起组成一个整体。如果看得足够透彻的话,即使是一个简单的Delphi窗体也是内上千个复杂的片段组成的。作为程序员,目标是要协调所有这些不同的片段,让它们一起工作。
    我相信所有程序都应该努力遵循简单性的道路。而且.我还相信编程的工作也应该简单。这本书致力于找到能够使你更容易地创建出强大程序的方法。我努力让我的目标做到适度,节约使用资源,既符合我的美学选择,又不过分。我努力创造既使用简单又易于理解的程序。
    我希望我的程序对于用户和程序员来说都是容易理解的。一个好的应用程序的体系结构应该具有和它的菜单系统同样简单的结构。帕台农神庙的建筑结构是建立在追求简单的建筑学原则的基础上的,我相信Delphi程序也应该以同样的模型作为基础。
    达本书不打算让干到凌晨4点,来挖拥程序中最深入的部分。应该能够用一种简单、容易的方式按时完成工作。这本书偶尔也会集中挖掘DeIphi中最深入和最秘密的部分,但我总是推行一种简单、自然和强大有效的方法来完成这些工作。
    编程不仅仅是一个技术工作,它也是一种心态。好的程序员表现出一种明智的风格。他们编写代码的方式和他们生活的方式是一样的。如果生活得简单而轻松,那么写的代码也会是简单和容易的。
    如果你能够发现有一体小念头,可以把简单的项日变得比初看上去复杂时,就进入了设计阶段。例如,我最初可能不会想到需要报告、保存状态以及创建某种图表。
    我经常能够用15分钟或1小时的时间就设计出一个东西,但要执行它却要花费我整整一天或几天的时间。要避免的陷阱是花费几大的时间来编写一个本质上就有缺陷的东西。如果仔细思考15到20分钟,可以为我节省两天编写程序的时间,那么花这点时间是值得的。

解决方案 »

  1.   

    螺旋式上升        有时,如果不写一些测试代码,我就无法把设计过程进行下去。在这样的情况下,我会进行一些试验,来测试我的理论的有效性。当我开始看到一个算法的轮廓时,通常我会停下来并把设计方案定下来。然后我可能会再编写一些代码,然后再重新研究一下项目的设计。
        这个过程是不断循环直到结束的。写一点代码,停下来看一看目标,然后再停下来研究一下设计问题,然后再写一些代码。
        这个过程最后应该像一个螺旋那样结束。从底端的一个大圈开始,然后不断重复编码和设计工作,从而使工作的圈子越来越小。每个循环都应该比上一个更小,  直到最终达到顶端。在顶端,园子可能已经小到了一个点(最佳方案)。于是,就确定了程序的正确实现方法。>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>注意灵活的事件处理程序    没有什么比不加区分地选样事件处理程序能够更快地引导OOP程序员走向毁灭的道路了。Delphi允许使用事件处理程序把代码添进主窗体中,这种简易性拉次都会使寻求发现对象的努力受到挫折。
        在人多数情况下,把复杂的、低级的代码放在定义窗体的文件之外是一个好主意。复杂而低级的代码届了独立的对象,而不属于主窗体。
        窗体的实现文件是存放用户界而代码的好地方。如果发现自己正在某一个PAS文件中编写大量复杂的逻辑操作,那么这正足‘个好机会,这说明一个对象触子可及,需要把这个对象标识出来并移到它自己的模块中去。
        举例来说,我近来正在编写一个窗体,它有许多关于从几个不同的资源中读取字符串的复杂的逻辑。代码要把字符串从资源个读出来,保存在列表中,然后把列表显示给用户。在花了一些时间查看我的程序之后,我得出了一个结论:用来读取资源并把它们转换到列表中去的代码确实是一个独立对象的一部分,而与主窗体毫无关系。所以,我把它从窗体中移出来,粘贴在它自己的模块里,然后用下面这样的代码束调用它:
        ResoureceObject := TResourceObject.Create;
        ComboBox1.Items := ResourceObject.GetItemList;
        ResourceObject.Free
        这几行里根本没有什么复杂的逻辑。它们也没什么问题。TResouceObject中所有棘手的代码都是由构造函数或GetItemList方法调用的(现在,这些代码的确切情况并不重要只需要知道它有40到50行字符解析以及创建一个列表的内容)。这样做的日的是用TResouceObject把复杂的事物封装在一个单独的对象中,这样我的窗体代码仍然还可以保持清楚和易于使用。
        再说一次,我的观点并不是说编均复杂的代码不对,我是说应该把复杂的代码封装在对象里。采用达种方式,调用它时可以减小不小心犯错误的风险。
        这样组织程序的另一个理由是便于重用。如果我把读取和解析资源的代码都包在单独的窗体里,那么会引起两个问题:
        ·那个窗体很可能还要容纳该程序其他特定处理过程所要求的逻辑。我将无法把处理资源的代码独立出来,而只能把它和其他一大堆运行窗体所必需的代码混在一起。
        ·即使我认为我可以重用那些代码,重用它的最好途径也只能把整个窗体复制到新项目中去。事实上,把窗体复制到新项目中去的行为本身并没有什么缺陷,因为那个窗体将会用一种方便的包装来封装逻辑。但是如果我需要把握窗体里的代码的话,那么问题就来了。在这种情况下,几乎肯定会发生像下面这样的情况:我修改窗体里代码的方式可能会使得第一个项目中的窗变得不能用了。在这种情况下,我需要复制两份代码:一个在新项目里,一个在旧项目里。如果我对其中某一份代码进行了修改,那么我还得回去修改在另一份中的同样的代码。你也知道,几乎无法指望什么人能确实修改两个地方的同一个错误,所以麻烦很快就来了。相反,我可能会决定在两个项目小都保留同一份代码,但我将不敢在其小任何一个程序中对它进行修改定制了,因为这可能会损害另一个。其结果是,对于某些次要的界面问题,我可以很容易地看到补救办法、但却由于受到人为的限制而不能进行修改。
        简而言之,通常情况下,把某些种类的代码封装在窗体中都不是好主意。取而代之的是,可以把代码放在一个独立的、易于访问的对象中。然后可以在可能会建立的任何窗体中编写接口代码访问该对象。在窗体里,只需要接口代码。低级代码则放在对象中。
        按这种方法编程可能会迫使你当时多写几行代码,但是以后当需要定制界面或对对象进行基本维护时,它会节省人量时间。它还使得代码更便于重用了。
      

  2.   

    感到懒于理清程序的环节    有时,你会发现对象的工作是重复性的。例如,我可能为运行一个窗体工作了一段时间,并发现程序最终开始正常工作了。如果我是刚刚接触编程的话,我会认为我已经抉要完成该窗体了。但是现在我想要梳理整个窗体,找出需要发现并给予独立范围的对象。
        这是,懒惰常常会把我带上歧途。最初时,通常比较容易把一个对象埋没存另一大块程序代码段中。直到后来,这种懒惰会缠住我并给我带来麻烦。
        当窗体的某一部分运行正常时, 正确的选择通常是把那部分程序的代码从窗体中取出来,并把它放到它自己的对象里上。这项操作会化掉一些时间,但以后它就会节省时间。然后就可以回过头去继续加工窗体。过了一段时间以后,又需要再检查窗体以找出隐藏的对象。
        近来,我正在对一个数组进行大量复杂的计算。过了一段时间以后,我发现实在需要把那个数组放在一个单独的对象中,那样的话我就可以编写像下面这样的代码:
    GridArray := TGridArray.Create;
    AResult := GridArray.PerformCalculations(Data1, Data2, Data3);
    GridArray.Free;
        现在,有一部分以前插入在我的窗体中的工作已经封装到TGridAarry对象中去了。
        当我第一次采用这种做法时,似乎做了大量痛苦的工作,却没有带来多少效果。不过,后来我发现需要在主窗体中创建一系列的TDaiIyTotal对象,它们中的每一个都需要进行数组计算。由于我采用了正确的程序结构,我所需要做的全部事情就是把TGridArray对象传递给TDailyTotal对象,然后让它们用自己的数据集合调用PerformCaIculations方法。简而言之,我并没有费多大的力气.就使我的程序结构清楚合理。
        如果我没有创建TDaiLyTotal对象和TGridArray对象,我将很难编写出易于维护和理解的代码。在我的窗体中将会有3或4个方法用于数组计算,还有3或4个方法用于建立每日总计。从一个方面看,每日总计的方法应该调用grid的方法。但我如何能指定一组方法属于某-个任务,而另一组方法属于另一个任务呢?我如何定义两组方法之间的联系呢?对于这些问题没有任何好的答案,因为这个程序的程序结构要求使用TDailyTotal对象和TGridArray对象。它们是必不可少的对象,就像TApplication和TDataSet是VCL程序结构中必不可少的部分一样。
        当我发现了TDailyTotal和TGridArray对象之后,我的程序就集合了简单和易用的特点。而且我确信,如果过几个月或几年以后,需要我问头重新看这个程序,我也可以立刻弄清楚它的程序结构。如果没有这些对象,那我就得在我的窗体中翻来覆去地给这些意大利面条似的代码分类,这会用掉我几个小时其至几天的时间。
        这里关键的一点是:我必须重复不断地梳理我的代码以找出对象。当我发现了对象时,我必须克服以往的惯性,强迫自己把它们分离出窗体或是我建立的其他模块。这时,可能看起来像是白费力气,但是从长远眼光束看,这是值得的。>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>避免使用隐藏数据交叉链接对象    好的OOP程序员从来都不允许对象共享私有数据。他们总是设计出独立的对象,只允许其他对象通过指定的接口来使用它们的数据。
        这些规则之所以重要,有如下两个原因:
        ·它们可以促进重用。如果把两个或更多的对象通过它们的数据牢牢地绑到了一起,那么要想在某个项目中单独使用其中一个对象就比较困难了。对象互相绑在一起,很难把它们分开。
        ·面向对象的程序设计的初衷是把任务封装在单独的对象中。这么做的主要原因之一是它可以限制可能发生问题的范围。如果谨慎地建立一个不依赖于其他对象的对象,那么就限制住了那个对象可能发生问题的领域。而如果允许两个对象把它们的数据密切捆绑在一起,就立刻把潜在问题的范围从一个对象扩大到了两个对象。问题领域成倍扩大了。因此进行维护工作至少要比以前困难两倍。
        严格遵守封装的原则会大大地有助于建立短小、简单的程序。而破坏封装性和不加选择地在对象之间共享数据将会结程序增加不必要的复杂性,并破坏程序结构的纯度。
        例如,如果我把前面那一部分的TDailyTotal对象和TGridArray对象用共享数据的办法连接到一起,那么就不太容易重用TGridArray对象了。例如,如果我发现需要建立TMonthlyTotal对象,然后希望把TGridArray对象传递给它,这样就实现了重用。但是如果TGridArray对象捆绑在TDailyTatol对象的数据上,重用就会很因难。事实上,我很可能不得不重新写一个TGridArray对象,以便能够重用它。最后,我打能会以写一个TDailGridArray对象和一个TMonthlyGridArray对象而告终。这种安排,虽然可能是有效的,但它很可能预示着建立了一个不必要的和过于复杂的程序结构。
      

  3.   

    看过,是《Delphi4编程技术内幕》里面的。