国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開發(fā) > 綜合 > 正文

為 PL/SQL 構(gòu)建代碼分析實(shí)用工具(二)

2024-07-21 02:34:33
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  第一部分:構(gòu)建一個(gè)代碼分析實(shí)用程序以確保代碼首次運(yùn)行時(shí)的流暢和正確
  
  構(gòu)建實(shí)用程序驗(yàn)證代碼質(zhì)量的內(nèi)部詳情
  
  許多開發(fā)人員和開發(fā)經(jīng)理所面對(duì)的一個(gè)突出問(wèn)題就是找到改進(jìn)代碼質(zhì)量的方法。于是我決定以一種獨(dú)特的方式來(lái)解決這一難題。在隨后的幾個(gè)月中,我將在 OTN 上發(fā)布一系列文章說(shuō)明我是如何構(gòu)建 Codecheck 的。 Codecheck 是依靠數(shù)據(jù)字典中的信息,執(zhí)行重要任務(wù)(即分析程序包以檢測(cè)這些程序包是否包含重載多義性)的一個(gè) PL/SQL 程序包。由于我采用的是自頂而下的設(shè)計(jì)方法并運(yùn)用了許多我在 《 Oracle PL/SQL 最佳實(shí)戰(zhàn)技巧》 中推薦的最佳實(shí)戰(zhàn)技巧,因此不想只是簡(jiǎn)單地呈現(xiàn)結(jié)果,而更愿意邀請(qǐng)您和我一同演練這一過(guò)程。
  
  深入了解這一實(shí)用程序要花費(fèi)一些時(shí)間,因?yàn)槲蚁虢柽@個(gè)機(jī)會(huì)實(shí)際經(jīng)歷一下開發(fā)生命周期中的幾個(gè)階段。在以后的幾個(gè)月中,我將進(jìn)行以下工作:
  
  確定我希望 Codecheck 解決的問(wèn)題并明確需求。
  給出驗(yàn)證實(shí)用程序正確運(yùn)行的測(cè)試案例。
  研究有助于解決問(wèn)題的相關(guān)技術(shù)。
  給出實(shí)用程序的整體設(shè)計(jì)(結(jié)果發(fā)現(xiàn)測(cè)試要求會(huì)對(duì)我的設(shè)計(jì)產(chǎn)生影響)。
  逐步細(xì)化以采用易于編寫、理解和部署的代碼塊來(lái)構(gòu)建解決方案。
  利用 utPLSQL 單元測(cè)試框架自動(dòng)對(duì)實(shí)用程序進(jìn)行復(fù)雜的回歸測(cè)試。
  通過(guò)對(duì) Codecheck 及其相關(guān)概念的學(xué)習(xí),您將了解到 Oracle PL/SQL 最新、最好的一些特性,如多層集合。此外,我還將提供一套平臺(tái),您可以在該平臺(tái)上構(gòu)建和添加自己的 QA 檢查,例如檢查參數(shù)是否太多或太少、查找所有程序包都要用到的程序,并確保代碼符合命名規(guī)則。也許親身演練的最大好處在于有機(jī)會(huì)看到實(shí)際運(yùn)用的一些最佳實(shí)戰(zhàn)技巧,這可能是學(xué)習(xí)如何使用這些技巧最簡(jiǎn)單的方法。
  
  我需要聲明一點(diǎn):我已經(jīng)完成了 Codecheck 的一個(gè)運(yùn)行版本。我計(jì)劃一邊寫下該實(shí)用程序的構(gòu)造經(jīng)過(guò),一邊對(duì)其進(jìn)行改進(jìn)。因此,該系列每一篇文章的下載都將包含一個(gè) Codecheck (codecheck.zip) 。請(qǐng)隨意下載并立即使用。假如您在調(diào)試的過(guò)程中碰到什么問(wèn)題,或是有一些改進(jìn)意見(jiàn),請(qǐng)發(fā)送至 steven@stevenfeuerstein.com 。
  
  確定問(wèn)題:程序包中的重載多義性
  
  為了寫出高質(zhì)量的程序而顧及到方方面面會(huì)令人發(fā)瘋。因此,我打算集中到幾個(gè)典型的問(wèn)題,以免屢屢受挫而不得不放棄創(chuàng)建 Codecheck 的初衷。編寫和成功編譯包含不可調(diào)用程序的 PL/SQL 程序包是極有可能的,而這并沒(méi)有多大的意義,不是嗎?讓我們來(lái)看看這一希奇的情形是怎樣出現(xiàn)的。
  
  Oracle PL/SQL 支持負(fù)載,也就是所謂的 靜態(tài)多態(tài)性 。這就意味著,您能在任何聲明段或程序包中用相同的名稱定義兩個(gè)或多個(gè)程序,只要這些程序區(qū)別顯著(通常是參數(shù)列表不同),編譯器能夠辨別您想要使用哪個(gè)程序。重載對(duì)于提高代碼的可用性來(lái)說(shuō)是一項(xiàng)有用的技術(shù)。然而,它也會(huì)帶來(lái)一些問(wèn)題,非凡是假如參數(shù)列表很長(zhǎng),其中的參數(shù)有些有缺省值,有些沒(méi)有,則尤其如此。
  
  為了向您證實(shí)開發(fā)人員的確會(huì)面臨這一問(wèn)題,我挑選了幾個(gè)可能會(huì)出錯(cuò)的例子,這些例子是以下面所示的程序包說(shuō)明開頭的:
  
  CREATE OR REPLACE PACKAGE salespkg
  
  IS
  
  PROCEDURE calc_total (zone_in IN VARCHAR2);
  
   
  
  PROCEDURE calc_total (reg_in IN VARCHAR2);
  
  END salespkg;
  
  /
  
  這一部分在編譯時(shí)不會(huì)有任何問(wèn)題,正如其程序體一樣。其中有兩段重載程序,都命名為 calc_total 。其中之一接收一個(gè)地段,例如 ' ZONE 15 ' ,然后計(jì)算該地段的總銷售額。而第二個(gè)程序則接收一個(gè)區(qū)域,例如 ' SOUTHWEST ' ,然后計(jì)算該區(qū)域的總銷售額。但當(dāng)我試圖調(diào)用其中某個(gè)程序,卻出現(xiàn)一個(gè)錯(cuò)誤。
  
  SQL> exec salespkg.calc_total ('ZONE 15')
  
  BEGIN salespkg.calc_total ('ZONE 15'); END;
  
  *
  
  ERROR at line 1:
  
  ORA-06550:line 1, column 7:
  
  PLS-00307:too many declarations of 'CALC_TOTAL' match this call
  
   
  
  該錯(cuò)誤消息明確地指出了這一問(wèn)題: "Too many declarations of CALC_TOTAL match this call." (有多個(gè) CALC_TOTAL 的聲明與該調(diào)用相匹配)。您可以看到,計(jì)算機(jī)并不是十分的聰明。您我都可以看出 ' ZONE 15 ' 是一個(gè)地段;難道 PL/SQL 編譯器就不能識(shí)別出這是 " 地段 " 的 calc_total 嗎(即帶有 zone_in 參數(shù)的重載)?不幸的是,編譯器并不是這樣工作的。 ' ZONE 15 ' 是字符串的字面意義,編譯器無(wú)法分析。編譯器無(wú)法知道應(yīng)該使用哪段程序,然后就甩手不管了。
  
  我們?cè)撊绾谓鉀Q這一問(wèn)題呢?在這種特定情況下,我可以通過(guò)使用指定的參數(shù)值來(lái)消除多義性:
  
  BEGIN
  
  salespkg.calc_total (zone_in => 'ZONE 15');
  
  END;
  
   
  
  在這個(gè)實(shí)例,我想要告訴編譯器使用特定的參數(shù) ( zone_in ) 。
