防御式編程

防御式編程

在防御式駕駛中要建立這樣一種思維,那就是你永遠也不能確定另一位司機將要做什么。這樣才能夠確保在其他人做出危險動作時你也不會受到傷害。你要承擔(dān)起保護自己的責(zé)任,哪怕是其他司機犯的錯誤。同樣,防御式編程的主要思想是:子程序應(yīng)該不因傳入錯誤數(shù)據(jù)而被破壞,哪怕是由其他子程序產(chǎn)生的錯誤數(shù)據(jù)。

保護程序免遭非法輸入數(shù)據(jù)的破壞

通常有三種方法來處理可能帶來非法數(shù)據(jù)的情況。

檢查所有來源于外部的數(shù)據(jù)的值 當(dāng)從文件、用戶、網(wǎng)絡(luò)或其他外部接口中獲取數(shù)據(jù)時,應(yīng)檢查所獲得的數(shù)據(jù)值,以確保它在允許的范圍內(nèi)。

檢查子程序所有輸入?yún)?shù)的值

使用錯誤處理技術(shù)處理錯誤的輸入數(shù)據(jù) 一旦檢測到非法的參數(shù),你可以選擇使用錯誤處理技術(shù)中描述的十幾種方案中的一種或幾種

斷言

斷言是指在開發(fā)期間使用的、讓程序在運行時進行自檢的代碼。斷言為真,則表明程序運行正常,而斷言為假,則意味著它已經(jīng)在代碼中發(fā)現(xiàn)了意料之外的錯誤。

斷言對于大型的復(fù)雜程序或可靠性要求極高的程序來說尤其有用。通過使用斷言,程序員能更快速地排查出因修改代碼或者別的原因,而弄進程序里的不匹配的接口假定和錯誤等。

一個斷言通常包含兩個參數(shù):一個描述假設(shè)為真時的情況的布爾表達式,和一個斷言為假時需要顯示的信息。eg: assert denominator !=0 : “denominator is unexpectedly equal to 0.”;

斷言主要是用于開發(fā)和維護階段。在開發(fā)階段,斷言可以幫助查清相互矛盾的假定,預(yù)料之外的情況以及傳給子程序的錯誤數(shù)據(jù)等。在生成產(chǎn)品代碼時,可以不把斷言編譯進目標(biāo)代碼里去,以免降低系統(tǒng)的性能。

使用斷言的指導(dǎo)建議

用錯誤處理代碼來處理預(yù)期會發(fā)生的情況,用斷言來處理絕不應(yīng)該發(fā)生的情況 斷言是用來檢查永遠不該發(fā)生的情況,而錯誤處理代碼是用來檢查不太可能經(jīng)常發(fā)生的非正常情況,這些情況是能在寫代碼時就預(yù)料到的,且在產(chǎn)品代碼中也要處理這些情況。錯誤處理通常用來檢查有害的輸入數(shù)據(jù),而斷言是用于檢查代碼中的bug。用錯誤處理代碼來處理反常情況,程序就能夠很從容的對錯誤做出反應(yīng)。

有種方式可以讓你更好的理解斷言,那就是把斷言看作是可執(zhí)行的注釋——你不能依賴它來讓代碼正常工作,但與編程語言中的注釋相比,它能更主動的對程序中的假定做出說明。

用斷言來注解并驗證先驗條件和后驗條件 先驗條件和后驗條件是一種名為”契約式設(shè)計”的程序設(shè)計和開發(fā)方法的一部分。使用先驗條件和后驗條件時,每個子程序或類與程序的其余部分都形成了一分契約。

先驗條件是子程序或類的調(diào)用方代碼在調(diào)用子程序或?qū)嵗瘜ο笾耙_保為真的屬性。先驗條件是調(diào)用方代碼對其所調(diào)用的代碼要承擔(dān)的義務(wù)。

后驗條件是子程序或類在執(zhí)行結(jié)束后要確保為真的屬性。后驗條件是子程序或類對調(diào)用方代碼所承擔(dān)的責(zé)任。

