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

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

PL/SQL構(gòu)建代碼分析工具之創(chuàng)建高水平的設(shè)計

2024-07-21 02:33:30
字體:
供稿:網(wǎng)友
    Feuerstein 的“構(gòu)建代碼分析實用工具”系列的第 3 部分    下載 codecheck.zip     在這一 Codecheck 系列的早期文章中(參見 大綱),我仔細(xì)分析了希望我的質(zhì)量保證工具解決的問題:自動識別程序包中潛在的歧義超載。我還確定了可用來實施解決方案的技術(shù) (DBMS_DESCRIBE 和 ALL_ARGUMENTS),并提出了一個測試計劃的概要。現(xiàn)在,我可以相當(dāng)簡明扼要地說明 Codecheck 應(yīng)當(dāng)做什么:對于一個指定的程序包,或者也許是一個程序包內(nèi)某個特定程序的名稱,從 DBMS_DESCRIBE 和 ALL_ARGUMENTS 中獲取關(guān)于這些程序的所有信息。然后讀取所有的參數(shù)信息,并確定是否存在歧義超載。最后,通過 DBMS_OUTPUT 將結(jié)果發(fā)送至屏幕,同時也發(fā)送給 cc_ambig_ovld_results 表,以便可以使用 utPLSQL 來測試 Codecheck.    似乎夠清楚了。這是否意味著下一步就可以開始編寫代碼了?不!在深入 IFs 和 LOOPs 之前,我需要收集足夠多的信息來創(chuàng)建一個設(shè)計,以指導(dǎo)編程。本文中,我探索了如何開發(fā)這種設(shè)計,并演示了我如何小心地避免在開始時過多地糾纏于細(xì)節(jié)。    輸入和輸出    為我的實用工具創(chuàng)建設(shè)計從“輸入什么,輸出什么?”這一問題開始。這是程序的一個基本問題,因為輸入(范圍包括參數(shù)到底層表格)驅(qū)動程序的行為,而要檢測一個程序的效果,沒有其它方法比檢查它的輸出(從廣義上定義的輸出)更好。    Codecheck 的所有輸入包括:    Codecheck 將檢查的程序包或 package.PRogram 的名稱。在涉及到超載的地方,分析獨立的過程或函數(shù)沒有任何意義。    ALL_ARGUMENTS 和 DBMS_DESCRIBE 所提供的與程序相關(guān)的參數(shù)。    Codecheck 的所有輸出包括:    將分析結(jié)果顯示到屏幕的輸出。是否存在歧義超載?假如存在,它們違反了什么規(guī)則?    寫至 cc_ambig_ovld_results 的行,這些行包含相同的信息。    關(guān)于 Codecheck 體系結(jié)構(gòu)與流程的最初的想法    給定這些輸入和輸出,我可以很快地提出 Codecheck 體系結(jié)構(gòu)的概念(參見圖 1)。該流程包含四個主要的階段:    從 ALL_ARGUMENTS 和 DBMS_DESCRIBE 中收集關(guān)于程序參數(shù)的數(shù)據(jù)。我假定將把這些信息加載到 Codecheck 中的一個集合。    分析參數(shù)信息,并識別歧義超載(假如存在的話)。    將結(jié)果寫到屏幕和結(jié)果表中。    運(yùn)行 utPLSQL 來驗證這些結(jié)果。    圖 1. 關(guān)于 Codecheck 總體流程的初步想法PL/SQL構(gòu)建代碼分析工具之創(chuàng)建高水平的設(shè)計(圖一)    我認(rèn)為這可以實現(xiàn)目標(biāo) — 并且以非常高的水平實現(xiàn)。這是起步的一個好辦法,但它還沒有提供開始編程所需的足夠細(xì)粒度。    第二次(和第三次……)的一些想法    無疑,在我有望創(chuàng)建一個可運(yùn)行的且精心編寫的 Codecheck 實用工具之前,我需要更加徹底地對事情進(jìn)行考慮。然而,事實是我不能獨立于代碼構(gòu)建過程來進(jìn)行這種思考和設(shè)計。您曾經(jīng)多少次提出一個很好的計劃然后開始編程,但隨后發(fā)現(xiàn)實際情況(就像這樣:我怎么把這給忘了?)迫使您改變設(shè)計?    避免過度的設(shè)計是我從極限編程(一種輕型方法論,它將通行的編程實踐發(fā)揮至極限,并且推動了我的 utPLSQL 單元測試框架;關(guān)于更多信息,請參見 www.XProgramming.com)中學(xué)到的最重要的原則之一。比如說,為一個三年的開發(fā)項目提出一個總體計劃是否真的有意義,而我們都知道這個計劃在六個月之內(nèi)就會漏洞百出?在 Codecheck 的情況下,每個細(xì)節(jié)在構(gòu)建程序包之前都考慮得過于具體對我是否真的有意義?    極限編程人員喜歡問這個問題:使代碼運(yùn)行最簡單的方法是什么?    我喜歡回答這個問題所帶來的挑戰(zhàn),因為它使我馬上在幾個層次上展開思考。什么是簡單?它應(yīng)該意味著
    透明、易于理解、修改和維護(hù)的代碼直接并直觀地響應(yīng)需求,但不超出它們的范圍的代碼    但工作意味著什么?馬上可以想到以下準(zhǔn)則:    代碼滿足用戶的需求。    代碼在一段可接受的時間內(nèi)運(yùn)行。    不過,我覺得反映一段代碼可工作性的另一個至關(guān)重要的因素是它的可居住性 (habitability) — Richard Gabriel 在他的著作 Patterns of Software: Tales From The Software Community (牛津大學(xué)出版社,1996)中提供的一個術(shù)語和概念。? 他認(rèn)為編寫另一個程序員可居住的代碼是非常重要的 — 可以方便地進(jìn)入,并進(jìn)行修改而不用害怕整個結(jié)構(gòu)會崩潰。    假如一個程序不是可居住的,那么它也不是可維護(hù)的。假如不費很大的勁就無法對其進(jìn)行維護(hù),那么它可能現(xiàn)在能工作,但要滿足未來的需求就將極其困難。    我預(yù)計維護(hù)代碼將逐漸在 PL/SQL 應(yīng)用程序代碼中占有越來越高的比例 — 增強(qiáng)并修補(bǔ)現(xiàn)有的相對穩(wěn)定的應(yīng)用程序。因此,設(shè)計并實施我們的代碼以使其具備可居住性是至關(guān)重要的。    為 Codecheck 提供的一個簡單有效的設(shè)計    我想按照極限編程的準(zhǔn)則來超越 — 但又不過多地超越 — 我的簡單設(shè)計(圖 1)。實現(xiàn)這一目標(biāo)最有效的方法是將我的實用工具所需的不同功能區(qū)域分隔開,然后創(chuàng)建程序包來包含這些功能。我喜歡把這些程序包看作是一些方便的“存儲桶”,當(dāng)我有了新的想法時,我可以往里面放程序和數(shù)據(jù)類型。    在編程過程的初期定義這些存儲桶有助于保持代碼庫井然有序而且模塊化。您將發(fā)現(xiàn)自己處理的是更大數(shù)量的簡潔、目的明確的程序包,而不是最后得到一些難于治理的數(shù)量龐大的小塊程序。隨著您的設(shè)計的發(fā)展,修改這些程序包,或甚至重組它們都相當(dāng)輕易。    抽象地討論這一技巧已經(jīng)夠多了。現(xiàn)在讓我們看看如何把它應(yīng)用到 Codecheck 中。    回到設(shè)計版本 1.0,以下是簡要的步驟:接收程序包(或程序包內(nèi)的程序)的名稱,獲取該程序包的參數(shù)數(shù)據(jù),分析參數(shù)(它們的編號、數(shù)據(jù)類型、是否存在默認(rèn)值等等),然后將結(jié)果發(fā)送至屏幕或測試信息庫。    回顧我其它的許多編程實踐(我知道對于一個從 1980 年起一直編寫程序的人而言,即使他在這個領(lǐng)域幾乎沒有受過任何正式的教育,自然也會積累起幾分優(yōu)勢),我認(rèn)為指定對象名可能需要技巧。用戶是將程序包的名稱、它的所有者和子程序名稱作為單獨的參數(shù)提供還是作為一個參數(shù)提供?我如何確定這個名稱是否引用了一個已有的有效對象?我如何確保它是一個程序包?您可以編寫一些復(fù)雜代碼對 ALL_OBJECTS 進(jìn)行查詢和解決同義字(可能通過遞歸的方式)問題等。或者您可以使用 DBMS_UTILITY.NAME_RESOLVE 過程來為您完成所有這些工作。    我可以馬上確定在構(gòu)建 Codecheck 的過程中會碰到許多細(xì)節(jié)問題 — 非凡是與數(shù)據(jù)類型有關(guān)的問題。DBMS_DESCRIBE 使用數(shù)字代碼;ALL_ARGUMENTS 提供字符串。假如我不想我的代碼馬上令人困窘地變得一團(tuán)糟,我就需要把這些細(xì)節(jié)隱藏在大量的枚舉常量和程序之后。    您已經(jīng)看到了我的參數(shù)信息源的復(fù)雜性。我需要能夠干凈利索地提取、合并,然后從原始數(shù)據(jù)中得出結(jié)論。這可能將涉及到相當(dāng)多的后處理。    報告分析結(jié)果也可能將是一件繁瑣的事情:如何避免 DBMS_OUTPUT 的缺陷?如何設(shè)計輸出的外觀?    我無疑將需要一些小型實用程序,以便不同的存儲桶共享它們。例如,考慮到它所有的值這一麻煩,我費力地避免了對 DBMS_OUTPUT.PUT_LINE 的直接調(diào)用。    隨著我越來越深入到 ALL_ARGUMENTS 和 DBMS_DESCRIBE 中,并試圖處理更有挑戰(zhàn)性的分析類型時,事情變得越來越復(fù)雜。假如我試圖愚弄自己,認(rèn)為這很簡單,一晚上就可以搞定,那我將注定要失敗。我可能不想預(yù)先具體考慮每一個可能的問題,但我也想為變化作好預(yù)備。    哦,別忘了測試的問題。我將需要一個與 utPLSQL 兼容的程序包來包含我的單元測試過程。    在思考了所有這些以及更多的問題之后,我發(fā)現(xiàn)我逐漸接近了圖 2 中所示的功能存儲桶。僅僅識別象這樣的不同區(qū)域并不夠。我還需要盡可能清楚地預(yù)先確定每一個存儲桶的用途、存儲桶包含什么、您能在里面放入什么、以及能取出什么。處理它的另一種方式是,我需要為每一個存儲桶定義握手方式 — 程序與存儲桶通信的方式,以及存儲桶反過來與調(diào)用程序通信的方式。    假如我很使得存儲桶之間的區(qū)別明顯,那么在任意指定的區(qū)域中添加功能,以及將來修補(bǔ)程序都將更輕易。這些存儲桶之間的牽連或相互依靠性會達(dá)到最小。將新的函數(shù)或過程放在什么地方將會很清楚,因此,在哪里能找到它也會很明確(這是最重要的,否則如何使用它?)。    圖 2. Codecheck 功能存儲桶PL/SQL構(gòu)建代碼分析工具之創(chuàng)建高水平的設(shè)計(圖二)    表 1 提供了 Codecheck 存儲桶(現(xiàn)在直接稱為程序包)的一個說明。當(dāng)我象這樣分隔代碼時,還不可避免地要對程序包的層次結(jié)構(gòu)進(jìn)行考慮。在這個層次結(jié)構(gòu)的最頂層是最復(fù)雜的程序包或程序,它們構(gòu)建于其它許多元素之上。在最底層的是不可分割的程序包 — 小型、高度集中的程序包,它們支持一種用途,并且與其它的程序包沒有太多的相關(guān)性。
    圖 3 顯示了 Codecheck 程序包的層次結(jié)構(gòu)的概念。在最底層的是 cc_util 和 cc_error.cc_util 程序包不依靠于其它的 Codecheck 程序包,并且可供所有程序包使用。它甚至不包含 Codecheck 特有的邏輯。cc_error 程序包合并了所有的錯誤處理和假設(shè)驗證邏輯。假如其它任何程序包檢測到了問題或出現(xiàn)了異常,您可以依靠 cc_error 來適當(dāng)?shù)靥幚磉@些情況。    圖 3. 我需要創(chuàng)建的 Codecheck 程序包的層次結(jié)構(gòu)。PL/SQL構(gòu)建代碼分析工具之創(chuàng)建高水平的設(shè)計(圖三)    向上一級是 cc_types 和 cc_names.這些小型、非常專門化的程序包除 cc_util 之外不引用任何程序包。再向上一個層次,我們開始碰到更強(qiáng)健和復(fù)雜的代碼段。cc_arguments 程序包有一個非常明確的用途:合并來自 ALL_ARGUMENTS 和 DBMS_DESCRIBE 的信息。不過,要實現(xiàn)這一點,它將可能需要進(jìn)入到更低的層次中。在 cc_arguments 之上,我們看到的是 cc_smartargs 和 cc_report.前者直接在 cc_arguments 之上構(gòu)建,而 cc_report 使用更底層的程序包和 cc_smartargs 來完成它的任務(wù)。    在這個堆棧的頂層,我們有 Codecheck,它是為終端用戶而設(shè)計的程序包,包含了由希望檢查代碼的 PL/SQL 開發(fā)人員來實際運(yùn)行的程序。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 边坝县| 临江市| 镶黄旗| 称多县| 南川市| 三穗县| 许昌县| 福泉市| 丹东市| 北川| 江津市| 塔河县| 富宁县| 安化县| 靖州| 阿拉尔市| 金山区| 东明县| 那曲县| 长治市| 淮阳县| 高陵县| 富平县| 麻江县| 双柏县| 溆浦县| 万源市| 开原市| 蕉岭县| 玛纳斯县| 土默特左旗| 米泉市| 凤山县| 会昌县| 县级市| 贵德县| 鹤庆县| 舒兰市| 临夏县| 嘉祥县| 定襄县|