因?yàn)檫@兩個(gè)重載程序中,只有一個(gè)程序的參數(shù)名與之相符,這樣編譯器就知道該調(diào)用這兩個(gè)中的哪一個(gè)了。盡管如此, 不得不 使用參數(shù)名引用來(lái)調(diào)用一個(gè)過(guò)程或一個(gè)函數(shù)還是令人難以接受。這明顯是一個(gè)糟糕的設(shè)計(jì) — 而且會(huì)越來(lái)越糟。考慮下面的程序包說(shuō)明:
  
  CREATE OR REPLACE PACKAGE salespkg
  
  IS
  
  PROCEDURE calc_total (zone_in IN VARCHAR2);
  
   
  
  PROCEDURE calc_total (zone_in IN CHAR);
  
  END salespkg;
  
  /
  
   
  
  同樣,這個(gè)程序包在編譯時(shí)也不會(huì)有任何問(wèn)題。但現(xiàn)在又面臨另一種情況:無(wú)法調(diào)用這些過(guò)程中的任意一個(gè)。他們共享程序名和參數(shù)名。唯一的區(qū)別就是數(shù)據(jù)類型。 VARCHAR2 當(dāng)然不同于 CHAR ,因此編譯器會(huì)讓您輕松過(guò)關(guān)。但不幸地是,這兩種數(shù)據(jù)類型的差異性還不夠大,這將導(dǎo)致在真正試圖使用代碼的時(shí)侯出現(xiàn)難題。考慮下面的一段代碼:
  
  BEGIN
  
  salespkg.calc_total ('ZONE15');
  
  END;
  
  ' ZONE 15 ' 是固定長(zhǎng)還是可變長(zhǎng)? PL/SQL 文檔中說(shuō)道 "All string literals except the null string ('') have datatype CHAR ," (所有非空串的字符串文字都是 CHAR 型)但是編譯器并沒(méi)有意識(shí)到這個(gè)問(wèn)題。非常希奇,即使向程序傳送了一個(gè)顯式聲明為固定長(zhǎng)度的字符串,仍然會(huì)出現(xiàn)問(wèn)題。
  
  SQL> DECLARE
  
  2 l _zone CHAR(6) := 'ZONE15';
  
  3 BEGIN
  
  4 salespkg.calc_total (l_zone);
  
  5 END;
  
  6 /
  
  salespkg.calc_total (l_zone);
  
  *
  
  ERROR at line 4:
  
  PLS-00307:too many declarations of 'CALC_TOTAL' match this call
  
  如您所見(jiàn),確實(shí)可以定義這樣一個(gè)程序包重載,即它可以順利通過(guò)編譯,但要么不可用,要么只能通過(guò) " 非自然行為 " 使用,例如強(qiáng)制使用參數(shù)名引用。
  
  我將采用什么樣的解決方案呢?
  
  為了識(shí)別這些重載問(wèn)題,我產(chǎn)生如下的想法:也許我可以構(gòu)建一個(gè)實(shí)用程序 " 自動(dòng) " 掃描程序包,檢查所有可能的有效程序調(diào)用置換,并提醒我注重那些多義重載。我能夠作到這一點(diǎn)嗎?看起來(lái)我應(yīng)該要能夠?qū)⒊绦虬x解析為各段程序,同時(shí)解析出每個(gè)程序的參數(shù)列表。我應(yīng)該能夠取出這些參數(shù)的數(shù)據(jù)類型和缺省值。我如何才能獲得這些信息呢?遺憾的是,我對(duì) PL/SQL 解析器沒(méi)有 API 級(jí)的訪問(wèn)權(quán)限,非凡是不能從 PL/SQL 自身內(nèi)部來(lái)進(jìn)行訪問(wèn)。而且我壓根不想 考慮 自己編寫一個(gè)解析器。那么一個(gè)積極的(深受困擾的)實(shí)用程序構(gòu)造者會(huì)如何去做呢?他會(huì)查找可以替代的方法。
  
  還有沒(méi)有其他的方法可以從程序中提取這一信息呢?我想起每當(dāng)我編譯一個(gè) PL/SQL 程序, Oracle 數(shù)據(jù)庫(kù)就會(huì)對(duì)源代碼進(jìn)行解析并將其裝載到數(shù)據(jù)字典中。然后就可以提供各種數(shù)據(jù)字典視圖給出對(duì)所存儲(chǔ)代碼的不同描述。 ALL_SOURCE 揭示了源代碼。 ALL_DEPENDENCIES 顯示各個(gè)對(duì)象之間的依靠性。 ALL_OBJECTS 告訴我哪個(gè)程序是 INVALID 。也許有某個(gè)數(shù)據(jù)字典視圖有助于解決這一問(wèn)題。我該如何找到它呢?數(shù)據(jù)字典中有很多視圖,而且這些視圖都非常晦澀。
  
  為了能對(duì)此有所幫助,我構(gòu)建了一個(gè)名為 dd_view_scan 的實(shí)用程序,該程序可以找到符合需要的那些視圖。使用 dd_view_scan ,我可以輕松搜索視圖集以便找到那些可能會(huì)提供幫助的數(shù)據(jù)源。接下來(lái)我會(huì)對(duì)某個(gè)特定的視圖進(jìn)行深入分析,看看它是否真的包含我所需要的信息。例如,假如我希望分析程序的重載,那么我就不僅需要知道程序名,還需要檢查參數(shù)列表(也就是傳遞的參數(shù))。首先我會(huì)向 dd_view_scan 查詢含有單詞 parameter 或 argument 的那些數(shù)據(jù)字典視圖。(注重:我使用 Oracle9 i Release 2 得到這些結(jié)果。使用早期版本運(yùn)行相同的查詢可能會(huì)得到不同的結(jié)果。)
  
  仔細(xì)檢查該列表, ALL_ARGUMENTS 引起了我的注重。其他的參數(shù)看起來(lái)要更具針對(duì)性,不是我想要的那種。當(dāng)我仔細(xì)分析該參數(shù),我找到了程序包名、參數(shù)名和數(shù)據(jù)類型。這些看起來(lái)就比較接近我的目標(biāo),有必要深入查看一下。讓我們繼續(xù)進(jìn)行探討。
  
  研究:有關(guān) ALL_ARGUMENTS 的全部?jī)?nèi)容
  
  下一步,查看 Oracle 文檔集。我急切地去查看 Oracle9 i 文檔,希望能從中找到答案。我從瀏覽器中打開文檔,使用 Master Index ,立即縮小了 ALL_ARGUMENTS 的范圍。使用下面的查詢,您可以順便獲得雖不相同但還相近的信息(參見(jiàn) all_arguments_

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 吉木乃县| 云和县| 扬州市| 韶关市| 普陀区| 扶绥县| 永春县| 民县| 新郑市| 敖汉旗| 从江县| 仁怀市| 新安县| 海原县| 天台县| 东至县| 上林县| 马鞍山市| 长泰县| 商城县| 闽清县| 祥云县| 明光市| 丹东市| 辽宁省| 河北省| 鄂州市| 新沂市| 昌图县| 长宁县| 南平市| 杭州市| 社旗县| 靖西县| 镇巴县| 盐亭县| 从化市| 木兰县| 米林县| 池州市| 志丹县|