斷言是用來說明先驗條件和后驗條件的有利工具。也可以用注釋來說明先驗條件和后驗條件,但斷言卻能動態(tài)地判斷先驗條件和后驗條件是否為真。

對于高健壯性的代碼,應(yīng)該先使用斷言再處理錯誤 對于每種可能出錯的條件,通常子程序要么使用斷言,要么使用錯誤處理代碼來進行處理,但是不會同時使用二者。一些專家主張只須使用一種處理方法即可。

然而,現(xiàn)實世界中的程序和項目通常都很亂,僅僅依賴斷言還是不夠的。這時,同時使用斷言和錯誤處理代碼來處理同一個錯誤是一種更好的選擇。以Microsoft Word 為例,在其代碼中對應(yīng)該始終為真的條件都加上了斷言,但同時也用錯誤處理代碼處理了這些錯誤,以應(yīng)對斷言失敗的情況。因為,斷言可以幫助在開發(fā)階段排查出盡可能多的錯誤。然而,在軟件交付之前發(fā)現(xiàn)并糾正一切錯誤是不現(xiàn)實的,所以應(yīng)用斷言的同時,對錯誤進行處理也至關(guān)重要。

錯誤處理技術(shù)

斷言可以用于處理代碼中不應(yīng)發(fā)生的錯誤。對于那些預(yù)料中可能發(fā)生錯誤的情況,常用的解決方案如下:
返回中立值 有時,處理錯誤數(shù)據(jù)的最佳做法就是繼續(xù)執(zhí)行操作并簡單的返回一個沒有危害的數(shù)值。比如說,數(shù)值計算可以返回 0,字符串操作可以返回空字符串,等等。

換用下一個正確的數(shù)據(jù) 在處理數(shù)據(jù)流的時候,有時只需返回下一個正確的數(shù)據(jù)即可。例如,如果在讀數(shù)據(jù)庫記錄并發(fā)現(xiàn)其中一條記錄已經(jīng)損壞時,你可以繼續(xù)讀下去直到又找到一條正確記錄為止。如果你以每秒100次的速度讀取體溫計的數(shù)據(jù),那么如果某一次得到的數(shù)據(jù)有誤,你只需再等上1/100秒然后繼續(xù)讀取即可。

返回與前次相同的數(shù)據(jù) 如果前面提到的體溫計讀取軟件在某次讀取中沒有獲得數(shù)據(jù),那么它可以簡單地返回前一次的讀取結(jié)果。根據(jù)這一應(yīng)用領(lǐng)域的情況,溫度在1/100 秒的時間內(nèi)不會發(fā)生太大改變。

換用最接近的合法值 在有些情況下,你可以選擇返回最接近的那個合法值。在從已經(jīng)校準(zhǔn)的儀器上取值時,這種方法往往是很合理的。比如說,溫度計也許已經(jīng)校準(zhǔn)在0到100攝氏度之間。如果你檢測到一次小于0的讀取結(jié)果,那你可以把它替換為0,即最接近的那個合法值。如果發(fā)現(xiàn)結(jié)果大于100,那么你可以把它替換為100。

把警告信息記錄到日志文件中 在檢測到錯誤數(shù)據(jù)的時候,你可以選擇在日志文件中記錄一條警告信息,然后繼續(xù)執(zhí)行。這種方法可以同其他的錯誤處理技術(shù)結(jié)合使用,比如說換用最接近的合法值、換用下一個正確的數(shù)據(jù)等。如果你用到了日志文件,要考慮是否能夠安全的公開它,或是否需要對其進行加密或施加其他方式的保護。

