lua 防禦式程式設計輔助函式

2021-08-14 07:48:54 字數 3552 閱讀 7154

防禦式程式設計是提高軟體質量技術的有益輔助手段。防禦式程式設計的主要思想是:子程式應該不因傳入錯誤資料而被破壞,哪怕是由其他子程式產生的錯誤資料。這種思想是將可能出現的錯誤造成的影響控制在有限的範圍內。

以上是引用自百科的一段描述,在實際編碼過程中,我們除了判斷引數是否合法外,還會 assert 非法引數,以達到快速定位出錯位置的目的。

比如我們有乙個 計算兩個 number 之和的乙個函式:

function

add( a, b )

return a + b

end

這個函式在我們傳入正確引數的情況下,可以完成它的功能:

local c = add(3, 5) --返回8

local d = add(100, 200) --返回300

但假如我們只傳入乙個引數:

local e = add(3, nil)
則會報以下錯誤:

attempt to perform arithmetic on a nil value (local 『b』)

所以我們要檢查引數,下面是第二版:

function

add( a, b )

iftype(a)=="number"

andtype(b)=="number"

then

return a + b

endend

這時再傳 nil 進去(或者string/table/etc…),就不會報錯了,函式什麼也不會做,也沒有返回值。

看起來已經可以了,但有時我們還有一些需要,就是希望我們寫的函式,外部在呼叫時,都應該傳入正確的引數,如果填了錯誤的引數,那肯定是呼叫法寫出bug了,這時我們希望能給出醒目的提醒,把問題扼殺在搖籃裡。

這時就需要 assert 了。

下面是加了 assert 後的第三版:

-- 第三版:對錯誤引數零容忍

function

add( a, b )

assert(type(a)=="number"

andtype(b)=="number", "invalid params")

return a + b

end

加 assert 在這種情況下看起來有些過於嚴格了,只是因為這個例子的原因而已,實際上在寫真正的功能時,函式要比這個複雜的多,對錯誤引數的容忍程度也不同,我們先假定我們這個簡單的add函式對錯誤引數是零容忍的。

這時候,再用非 number 引數呼叫add,會立即觸發 assert,中止程式的執行,開發者可以馬上看到自己的錯誤用法。

所以我們有乙個較溫和的版本,只記錄出錯日誌,而不 assert ,如下:

-- 第四版:唔,偶爾犯點錯可以接受,只記過不開除

function

add( a, b )

iftype(a)~="number"

ortype(b)~="number"

then

print("invalid param", tostring(a), tostring(b))

return

endreturn a + b

end

好了,以上第三版和第四版就是我們的所有需求了,只不過每次都要寫這麼多**「防禦」,也太麻煩了,有沒有自動化的解決方案?

當然有了,會偷懶的程式設計師才是好的程式設計師,let』s go!

-- 防禦式程式設計 輔助函式

-- 第三版:對引數零容忍的輔助函式

function

check

( condition )

ifnot condition then

log.e("check failed!!", tostring(condition))

assert(false, "check failed!!")

endend-- 第四版:只記 log 不 assert

function

ok( condition )

ifnot condition then

log.e("if_ok!!")

return

false

else

return

true

endend

-- 同樣是第四版,只記 log 的,但跟 ok 用法相反

function

not( condition )

ifnot condition then

log.e("if_not!!")

return

true

else

return

false

endend

-- 注:上述函式中的 log.e,請換為自己專案中記錄錯誤日誌的函式。

好了,讓我們用上面的輔助函式重寫我們的add函式:

-- 第三版:對錯誤引數零容忍

function

add( a, b )

-- 一旦條件為假,就會 assert,並記錄錯誤日誌(含呼叫棧資訊,方便查線上問題)

check(type(a)=="number"

andtype(b)=="number")

return a + b

end-- 第四版:只記 log 不 assert

function

add( a, b )

-- 一但「不ok」,就會記錄錯誤日誌,但不會assert

-- ok條件返回 false, 所以 if 內的邏輯不會執行,跟直接用 if 判斷效果一樣

if ok(type(a)=="number"

andtype(b)=="number") then

return a + b

endend-- 第四版也可以這麼寫

-- 但這樣寫極不自然,看著非常費勁,not 也不是這麼用的

-- 關於ok和not,各自有各自的應用場景,如果現在不理解可以只用check和ok,這兩個用多了以後

-- 就知道not是幹嘛的了 ;-)

function

add( a, b )

if not(type(a)~="number"

ortype(b)~="number") then

return

endreturn a + b

end

check可以認為就是乙個會打錯誤日誌的assert

oknot都是在判斷的條件為 false 時,記錄下錯誤日誌,但並不會觸發 assert。

在日常編碼過程中,對於一些關鍵的、不希望為假的、一旦為假必為bug的條件,可以使用 ok 和 not 判斷,但不要濫用,普通的條件(true/false都為正常情況的)不建議使用。

end

防禦式程式設計

防禦式程式設計 防禦式程式設計的主要思想是 子程式應該不因傳入錯誤資料而被破壞,哪怕是由其他子程式產生的錯誤資料。更一般地說,其核心思想是要承認程式都會有問題,都需要修改,聰明的程式設計師應該根據這一點來程式設計序。我們心裡應該自始至終考慮各種各樣的錯誤處理機制 在區域性處理錯誤 使用錯誤碼來傳遞錯...

防禦式程式設計

場景 交易終端支援市中核算,必須需要處理當日的委託和成交資料,現系統的委託和成交在本地快取和遠端快取中各有乙份。思路 核算優先使用本地快取,本地快取不存在那麼就 防禦式 取遠端快取。實現package demo.design.defensive 專案 demo design defensive 場景...

防禦式程式設計

檢查所有 於外部的資料的值,檢查輸入值的合法性,與我們在註冊資訊是的正規表示式類似。斷言一般用於開發和維護階段,斷言為真,程式正常執行,斷言為假,程式出錯。斷言只在開發階段被編譯到目標 中,在生產產品中不編譯進去。使用斷言的指導意見 斷言是用來檢查永遠不該發生的情況,比如我們對於年齡的檢查,年齡不能...