排出PL/SQL最佳操作规程的优先次序并加以应用,完善新旧应用程序。
为开发人员提出一个"该做什么"和"不该做什么"的列表并不困难。但是,这个列表很容易让人完全不知所措,因为(a)记住所有的最佳操作规程可能很难,(b)实施最佳操作规程可能是个挑战,(c)确定一个团队的开发人员是否真正遵循这些最佳操作规程可能很麻烦。
任何一个开发机构所面临的挑战都是跟踪和应用最佳操作规程。
本文从实用角度出发,探讨了应用排出优先次序的最佳操作规程列表的几种方法,然后论证了一些关于代码是否遵循一系列建议的操作规程的自动分析方法。
将最佳操作规程铭记在心
尽可能地采用最佳操作规程,并以可重用代码块的方式来加以实施,如通用错误处理包。然后只需对开发人员进行培训并说服他们使用这些组件,他们便会自动遵循这些最佳操作规程。
请思考代码清单1中的代码。这是一种相当典型的错误处理逻辑:我要精确地说明我将如何完成这项工作,包括将信息输出到一个数据库表。代码中存在着一个重大问题,即:向日志表中插入数据的INSERT语句的执行变成了业务处理的一部分。回滚之后,日志会丢失。 我实在是应该利用自主事务处理方法啊!
不过,我不会逐一修改这些处理程序段,我会构建一个错误处理包,然后将它应用于每个处理程序段。代码清单2给出了这类程序包的一个简单示例的清单。代码清单3说明了此程序包在异常程序段的应用方法。
有了标准的错误处理包,你无需再忧虑如何向日志输出信息,也不必采用任何措施将异常程序段输出至该封装块。错误处理包会根据为该应用程序所定义的标准,完成这些所有工作。你可以大大缩短编写异常程序段所需的时间,而且你的代码会遵循团队所定义的最佳操作规程,你也不必考虑这些最佳操作规程是什么。
当然,通用的可重用包不可能照顾到应用程序开发的方方面面。你仍需编写大量的常规代码,而且还要注意这些PL/SQL代码行的最佳操作规程。因为跟踪所有最佳操作规程比较困难,所以必须排出它们的优先次序。
为新应用程序排出操作规程的优先次序
并非所有的最佳操作规程都彼此相当。有些对代码整体结构、可读性和可维护性的影响非常大。其他的最佳操作规程对代码影响要相对小一些。
不是要努力记住所有的最佳操作规程或强迫开发人员遵循所有这些策略,而是要提出一个最佳操作规程优先次序列表。要确定哪些是要遵循的最重要的最佳操作规程,还要确定如何遵循。然后创建一个短小而简单的列表,开发人员可以将它贴在计算机上或附近,以便非常方便地、经常地提醒他们。
在此我提出一些建议,用于最佳操作规程优先次序列表项和以下两种情况:新应用程序的开发和现有或原有应用程序的维护。
在构建新应用程序时,你完全有可能把它做好。最佳操作规程的主要侧重点应放在整体代码结构和可读性上,同时要给出一定数量的关键性能增强器的提示。由于篇幅限制,我无法非常详细地深入探讨这些最佳操作规程列表的所有主题。在以前的Oracle杂志和OTN文章中,我已经论及了其中的一些主题,在我的《Oracle PL/SQL最佳实践》一书中对其他的主题进行了讨论。我对新应用程序最佳操作规程列表项的建议如下:
不要编写SQL。当你需要某些数据时,不要编写SELECT INTO语句,而应调用一个能提取数据,并将所有标准的错误处理和优化逻辑都隐含在其中的函数。使用能处理大多数SQL需求的综合"数据封装包"会更好。
Oracle设计器可生成表格API(TAPI)包。也可以用PL/Generator生成这些包,PL/Generator是Quest软件公司提供的一个免费实用程序,可在www.stevenfeuerstein.com/puter/gencentral.htm获得。还可以使用Swyg,这是我在www.Swyg.com上提供的一个新产品。
带有特定SQL最佳操作规程列表提示的列表应包括以下项目:
编写微小的代码块。 在Oracle杂志2003年11/12月号中,我强烈建议代码的执行部分长度不应超过50或60行。这样随着时间的推移,该代码的阅读和维护会轻松许多。在新代码中遵循这一最佳操作规程的最佳方法是采用自顶向下的设计方法,同时采用局部模块或嵌套模块。OTN上我的《代码检查》一文(位于otn.oracle.com/pub/articles)详细地介绍了这种方法。
带有特定代码块提示的列表应包括以下项目:
从BEGIN到END的代码不超过50行。
创建局部过程和函数以隐含逻辑。
将所有的公式和商务规则都隐含在函数当中。
首先编写单元测试。开始编写代码之前,应先设计用于测定该代码能否运行的测试。如果一直等到写完程序之后才设计"测试",你会下意识地只编写你完全知道其(或希望的)功能的条件和逻辑"测试"。如果首先编写测试,你就可以专注于代码库的整体设计及与单个程序的接口。
当然,编写测试代码本身就是一个非常大的话题,自然也是一个非常大的挑战,但是我建议利用Ounit和utPLSQl:面向PL/SQL开发人员的免费的、自动化单元测试软件,可在www.ounit.com网站获得。开诚布公的讲,是我设计了这两个工具,而且其总开发师也是我。
你的列表应考虑到这些测试项:
编写代码之前编写测试实例。
编写测试实例来验证错误报告。
编写测试实例来验证成功的改进。
利用自动框架(Ounit和utPLSQL或自编的实用程序)来执行测试实例。
为维护排出操作规程的优先次序
许多PL/SQL开发人员将相当一部分时间都用在了维护现有应用程序上。 这种工作往往难度很大,容易使人灰心,因为许多代码写得都很差,难于理解,而且绝大部分都没有经过测试。 几乎每个应用程序都有一个"黑洞"程序: 那些毫无结构化可言、使每个人都望而却步的极大的代码块。 如果在第255行作一下修改,那么整个程序中可能会引入25个错误。 还没有办法让人真正知道所做修改对整个代码会产生什么影响,因为还没有适用的回归测试。
如需将最佳操作规程用于现有的应用程序,应当采用递增和迭代的方式进行修改。 仅仅因为现行的生产应用程序能够编写得更好,开发经理就支持对其进行修改是比较困难的。
如果必须打开黑洞程序,你应当应用关键性的最佳操作规程,而且其应用应当有限。 以此方式进行修改的最佳操作规程列表的一些建议如下:
编写一个回归测试。这可能是一项既费心又费力的工作,但如果你对维护一块代码还抱有一线希望,也还有信心,你就必须完成这项工作。开始维护现有程序之前,应尽可能多地思考能够验证程序工作情况的那些测试条件。在一个测试包中执行这些条件,运行该代码,并确定该程序运行是否正常。接下来,在进行修改时,可以重新运行这一测试,并确保没有引入任何错误。此外,Ounit与utPLSQL此时也可以大显身手。
构建隐含功能可识别区域的局部模块。 程序的执行部分可能长达1000行。从该执行部分的顶部开始,向下通读整个代码。假如可以确定其中的20、30或100行代码是用来验证参数和初始化数据的,就可以将所有这些代码行从该执行部分取出,并代之以一行代码:
initialize_data;
然后,将这些行移至声明部分,其中的局部过程上下文如下:
PROCEDURE initialize_data IS
...all that code...
END initialize_data;
随着时间的推移,这个不可读的执行部分将变得越来越小、更易于访问。
从性能的角度来看,应查找可应用FORALL和BULK COLLECT的区域,几乎所有情况下使用它们都能大大提高性能。找出程序中所有的DML语句。如果它们出现在任意的一种循环内部(游标或其他类型),则将所有的DML逻辑取出,代之以过程调用;将此逻辑作为一个局部模块移至声明部分;然后将其改进以进行批量处理。
验证是否遵循最佳操作规程
你要购买书籍、编写列表、传授最佳操作规程。接下来是团队中的所有开发人员编写他们的代码。即使是对于已经排出优先次序的建议,要让每个人(无论谁)都记住并遵循也不太可能。
因此你必须决定:是让这些最佳操作规程都变为可任选的(这意味着其中的大部分都将被忽略),还是努力确保人们都遵照它们行事。
我建议你应该找出用于检查团队开发人员所编代码(或者你自己编写的代码,因为即使有了最好的计划,你也会遇到困难,你必须做对每一件事!)的方法。验证是否遵循最佳操作规程的两个最好方法是代码复查和代码分析。
仔细检查代码!未经不同的开发人员(除代码编写者之外的人)检查,任何代码都不能移交给质保人员(QA)或者运行于生产环境中。代码复查可以表现为从极限编程(Extreme Programming)的结对编程到简单的伙伴系统(Oracle杂志2003年11/12月号进行了探讨)等多种形式。
在结对编程时,任何程序员都不是独自编写代码。每个工作站前面都坐着两个人,代码的每一行都由两个人进行检查和评估。显然这是一种极端的作法,尽管这样可以提供巨大价值,但极少有开发团队这样做。
有些机构具有正规的代码复查过程,所有的开发人员都将其代码提交给其他所有开发人员并获得反馈意见。其他机构采用一些非正规方法:高级程序员只负责代码的整体情况,有时也会停下来检查其他开发人员的代码并提出建议。
用SQL分析代码。如果你开发的是大型应用程序,当然就会有几万行的代码。复查每一行代码可能完全不切实际。在这种情况下,自动化的代码分析非常重要。 还好,PL/SQL语言可用于这种分析。
无论何时需要编译程序,Oracl