返回一個錯誤碼 你可以決定只讓系統(tǒng)的某些部分處理錯誤。其他部分則不在本地處理錯誤,而只是簡單地報告說有錯誤發(fā)生,并信任調(diào)用鏈上游的某個子程序會處理該錯誤。通知系統(tǒng)其余部分已經(jīng)發(fā)生錯誤可以采用下列方法之一:
· 設(shè)置一個狀態(tài)變量的值
· 用狀態(tài)值作為函數(shù)的返回值
· 用語言內(nèi)建的異常機制拋出一個異常

在這種情況下,與特定的錯誤報告機制相比,更為重要的是要決定系統(tǒng)里的哪些部分應(yīng)該直接處理錯誤,那些部分只是報告所發(fā)生的錯誤。如果安全性很重要,請確認(rèn)調(diào)用方的子程序總會檢查返回的錯誤碼。

調(diào)用錯誤處理子程序 另一種方法則是把錯誤處理都集中在一個全局的錯誤處理子程序或?qū)ο笾?。這種方法的優(yōu)點在于能把錯誤處理的職責(zé)集中到一起,從而讓調(diào)試工作更為簡單。而代價則是整個程序都要知道這個集中點并與之緊密耦合。如果你想在其他系統(tǒng)中重用其中的某些代碼,那就得把錯誤處理代碼一并帶過去。

當(dāng)錯誤發(fā)生時顯示出錯消息

用最妥當(dāng)?shù)姆绞皆诰植刻幚礤e誤 這種方法給予每個程序員很大的靈活度,但也帶來顯著的風(fēng)險,即系統(tǒng)的整體性能將無法滿足對其正確性或可靠性的需求。

關(guān)閉程序 有些系統(tǒng)一旦檢測到錯誤發(fā)生就會關(guān)閉。

高層次設(shè)計對錯誤處理方式的影響

既然有這么多選擇,你就必須注意,應(yīng)該在整個程序里采用一致的方式處理非法的參數(shù)。對錯誤進行處理的方式會直接關(guān)系到軟件能否滿足在正確性、健壯性和其他非功能性指標(biāo)方面的要求。確定一種通用的處理錯誤參數(shù)的方法,是架構(gòu)層次的設(shè)計決策,需要在那里的某個層次上解決。

一旦確定了某種方法,就要確保始終如一地貫徹這一方法。如果你決定讓高層的代碼來處理錯誤,而低層的代碼只需要簡單的報告錯誤,那么就要確保高層的代碼真的處理了錯誤!即使你認(rèn)定某個函數(shù)絕對不會出錯,也無論如何要去檢查一下。防御式編程全部的重點就在于防御那些你未曾預(yù)料到的錯誤。

這些指導(dǎo)建議對于系統(tǒng)函數(shù)和你自己編寫的函數(shù)都是成立的。除非你已確定了一套不對系統(tǒng)調(diào)用進行錯誤檢查的架構(gòu)性指導(dǎo)建議,否則請在每個系統(tǒng)調(diào)用后檢查錯誤碼。一旦檢測到錯誤,就記下錯誤代號和他的描述信息。

異常

異常是把代碼中的錯誤或異常事件傳遞給調(diào)用方代碼的一種特殊手段。如果在一個子程序中遇到了預(yù)料之外的情況,但不知道該如何處理的話,它就可以拋出一個異常。對出錯的前因后果不甚了解的代碼,可以把控制權(quán)轉(zhuǎn)交給系統(tǒng)中其他能更好的解釋錯誤并采取措施的部分。

還可以用異常來清理一段代碼中存在的雜亂邏輯。

用異常通知程序的其他部分,發(fā)生了不可忽略的錯誤 異常機制的優(yōu)越之處在于它能提供一種無法被忽略的錯誤通知機制。其他的錯誤處理機制有可能會導(dǎo)致錯誤在不知不覺中向外擴散,而異常則消除了這種可能性。

只在真正例外的情況下才拋出異常 僅在真正例外的情況下才能使用異?!獡Q句話說,就是僅在其他編碼實踐方法無法解決的情況下才使用異常。異常的應(yīng)用情形跟斷言相似——都是用來處理那些不僅罕見甚至永遠不該發(fā)生的情況。

