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

首頁 > 開發 > 綜合 > 正文

構建實用程序驗證代碼質量的內部詳情

2024-07-21 02:37:50
字體:
來源:轉載
供稿:網友

  通過對 Codecheck 及其相關概念的學習,您將了解到 Oracle PL/SQL 最新、最好的一些特性,如多層集合。此外,我還將提供一套平臺,您可以在該平臺上構建和添加自己的 QA 檢查,例如檢查參數是否太多或太少、查找所有程序包都要用到的程序,并確保代碼符合命名規則。 也許親身演練的最大好處在于有機會看到實際運用的一些最佳實戰技巧,這可能是學習如何使用這些技巧最簡單的方法。
  
  我需要聲明一點:我已經完成了 Codecheck 的一個運行版本。我計劃一邊寫下該實用程序的構造經過,一邊對其進行改進。因此,該系列每一篇文章的下載都將包含一個 Codecheck (codecheck.zip)。請隨意下載并立即使用。假如您在調試的過程中碰到什么問題,或是有一些改進意見,請發送至 steven@stevenfeuerstein.com。
  
  確定問題:程序包中的重載多義性
  
  為了寫出高質量的程序而顧及到方方面面會令人發瘋。因此,我打算集中到幾個典型的問題,以免屢屢受挫而不得不放棄創建 Codecheck 的初衷。編寫和成功編譯包含不可調用程序的 PL/SQL 程序包是極有可能的,而這并沒有多大的意義,不是嗎?讓我們來看看這一希奇的情形是怎樣出現的。
  
  Oracle PL/SQL 支持負載,也就是所謂的靜態多態性。這就意味著,您能在任何聲明段或程序包中用相同的名稱定義兩個或多個程序,只要這些程序區別顯著(通常是參數列表不同),編譯器能夠辨別您想要使用哪個程序。重載對于提高代碼的可用性來說是一項有用的技術。然而,它也會帶來一些問題,非凡是假如參數列表很長,其中的參數有些有缺省值,有些沒有,則尤其如此。
  
  為了向您證實開發人員的確會面臨這一問題,我挑選了幾個可能會出錯的例子,這些例子是以下面所示的程序包說明開頭的:
  
  CREATE OR REPLACE PACKAGE salespkg
  IS
  PROCEDURE calc_total (zone_in IN VARCHAR2);
  
  PROCEDURE calc_total (reg_in IN VARCHAR2);
  END salespkg;
  /
  
  這一部分在編譯時不會有任何問題,正如其程序體一樣。其中有兩段重載程序,都命名為 calc_total。其中之一接收一個地段,例如 'ZONE 15',然后計算該地段的總銷售額。而第二個程序則接收一個區域,例如 'SOUTHWEST',然后計算該區域的總銷售額。但當我試圖調用其中某個程序,卻出現一個錯誤。
  
  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
  
  該錯誤消息明確地指出了這一問題:"Too many declarations of CALC_TOTAL match this call."(有多個 CALC_TOTAL 的聲明與該調用相匹配)。您可以看到,計算機并不是十分的聰明。您我都可以看出 'ZONE 15' 是一個地段;難道 PL/SQL 編譯器就不能識別出這是"地段"的 calc_total 嗎(即帶有 zone_in 參數的重載)?不幸的是,編譯器并不是這樣工作的。'ZONE 15' 是字符串的字面意義,編譯器無法分析。編譯器無法知道應該使用哪段程序,然后就甩手不管了。
  
  我們該如何解決這一問題呢?在這種特定情況下,我可以通過使用指定的參數值來消除多義性:
  
  BEGIN
  salespkg.calc_total (zone_in => 'ZONE 15');
  END;
  
  在這個實例,我想要告訴編譯器使用特定的參數 (zone_in)。因為這兩個重載程序中,只有一個程序的參數名與之相符,這樣編譯器就知道該調用這兩個中的哪一個了。盡管如此,不得不 使用參數名引用來調用一個過程或一個函數還是令人難以接受。這明顯是一個糟糕的設計—而且會越來越糟。考慮下面的程序包說明:
  
  CREATE OR REPLACE PACKAGE salespkg
  IS
  PROCEDURE calc_total (zone_in IN VARCHAR2);
  
  PROCEDURE calc_total (zone_in IN CHAR);
  END salespkg;
  /
  
  同樣,這個程序包在編譯時也不會有任何問題。但現在又面臨另一種情況:無法調用這些過程中的任意一個。他們共享程序名和參數名。唯一的區別就是數據類型。VARCHAR2 當然不同于 CHAR,因此編譯器會讓您輕松過關。但不幸地是,這兩種數據類型的差異性還不夠大,這將導致在真正試圖使用代碼的時侯出現難題。考慮下面的一段代碼:
  
  BEGIN
  salespkg.calc_total ('ZONE15');
  END;
  
  'ZONE 15' 是固定長還是可變長?PL/SQL 文檔中說道 "All string literals except the null string ('') have datatype CHAR,"(所有非空串的字符串文字都是 CHAR 型)但是編譯器并沒有意識到這個問題。非常希奇,即使向程序傳送了一個顯式聲明為固定長度的字符串,仍然會出現問題。

  
  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
  
  如您所見,確實可以定義這樣一個程序包重載,即它可以順利通過編譯,但要么不可用,要么只能通過"非自然行為"使用,例如強制使用參數名引用。
  
  我將采用什么樣的解決方案呢?
  
  為了識別這些重載問題,我產生如下的想法:也許我可以構建一個實用程序"自動"掃描程序包,檢查所有可能的有效程序調用置換,并提醒我注重那些多義重載。我能夠作到這一點嗎?看起來我應該要能夠將程序包定義解析為各段程序,同時解析出每個程序的參數列表。我應該能夠取出這些參數的數據類型和缺省值。我如何才能獲得這些信息呢?遺憾的是,我對 PL/SQL 解析器沒有 API 級的訪問權限,非凡是不能從 PL/SQL 自身內部來進行訪問。而且我壓根不想考慮自己編寫一個解析器。那么一個積極的(深受困擾的)實用程序構造者會如何去做呢?他會查找可以替代的方法。
  
  還有沒有其他的方法可以從程序中提取這一信息呢?我想起每當我編譯一個 PL/SQL 程序,Oracle 數據庫就會對源代碼進行解析并將其裝載到數據字典中。然后就可以提供各種數據字典視圖給出對所存儲代碼的不同描述。ALL_SOURCE 揭示了源代碼。ALL_DEPENDENCIES 顯示各個對象之間的依靠性。ALL_OBJECTS 告訴我哪個程序是 INVALID。也許有某個數據字典視圖有助于解決這一問題。我該如何找到它呢?數據字典中有很多視圖,而且這些視圖都非常晦澀。
  
  為了能對此有所幫助,我構建了一個名為 dd_view_scan 的實用程序,該程序可以找到符合需要的那些視圖(參見表 1;完整的實現行位于 ddviewscan.sp 文件中)。使用 dd_view_scan,我可以輕松搜索視圖集以便找到那些可能會提供幫助的數據源。接下來我會對某個特定的視圖進行深入分析,看看它是否真的包含我所需要的信息。例如,假如我希望分析程序的重載,那么我就不僅需要知道程序名,還需要檢查參數列表(也就是傳遞的參數)。首先我會向 dd_view_scan 查詢含有單詞parameter 或 argument 的那些數據字典視圖。您可以在 列表 2 中查看到相應的結果。(注重:我使用Oracle9i Release 2 得到這些結果。使用早期版本運行相同的查詢可能會得到不同的結果。)
  
  仔細檢查該列表,ALL_ARGUMENTS 引起了我的注重。其他的參數看起來要更具針對性,不是我想要的那種。當我仔細分析該參數,我找到了程序包名、參數名和數據類型(參見列表 3)。這些看起來就比較接近我的目標,有必要深入查看一下。讓我們繼續進行探討。
  
  研究:有關 ALL_ARGUMENTS 的全部內容
  
  下一步,查看 Oracle 文檔集。我急切地去查看 Oracle9i 文檔,希望能從中找到答案。我從瀏覽器中打開文檔,使用 Master Index,立即縮小了 ALL_ARGUMENTS 的范圍。表 1 顯示了對該視圖每一列的描述。使用下面的查詢,您可以順便獲得雖不相同但還相近的信息(參見 all_arguments_cols.sql):
  
  SELECT column_name, comments
  FROM all_col_comments
  WHERE table_name='ALL_ARGUMENTS'
  
  遺憾的是,您在表 1 中所見的就是 Oracle 可提供的所有信息。無論如何,我們已經邁出了第一步。許多列的引入都是不言而喻的。而對于其他的,例如 OVERLOAD、POSITION 和 DATA_LEVEL,就不太清楚了。
  
  下面,我需要確信我已經理解了 ALL_ARGUMENTS 的內容。我還必須證實 ALL_ARGUMENTS 包含了 Oracle 所說的它包含的東西。假如您研究 Oracle 技術超過六個月,那么您就會明白任何事都不能想當然。文檔中對某技術有某種說法,并不意味著該技術本身就是那樣的。某個作者(例如 Steven Feuerstein)說某技術能夠在其筆記本電腦中 windows 2000 下的 Oracle9i Release 2 上運行,并不意味著該技術在您的系統中也會以同樣的方式運行。自己進行測試來驗證取決于您的應用程序的那些操作是非常重要的。
  
  下面就是我所作的一些工作:我將名為 allargs_test 的程序包(位于 all_arguments.tst 文件中)放在一起。該程序包定義了一個帶有子程序的包,這些子程序含有各種不同的參數組合(或者沒有),這些參數會用到大量不同的數據類型、參數模式等。
  
  然后,我又構造了一些查詢以檢查 ALL_ARGUMENTS 必須向該程序包提供哪些信息。可以在 allargs*.sql 腳本中找到這些查詢。為了讓您能夠看到 ALL_ARGUMENTS 內容,我會回顧這些查詢的某些結果。隨后我將提供一個發現結果列表,該列表將引導我設計和實現 Codecheck。
  
  假如有一個帶有下列說明的

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 垦利县| 安吉县| 元谋县| 永登县| 忻城县| 抚松县| 石屏县| 嵊泗县| 阳新县| 阿合奇县| 肇源县| 铜梁县| 乌苏市| 视频| 石首市| 桐乡市| 灌阳县| 萝北县| 高台县| 定陶县| 来凤县| 龙胜| 石台县| 巴塘县| 大安市| 漳浦县| 通河县| 新安县| 德化县| 尚义县| 视频| 秭归县| 城市| 都匀市| 襄城县| 丹阳市| 革吉县| 宁河县| 湘潭市| 武胜县| 平遥县|