Kotlin邊用邊學(xué):利用 require / check / assert 完善接口定義

Key Takeaways(劃重點(diǎn)):

  • require對(duì)外、check對(duì)內(nèi),組成了協(xié)議的前置條件
  • assert是協(xié)議的后置條件

接觸過(guò)Design by contractOCL(Object Constraint Language)或平時(shí)設(shè)計(jì)比較嚴(yán)謹(jǐn)?shù)耐瑢W(xué)應(yīng)該知道,一個(gè)良好的接口設(shè)計(jì)/文檔其實(shí)是應(yīng)該包括了接口的前置條件(即滿足什么條件才可以調(diào)用這個(gè)接口)和后置條件的(執(zhí)行完畢這個(gè)接口后,哪些是真)。在2000年初期MDA (Model-driven Architecture)還比較紅火的時(shí)候,很多模型師、架構(gòu)師都會(huì)在接口中追加此類定義。這個(gè)追加行為,除了本身有利于源代碼的輸出(是的,當(dāng)時(shí)MDA的口號(hào)其實(shí)就是以后不需要碼農(nóng),只要模型師的),確實(shí)可以讓接口的定義更完整、清晰,顯得專業(yè)味十足。

現(xiàn)在MDA雖然不怎么再提到,但其科普的前置/后置條件還是一定程度幫助了軟件業(yè)的完善。Kotlin作為一個(gè)比較現(xiàn)代的語(yǔ)言,在汲取了多類語(yǔ)言和設(shè)計(jì)概念后,很多原先其他語(yǔ)言需要特定實(shí)現(xiàn)(或重復(fù)發(fā)明輪子)的事情,在Kotlin的標(biāo)準(zhǔn)庫(kù)就自帶了,譬如require / check / assert 對(duì)于前置/后置條件的支持。

先看下三者的定義:

  • require(Boolean) throw IllegalArgumentException
  • check(Boolean) throw IllegalStateException
  • assert(Boolean) throw AssertionError

其實(shí)對(duì)應(yīng)著看到各自的輸出,應(yīng)該能猜測(cè)到一些東西。譬如

  • IllegalArgumentException: 傳入的參數(shù)有問(wèn)題
  • IllegalStateException:自身狀態(tài)不對(duì)
  • AssertionError:和預(yù)估的不一樣 (在后置條件的維基百科中其實(shí)就是這么定義的)

    Postconditions are sometimes tested using assertions within the code itself

所以總結(jié)下來(lái),大概就是這么回事了:

  • require負(fù)責(zé)檢查輸入的參數(shù),如果有問(wèn)題,拋出IllegalArgumentException
  • check負(fù)責(zé)檢查自身是否萬(wàn)事俱備可以執(zhí)行了,如果不是,拋出IllegalStateException
  • require + check就是在做前置條件的檢查,通過(guò)了才可以執(zhí)行真正的程序邏輯
  • assert負(fù)責(zé)確保程序執(zhí)行完畢后的結(jié)果/內(nèi)部狀態(tài)是否符合預(yù)期,如果不是,拋出AssertionError

一個(gè)完整應(yīng)用了這幾個(gè)檢查的代碼大概如下(一個(gè)方法用于單次執(zhí)行指定的sql語(yǔ)句,每次執(zhí)行連接數(shù)據(jù)庫(kù)并在執(zhí)行完畢后釋放連接(老土的demo,沒(méi)有連接池-_-)):

fun execute(sql: String) : Unit {
    // 輸入?yún)?shù)的檢查
    require(!sql.isNullOrBlank()) {
        "被執(zhí)行的sql語(yǔ)句不能為空"
    }

    // 自身狀態(tài)檢查
    check(!this.host.isNullOrBlank()) {
        "sql server未指定"
    }

    /*
     * conn = ...
     * conn.execute(sql)
     * conn.disconnect()
     */

    // 執(zhí)行完畢后狀態(tài)檢查
    assert(!conn.isConnected) {
        "每次執(zhí)行完畢后都需要釋放連接"
    }
}

上面的require和check的順序,沒(méi)有一定的誰(shuí)先誰(shuí)后,這個(gè)純粹看個(gè)人風(fēng)格/習(xí)慣。不過(guò)如果涉及到某些執(zhí)行/檢查比較費(fèi)資源時(shí),還是讓不費(fèi)資源的優(yōu)先執(zhí)行為上。

Kotlin標(biāo)準(zhǔn)庫(kù)的這幾個(gè)函數(shù),雖小卻清晰的用代碼來(lái)定義了契約,講究協(xié)作的今天,還是挺需要的。

希望這篇博文能對(duì)你有所幫助,喜歡的話點(diǎn)個(gè)贊吧!

更多Kotlin的實(shí)用技巧,請(qǐng)參考《Kotlin邊用邊學(xué)系列

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

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,628評(píng)論 19 139
  • 本文是在學(xué)習(xí)和使用kotlin時(shí)的一些總結(jié)與體會(huì),一些代碼示例來(lái)自于網(wǎng)絡(luò)或Kotlin官方文檔,持續(xù)更新... 對(duì)...
    竹塵居士閱讀 3,489評(píng)論 0 8
  • 一、什么是擴(kuò)展函數(shù)? 擴(kuò)展函數(shù)數(shù)是指在一個(gè)類上增加一種新的行為,甚至我們沒(méi)有這個(gè)類代碼的訪問(wèn)權(quán)限。這是一個(gè)在缺少有...
    常思行閱讀 1,100評(píng)論 1 2
  • 前言 人生苦多,快來(lái) Kotlin ,快速學(xué)習(xí)Kotlin! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,703評(píng)論 9 118
  • 今天滿天都是烏云密布,把雨水藏在云霄間,還沒(méi)有下。就像是太陽(yáng)公公用一塊麻布遮住臉頰,不讓我們知道它的真面目。就好像...
    王玉笙閱讀 257評(píng)論 0 0

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