異常需要你做出一個取舍:一方面他是一種強大的用來處理預(yù)料之外的情況的途徑,另一方面程序的復(fù)雜度會因此增加。由于調(diào)用子程序的代碼需要了解被調(diào)用代碼中可能會拋出的異常,因此異常弱化了封裝性。同時,代碼的復(fù)雜度也有所增加。

不能用異常來推卸責(zé)任 如果某種錯誤情況可以在局部處理,那就應(yīng)該在局部處理掉它。不要把本來可以在局部處理掉的錯誤當(dāng)成一個未被捕獲的異常拋出去。

避免在構(gòu)造函數(shù)和析構(gòu)函數(shù)中拋出異常,除非你在同一個地方把他們捕獲

在恰當(dāng)?shù)某橄髮哟螔伋霎惓? 子程序應(yīng)在其接口中展現(xiàn)出一致的抽象,類也是如此。拋出的異常也是程序接口的一部分,和其他具體的數(shù)據(jù)類型一樣。

當(dāng)你決定把一個異常傳給調(diào)用方時,請確保異常的抽象層次與子程序接口的抽象層次是一致的。這個例子說明了應(yīng)該避免什么樣的做法:
Java反例:拋出抽象層次不一致的異常的類

        class Employee {

                ···

                public TaxId GetTaxId() throws EOFException {

                ···

                }

                ···

        }

GetTaxId()把更低層的EOFException(文件結(jié)束,end of file)異常返回給了它的調(diào)用方。它本身并不擁有這一異常,但卻通過把更低層的異常傳給它的調(diào)用方,暴露了自身的一些實現(xiàn)細節(jié)。這就使得子程序的調(diào)用方代碼不僅與Employee類的代碼耦合,而是與比Employee類層次更低的拋出EOFException異常的代碼耦合起來了。這樣做既破壞了封裝性,也減低了代碼的智力上的可管理性。

與之相反,GetTaxId()代碼應(yīng)拋回一個與其所在的類的接口相一致的異常,就像下面這樣:
Java 示例:一個在一致的抽象層次上拋出異常的類

        class Employee {

                ···

                Public TaxId getTaxId() throws EmployeeDataNotAvailable {

                ···

             }

             ···

        }

GetTaxId()里的異常處理代碼可能只需要把一個io_disk_not_ready(磁盤IO未就緒)異常映射為EmployeeDataNotAvailable(雇員數(shù)據(jù)不可用)異常就好了,因為這樣一來就能充分地保持接口的抽象性。

在異常消息中加入關(guān)于導(dǎo)致異常發(fā)生的全部信息 每個異常都是發(fā)生在代碼拋出異常時所遇到的特殊情況下。這一信息對于讀取異常消息的人們來說是很有價值的,因此要確保該消息中含有為理解異常拋出原因所需的信息。如果異常是因為一個數(shù)組下標(biāo)錯誤而拋出的,就應(yīng)在異常消息中包含數(shù)組的上界、下界以及非法的下標(biāo)值等信息。

避免使用空的catch語句 有時你可能會試圖敷衍一個不知該如何處理的異常,比如這個例子:
Java示例:忽略異常的錯誤做法

        try {

                ·····

                ·····

        } catch ( AnException exception ) {

        }

這種做法就意味著:要么是try里的代碼不對,因為它無故拋出了一個異常;要么是catch里的代碼不對,因為它沒能處理一個有效的異常。確定一下錯誤產(chǎn)生的根源,然后修改try或catch二者其一的代碼。
偶爾你也可能會遇到某個較低層次上的異常,它確實無法表現(xiàn)為調(diào)用方抽象層次上的異常。如果確實如此,至少需要寫清楚為什么采用空的catch語句是可行的。你也可以用注釋或向日志文件中記錄信息來對這一情況進行 “文檔化”,就像下面這樣:
Java示例:忽略異常的正確做法

    try {

          ·····

          ·····

    }catch( AnException exception ) {

            LogError( “Unexpected exception” );

    }

    了解所用函數(shù)庫可能拋出的異常    未能捕獲由函數(shù)庫拋出的異常將會導(dǎo)致程序崩潰,就如同未能捕獲由自己代碼拋出的異常一樣。如果函數(shù)庫沒有說明它可能拋出哪些異常,可以通過編寫一些原型代碼來演練該函數(shù)庫,找出可能發(fā)生的異常。

