日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

浅谈契约式编程

發布時間:2023/12/29 综合教程 52 生活家
生活随笔 收集整理的這篇文章主要介紹了 浅谈契约式编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  契約式編程是編程的一種方法。那么什么是契約式編程呢?我想這個概念是從“合同”演變過來的。

  在人類的社會活動中,契約一般是用于兩方,一方(供應者)為另一方(客戶)完成一些任務。每一方都期待從契約中獲得利益,同時也要接受一些義務。通常,一方視為義務的對另一方來說是權利。契約文檔要清楚地寫明雙方的權利與義務。契約合同能保障雙方的利益,對客戶來說,合同規定了供應者要做的工作;對供應者來說,合同說明了如果約定的條件不滿足,供應者沒有義務一定要完成規定的任務。

  同樣的道理也適合于軟件。設想一個軟件單元E。它要達到它的目的(履行契約), E使用的策略可能會包括一系列的子任務,t1, ... tn。如果子任務ti 不是那么簡單的,它得調用另一個功能例程(routine)R。換句話說,E把子任務轉包給R。這樣的情形應該被一個很好定義的“登記表”(roster)來管理雙方的義務與權利--契約。假如ti是一項任務,要求把一個給定的元素插入到一個有限容量的字典中。此處字典是一個(名-值)表,每一個元素(值)通過一個作為關鍵字的字符串(名)存取。(譯者注:這里“元素”可以理解成一個任意的數據項)。簡而言之,就是函數調用者應該保證傳入函數的參數是符合函數的要求,如果不符合函數要求,函數將拒絕繼續執行。如果按照契約式編程的思想編寫代碼,就要求我們寫函數時檢查函數參數。有時候是簡單的判斷某個參數不能為空,或者數值不能小于0。如果在項目中全面應用契約式編程,則應該有一個“契約框架”幫我們來做這些事情。

契約與我們通常所說的商業契約很相似,有以下幾個特點:

契約關系的雙方是平等的,對整個bussiness的順利進行負有共同責任,沒有哪一方可以只享有權利而不承擔義務。
契約關系經常是相互的,權利和義務之間往往是互相捆綁在一起的;
執行契約的義務在我,而核查契約的權力在對方;
我的義務保障的是你的利益,而你的義務保障的是我的利益;

  將契約關系引入到軟件開發領域,尤其是面向對象領域之后,在觀念上給我們帶來了幾大沖擊:

  一般的觀點,在軟件體系中,程序庫和組件庫被類比為server,而使用程序庫、組件庫的程序被視為client。根據這種C/S關系,我們往往對庫程序和組件的質量提出很嚴苛的要求,強迫它們承擔本不應該由它們來承擔的責任,而過分縱容client一方,甚至要求庫程序去處理明顯由于client錯誤造成的困境。客觀上導致程序庫和組件庫的設計和編寫異常困難,而且質量隱患反而更多;同時client一方代碼大多松散隨意,質量低劣。這種情形,就好像在一個權責不清的企業里,必然會養一批尸位素餐的混混,苦一批任勞任怨,不計得失的老黃牛。引入契約觀念之后,這種C/S關系被打破,大家都是平等的,你需要我正確提供服務,那么你必須滿足我提出的條件,否則我沒有義務“排除萬難”地保證完成任務。

  一般認為在模塊中檢查錯誤狀況并且上報,是模塊本身的義務。而在契約體制下,對于契約的檢查并非義務,實際上是在履行權利。一個義務,一個權利,差別極大。例如下面的代碼:

if (dest == NULL) { ... }

  這就是義務,其要點在于,一旦條件不滿足,我方(義務方)必須負責以合適手法處理這尷尬局面,或者返回錯誤值,或者拋出異常。而:

assert(dest != NULL);

  這是檢查契約,履行權利。如果條件不滿足,那么錯誤在對方而不在我,我可以立刻“撕毀合同”,罷工了事,無需做任何多余動作。這無疑可以大大簡化程序庫和組件庫的開發。

  契約所核查的,是“為保證正確性所必須滿足的條件”,因此,當契約被破壞時,只表明一件事:軟件系統中有bug。其意義是說,某些條件在到達我這里時,必須已經確保為“真”。誰來確保?應該是系統中的其他模塊在先期確保。如果在我這里發現契約沒有被遵守,那么表明系統中其他模塊沒有正確履行自己的義務。就拿上面提到的“打開文件”的例子來說,如果有一個模塊需要一個FILE*,而在契約檢查中發現該指針為NULL,則意味著有一個模塊沒有履行其義務,即“檢查文件是否存在,確保文件以正確模式打開,并且保證指針的正確性”。因此,當契約檢查失敗時,我們首先要知道這意味著程序錯誤,而且要做的不是糾正契約核查方,而是糾正契約提供方。換句話說,當你發現:

assert(dest != NULL);

  報錯時,你要做的不是去修改你的string_copy函數,而是要讓任何代碼在調用string_copy時確保dest指針不為空。

  我們以往對待“過程”或“函數”的理解是:完成某個計算任務的過程,這一看法只強調了其目標,沒有強調其條件。在這種理解下,我們對于exception的理解非常模糊和寬泛:只要是無法完成這個計算過程,均可被視為異常,也不管是我自己的原因,還是其他人的原因(典型的權責不清)。正是因為這種模糊和寬泛,“究竟什么時候應該拋出異常”成為沒有人能回答的問題。而引入契約之后,“過程”和“函數”被定義為:完成契約的過程。基于契約的相互性,如果這個契約的失敗是因為其他模塊未能履行契約,本過程只需報告,無需以任何其他方式做出反應。而真正的異常狀況是“對方完全滿足了契約,而我依然未能如約完成任務”的情形。這樣以來,我們就給“異常”下了一個清晰、可行的定義。

  一般來說,在面向對象技術中,我們認為“接口”是唯一重要的東西,接口定義了組件,接口確定了系統,接口是面向對象中我們唯一需要關心的東西,接口不僅是必要的,而且是充分的。然而,契約觀念提醒我們,僅僅有接口還不充分,僅僅通過接口還不足以傳達足夠的信息,為了正確使用接口,必須考慮契約。只有考慮契約,才可能實現面向對象的目標:可靠性、可擴展性和可復用性。反過來,“沒有契約的復用根本就是瞎胡鬧。(Bertrand Meyer語)”。

  由上述觀點可以看出,雖然Eiffel所倡導的Design By Contract在表象上不過是系統化的斷言(assertion)機制,然而在背后,確實是完全的思想革新。正如Ivar Jacoboson訪華時對《程序員》雜志所說:“我認為Bertrand Meyer的方向——Design by Contract——是正確的方向,我們都會沿著他的足跡前進。我相信,大型廠商(微軟、IBM,當然還有Rational)都不會對Bertrand Meyer的成就坐視不理。所有這些廠商都會在這個方向上有所行動。”

轉自http://www.nowamagic.net/internet/internet_ContractProgramming.php

總結

以上是生活随笔為你收集整理的浅谈契约式编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。