考慮創(chuàng)建一個集中的異常報告機制 有種方法可以確保異常處理的一致性,即創(chuàng)建一個集中的異常報告機制。這個集中報告機制能夠為一些與異常有關(guān)的信息提供一個集中的存儲,如所發(fā)生的異常種類、每個異常該被如何處理以及如何格式化異常消息等。
下面就是一個簡單的異常處理器,它只是簡單地打印出診斷信息:

        public class ReportException {

                private static final String TAG = ReportException.class.getSimpleName();

                public static void Report(Throwable throwable) {

                Log.d(TAG, throwable.getMessage());

                }

        }

你可以像這樣在代碼中使用這個通用的異常處理器:

        try {

                ····

        } catch (Exception e) {

                     ReportException.Report(e);

                }

這個版本的ReportException 代碼非常簡單。而在實際的應(yīng)用程序中,你可以根據(jù)異常處理的需要開發(fā)或簡或繁的代碼。

把項目中對異常的使用標(biāo)準(zhǔn)化 為了保持異常處理盡可能便于管理,你可以用以下幾種途徑把對異常的使用標(biāo)準(zhǔn)化。
· 如果你在用一種像java一樣的語言,其中允許拋出多種多樣的對象、數(shù)據(jù)的話,那么就應(yīng)該為到底可以拋出哪些種類的異常建立一個標(biāo)準(zhǔn)。
· 考慮創(chuàng)建項目的特定異常類,它可用做項目中所有可能拋出的異常的基類。這樣就能把記錄日志、報告錯誤等操作集中起來并標(biāo)準(zhǔn)化。
· 規(guī)定在何種場合允許代碼使用try-catch 語句在局部對錯誤進行處理。
· 規(guī)定在何種場合允許代碼拋出不在局部進行處理的異常。
· 確定是否要使用集中的異常報告機制。
· 規(guī)定是否允許在構(gòu)造函數(shù)和析構(gòu)函數(shù)中使用異常

考慮異常的替換方案 有些程序猿用異常來處理錯誤,只是因為他所用的編程語言提供了這種特殊的錯誤處理機制。你心里應(yīng)該自始至終考慮各種各樣的錯誤處理機制:在局部處理錯誤、使用錯誤碼來傳遞錯誤、在日志文件中記錄調(diào)試信息、關(guān)閉系統(tǒng)或其他的一些方式等。僅僅因為編程語言提供了異常處理機制而使用異常,是典型的“為用而用”;這也是典型的“在一種語言上編程”而非“深入一種語言去編程”的例子。

隔離程序,使之包容由錯誤造成的傷害

隔欄是一種容損策略

以防御式編程為目的而進行隔離的一種方法,是把某些接口選定位”安全”區(qū)域的邊界。對穿越安全區(qū)域邊界的數(shù)據(jù)進行合法性校驗,并當(dāng)數(shù)據(jù)非法時做出敏銳的反應(yīng)。

也同樣可以在類的層次采用這種方法。類的公用方法可以假設(shè)數(shù)據(jù)是不安全的,他們要負責(zé)檢查數(shù)據(jù)并進行清理。一旦類的公用方法接受了數(shù)據(jù),那么類的私用方法就可以假定數(shù)據(jù)都是安全的了。

在輸入數(shù)據(jù)時將其轉(zhuǎn)換為恰當(dāng)?shù)念愋? 輸入的數(shù)據(jù)通常都是字符串或數(shù)字的形式。這些數(shù)據(jù)有時要把被映射為 “是”或”否”這樣的布爾類型,有時要被映射為像Color_Red、Color_Green和Color_Blue這樣的枚舉類型。在程序中長時間傳遞類型不明確的數(shù)據(jù),會增加程序的復(fù)雜度和崩潰的可能性——比如說有人在需要輸入顏色枚舉值得地方輸入了”是”。因此,應(yīng)該在輸入數(shù)據(jù)后立即將其轉(zhuǎn)換到恰當(dāng)?shù)念愋?/p>

隔欄與斷言的關(guān)系

隔欄的使用使斷言和錯誤有了清晰的區(qū)分。隔欄外部的程序應(yīng)使用錯誤處理技術(shù),在那里對數(shù)據(jù)做的任何假定都是不安全的。而隔欄內(nèi)部的程序里就應(yīng)使用斷言技術(shù),因為傳進來的數(shù)據(jù)應(yīng)該已在通過隔欄時被清理過了。如果隔欄內(nèi)部的某個子程序檢測到了錯誤的數(shù)據(jù),那么這應(yīng)該是程序里的錯誤而不是數(shù)據(jù)里的錯誤。

隔欄的使用還展示了”在架構(gòu)層次上規(guī)定應(yīng)該如何處理錯誤”的價值。規(guī)定隔欄內(nèi)外的代碼是一個架構(gòu)層次上的決策。

輔助調(diào)試的代碼

防御式編程的另一個重要方面是使用調(diào)試助手(輔助調(diào)試的代碼),調(diào)試助手非常強大,可以幫助快速地檢測錯誤。

盡早引入輔助調(diào)試的代碼

你越早引入輔助調(diào)試的代碼,它能夠提供的幫助也越大。通常,除非被某個錯誤反復(fù)地糾纏,否則你是不愿意花精力去編寫一些調(diào)試輔助的代碼的。然而,如果你一遇到問題馬上就編寫或使用前一個項目中用過的某個調(diào)試助手的話,它就會自始至終在整個項目中幫助你。

采用進攻式編程

應(yīng)該以這么一種方式來處理異常情況:在開發(fā)階段讓它顯現(xiàn)出來,而在產(chǎn)品代碼運行時讓它能夠自我恢復(fù)。這種方式稱為“進攻式編程”。

假設(shè)你有一段case語句,期望用它處理5類事件。在開發(fā)期間,應(yīng)該讓針對默認(rèn)情況的case分支顯示警告信息說:“嗨!這兒還有一種沒有處理的情況!改程序吧!” 然而,在最終的產(chǎn)品代碼里,針對默認(rèn)情況的處理則應(yīng)更穩(wěn)妥一些,比如說可以在錯誤日志文件中記錄該信息。

下面列出一些可以讓你進行進攻式編程的方法。
· 確保斷言語句使程序終止運行。不要讓程序猿養(yǎng)成壞習(xí)慣,一碰到已知問題就按回車鍵把它跳過。讓問題引起的麻煩約大約好,這樣才能被修復(fù)。
· 確保每一個case語句中的defaut分支或else分支都能產(chǎn)生嚴(yán)重錯誤,或者至少讓這些錯誤不會被忽視。
· 讓程序把他的錯誤日志文件用電子郵件發(fā)給你,這樣你就能了解到已發(fā)布的軟件中還發(fā)生了哪些錯誤——如果這對于你所開發(fā)的軟件適用的話。

計劃移除調(diào)試輔助的代碼

你都有哪些常用的方法,說說看

確定在產(chǎn)品代碼中該保留多少防御式代碼

保留那些檢查重要錯誤的代碼 你需要確定程序的哪些部分可以承擔(dān)未檢測出錯誤而造成的后果,而哪些部分不能承擔(dān)。

去掉檢查細微錯誤的代碼 如果一個錯誤帶來的影響確實微乎其微的話,可以把檢查它的代碼去掉。這里的”去掉”并不是永久地刪除代碼,而是利用版本控制、預(yù)編譯器開關(guān)或其它技術(shù)手段來編譯不包含這段特定代碼的程序。如果程序所占的空間不是問題,你也可以把錯誤檢查代碼保留下來,但應(yīng)該讓它不動聲色地把錯誤信息記錄在日志文件里。

去掉可以導(dǎo)致程序硬性崩潰的輔助調(diào)試代碼 正如我所說的,當(dāng)你的程序在開發(fā)階段檢測到了錯誤,你肯定想讓它盡可能地引人注意,以便能修復(fù)它。實現(xiàn)這一目的的最好方法通常就是讓程序在檢測到錯誤后打印出一份調(diào)試信息,然后崩潰退出。這種方法甚至對于細微的錯誤也很有用。

保留可以讓程序穩(wěn)妥的崩潰的代碼 如果你的程序里有能夠檢測出潛在嚴(yán)重錯誤的調(diào)試代碼,那么應(yīng)該保留那些能讓程序穩(wěn)妥地崩潰的代碼,以便輔助調(diào)試產(chǎn)品中的錯誤。

為你的技術(shù)支持人員記錄錯誤信息 可以考慮在產(chǎn)品代碼中保留輔助調(diào)試用的代碼,但要改變他們的工作方式,以便與最終產(chǎn)品軟件相適應(yīng)。如果你開發(fā)時在代碼里大量地使用了斷言來終止程序的執(zhí)行,那么在發(fā)布產(chǎn)品時你可以考慮把斷言子程序改為向日志文件中記錄信息,而不是徹底去掉這些代碼。

確認(rèn)留在代碼中的錯誤信息是友好的 如果你在程序中留下了內(nèi)部錯誤消息,請確認(rèn)這些消息的用語對用戶而言是友好的。

對防御式編程采取防御的姿態(tài)

過度的防御式編程會引起問題。如果你在每一個能想到地地方用每一種能想到的方法檢查從參數(shù)傳入的數(shù)據(jù),那么你的程序會變得臃腫而緩慢。更糟糕的是,防御式編程引入的額外代碼增加了軟件的復(fù)雜度。防御式編程引入的代碼也并非不會有缺陷,和其它代碼一樣,你同樣能輕而易舉地在防御式編程添加的代碼中找到錯誤——尤其是當(dāng)你隨手編寫這些代碼時更是如此。因此,要考慮好什么地方你需要進行防御,然后因地制宜地調(diào)整你進行防御式編程的優(yōu)先級。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 防御式編程 思想與要點 保護程序免遭非法輸入數(shù)據(jù)的破壞??子程序應(yīng)該不因傳入錯誤數(shù)據(jù)而被破壞,哪怕是由其他子程序產(chǎn)...
    Pengzh1閱讀 1,115評論 0 0
  • 背景 事情的來由還要從幾十幾億年前的一次星球大爆炸說起,sorry,背錯臺詞了,是從幾天前討論接口返回數(shù)據(jù)和幾個月...
    cuiyao50閱讀 448評論 0 1
  • 主要思想: 子程序應(yīng)該不因傳入錯誤數(shù)據(jù)而被破壞, 哪怕是由其他子程序產(chǎn)生的錯誤數(shù)據(jù);換一種說法是, 程序員應(yīng)該承認(rèn)...
    娟子閱讀 2,662評論 0 1
  • 最近業(yè)余時間在閱讀《代碼大全》,閱讀“防御式編程”章節(jié)的時候非常受啟發(fā),自己之前對系統(tǒng)的錯誤處理這塊也確實隨意了。...
    henry_g閱讀 715評論 0 0
  • 保護程序免遭非法輸入數(shù)據(jù)的破壞 檢查所有來源于外部的數(shù)據(jù)的值檢查子程序所有輸入?yún)?shù)的值決定如何處理錯誤的輸入數(shù)據(jù) ...
    lucasdada閱讀 405評論 0 0

友情鏈接更多精彩內(nèi)容