您好,登錄后才能下訂單哦!
本篇內容介紹了“為什么使用API”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
什么是API
API(Application Programming Interface)提供了對某個問題的抽象,以及客戶與解決該問題的軟件組件之間進行交互的方式。組件本身通常以軟件類庫形式分發,它們可以在多個應用 程序中使用。概括地說,API定義了一些可復用的模塊,使得各個模塊化功能塊可以嵌入到終端用戶的應用程序中去。
你可以為自己、你所在機構中的其他工程師或大型開發社區編寫API。它可以小到只包含一個單獨的函數,也可以大到包含數以百計的類、方法、全局函 數、數據類型、枚舉類型和常量等。它的實現可以是私有的,也可以是開源的。有關API的一個重要的基本定義是:API是一個明確定義的接口,可以為其他軟 件提供特定服務。
現代應用程序通常都是基于很多API建立起來的,而這些API往往又依賴于其他API。如圖1-1中示例應用程序所示,該應用程序用到了3個類庫 (1、2、3)的API,而這3個API中有2個又用到了另兩個類庫(4和5)。舉例來說,瀏覽圖片的應用程序可能會用到加載GIF圖片的API,而該 API本身則可能又依賴更底層的壓縮或解壓縮數據的API。
圖字翻譯:
Application Code:應用程序代碼
Library:類庫
圖1-1 從層次化API中調用例程的應用程序。每個方框代表一個軟件類庫,灰色部分表示其公共接口,對于類庫而言即是其API,白色部分表示隱藏在API后面的具體實現。
API開發在現代軟件開發中隨處可見,其目的是為某個組件的功能提供一個邏輯接口,同時隱藏該模塊內部的實現細節。舉例來說,我們用來讀取GIF圖片的API可能僅僅提供一個LoadImage()
方法,后者接收一個文件名作為參數,并返回一個2維的像素數組。所有文件格式和數據壓縮的細節全部隱藏在這個看似簡單的接口之下。這個概念也在圖1-1中進行了說明,即客戶端代碼只能夠通過該API的公有接口訪問。API公有接口如圖1-1中每個方框頂部的灰色區域所示。
雖然有很多通用API設計方法學(可適用于任何編程語言或編程環境)可以講,但最終都需要使用一門特定的編程語言來表述。因此了解特定語言的特征以 促進規范的API設計是非常必要的。所以,本書專門使用一種語言(C++)描述API設計的問題,而非分散內容使其適用于所有語言。然而,想要使用其他語 言(如Java或C#)開發API的讀者仍然可以從本書中獲得許多通用的深刻見解。本書的直接目標讀者是編寫并維護API的C++工程師,他們的API要 供給其他工程師使用。
目前,C++仍是大型軟件項目中使用最廣泛的編程語言之一,并且日漸成為注重代碼性能項目的***語言,因此,你可以在自己應用中選用的C和C++的 API種類非常多(前面我已經列出一些)。本書重點關注如何使用C++編寫優秀API,并引入了豐富的源代碼示例以更好地闡述這些概念。也就是說,本書會 涉及一些C++特有的主題,例如模板、封裝、繼承、命名空間、操作符、const正確性、內存管理、STL的使用、Pimpl慣用法,等等。
另外,在本書出版期間,C++也正經歷著巨大的變革。新版的C++規范處于ISO/IEC的標準化進程中。目前,多數C++編譯器遵循1998年***發布的標準,即C++98。隨后的標準于2003年出版,修正了前版的幾處缺陷。自那時以來,標準委員會一直致力于一個重大的新版本規范。在標準被正式 批準生效并確定發布日期之前,該版本一直被非正式地稱為C++0x。當你讀到本書時,新的標準可能已經發布了。但是,在我編寫本書的期間,它仍然被稱為 C++0x。
盡管如此,C++0x已經達到標準化進程的高級階段,我們可以滿懷信心地預言一些新的特性。事實上,一些主流的C++編譯器已經開始實現許多建議的 新特性。在API設計方面,某些新特性可以用來構建更加優雅和健壯的接口。因此,我一直努力在整本書中強調和解釋C++0x中的API設計。所以,本書在 未來幾年中應該依然具有參考價值。
為什么使用API
在軟件項目中為什么要關注API,這一問題可以從兩個方面理解:(1)為什么要設計并編寫API?(2)為什么要在應用中使用其他人提供的API?我將在接下來的小節中回答這兩個方面的問題,并指出在項目中使用API的各種好處。
如果你正在編寫供其他開發人員使用的模塊,不管他們是公司里的其他工程師還是外部客戶,比較明智的辦法是構建API來讓他們訪問這些功能。這么做會帶來以下好處。
更健壯的代碼
隱藏實現。通過隱藏模塊內部實現的細節,開發人員就可以在未來的某個時間自由修改模塊的實現而不給用戶造成重 大影響。如若不然,會導致以下結果:(1)代碼的更新將會受到限制;(2)用戶只有重寫代碼才能使用新版本的程序庫。如果總是讓用戶不停地更新軟件版本, 他們很可能不愿再做更新,或者干脆棄用,另外尋找不需要太多維護工作的API。因此,優秀的API設計對業務或項目成功至關重要。
延長壽命。隨著使用時間增長,那些公開了實現細節的系統的內部代碼會變得錯綜復雜,系統的各個部分要依賴其他 部分的內部實現細節。因此,系統將會變得脆弱、死板、不可移植且粘滯性高(Martin,2000)。如此一來,公司為了改善這些代碼,就不得不花費大量 人力財力,甚至推倒重寫。事先花工夫做好API設計,而后維護好該設計以保證一致性,軟件壽命就能延長,從長遠看也能節省花費。在第4章的前面部分,我們 會深入討論該問題。
促進模塊化。API通常用來完成一項具體的任務或用例。因此,API定義了一組具有一致目的的模塊化的功能集。在大量API基礎之上開發的應用,其結構將降低耦合而更加模塊化,每一個模塊的行為都不依賴其他模塊的內部細節。
減少代碼重復。代碼重復是軟件工程中最惡劣的行為之一,任何時候都要避免犯此類錯誤。通過把所有的代碼邏輯置 于一個嚴格的接口之后,讓所有客戶使用這個接口,就能將程序的某種行為統一處理。這樣做意味著只需更新一處代碼就可以改變向所有客戶提供的API的行為。 這樣有助于消除代碼中所有重復的實現。事實上很多的API就是這樣實現的,人們首先發現有重復的代碼,然后制作統一的接口取代這些重復代碼,于是就產生了 API。這是一件好事。
消除硬編碼負擔。很多程序可能包含硬編碼的值,并在整個代碼中不斷復制。例如,在需要寫日志文件的地方就使用具體的文件名“myprogram.log”。我們可以使用API來提供這些信息,而不用在整個代碼層面復制這些常量,例如,使用GetLogFilename()
API調用代替硬編碼的“myprogram.log”字符串。
易于改變實現。如果將所有的實現細節隱藏在公共接口背后,就可以在不影響任何依賴此API代碼的情況下改變其內部的實現細節。例如,可以將原本使用std::string
解析文件的方式變為分配、釋放、再分配char*
緩沖區的方式。
易于優化。成功隱藏了實現細節后,在優化API的性能時就不用操心更改客戶端代碼。例如,可以利用加設緩存的方案優化某個計算密集型的方法。之所以這樣做是因為所有讀寫潛在數據的操作都是通過該API進行的,因此該API更確切地知道何時緩存中的結果無效并且需要重新計算結果。
代碼重用
代碼重用就是使用已有的軟件去構建新的軟件。這是現代軟件開發所追求的一個神圣的目標。API提供了一種代碼復用的機制。
在早期的軟件開發中,有種情況很常見,即公司不得不為其制作的任一應用編寫所有代碼。如果某個程序需要讀取GIF圖片或者解析文本文件,公司不得不 自己編寫全部代碼。如今,隨著優秀的商業庫和開源庫的增多,重用別人已經編寫過的代碼變得非常簡單。舉例來說,如今已經有各種開源的讀取圖像的API和解 析XML的API供人們下載和使用。這些庫被世界上許多程序開發人員不斷地改進和調試,同時也已經在很多其他程序中被實踐檢驗過。
通過使用不同的組件(它們用于構建應用程序各個模塊)并借助組件已發布的API相互通信,軟件開發從本質上已變得更加模塊化。這種做法的好處是不需 要了解每個軟件組件的所有細節,如同前面提到的建造房屋的比喻,可以將很多細節問題委托給專業承包商。這樣能夠縮減開發周期,這一方面是因為可以重用已有 的代碼,另一方面則因為可以將各種組件的開發計劃分離,還可以讓開發者把重點放在核心業務邏輯上,而不必浪費時間重新發明輪子。
然而,實現代碼重用的一個障礙是,常常需要比原本計劃更加通用的接口,因為其他客戶可能有額外的期望和需求。因此有效的代碼重用來自對軟件客戶的深入了解以及結合了客戶和自身利益的系統設計。
C++ API和WEB
依賴第三方API的應用程序在云計算領域里越來越普遍。該領域中,Web應用越來越依賴Web服務(API)為其提供核心功能。對于Web混搭應用程序 (mashup),應用程序本身有時僅僅是對多種已有服務進行再次封裝,從而提供新的服務。例如,將Google地圖API和本地犯罪統計數據庫相結合就 可以為犯罪數據提供一個基于地圖的界面。
實際上,花一些時間強調C++ API設計在Web開發中的重要性是值得的。膚淺的分析可能得出這樣的結論:服務器端的Web開發局限于腳本語言,諸如PHP、Perl、 Python(即流行的LAMP架構縮寫中的“P”),或者基于Microsoft ASP(動態服務器頁面)技術的.Net語言。對于小規模的Web開發可能確實如此,然而值得注意的是,許多大規模的Web服務器都使用C++實現的后臺 服務,以求***性能。
事實上,Facebook開發過一個名為HipHop的產品,它將PHP代碼轉換為C++,以此改善社交網站的性能。因此C++ API設計在可擴展的Web服務開發中確實占有一席之地。此外,使用C++開發核心API不僅可以構建高性能的Web服務,而且這些代碼還可以在諸如桌面 或移動電話版本等其他形式交付的產品中重用。
說句題外話,對于這種軟件開發策略的轉變,一種可能的解釋是全球化推動的結果(Friedman,2008;Wolf, 2004)。實際上,互聯網、標準網絡協議和Web技術的匯聚已經創造了一個軟件競技平臺。這使得來自世界各地的公司和個人都可以在大型復雜軟件項目中進 行創造、貢獻和競爭。這種形式的全球化促成了一種環境,在該環境下,全世界的公司和開發者能夠以開發軟件子系統為生。世界各地的其他組織進而可以通過組合 與擴展這些構建模塊創建解決特定問題的最終用戶應用程序。就本書討論的焦點而言,API提供了促成現代軟件開發全球化和組件化的機制。
并行開發
即使你只是編寫內部軟件,與你共事的工程師也很可能要使用你的代碼編輯程序。如果使用良好的API設計技巧,就可以簡化彼此的工作,不必回答諸多關于代碼如何工作、如何使用的問題。這在多個開發者并行開發相互依賴的代碼時顯得尤為重要。
舉例來說,假設你正在編寫一個字符串加密算法,其他開發者需要使用該算法將數據寫入配置文件。一種做法是讓其他開發者等你完成所有工作,然后在其文 件輸出模塊中使用你的算法。然而,更有效率的做法是,你們提前見面協商好恰當的API,然后你把API放在適當的位置,而API僅僅起占位符的作用,這樣 你的同事就可以立即調用它們了,例如:
#include <string> classStringEncryptor { public: ///設置Encrypt()和Decrypt()調用時使用的密鑰 voidSetKey(conststd::string &key); ///基于當前密鑰加密輸入字符串 std::string Encrypt(conststd::string &str) const; ///基于當前密鑰解密輸入字符串 /// Decrypt()一個由Encrypt()返回的字符串 /// 返回同一個密鑰下原始的字符串 std::string Decrypt(conststd::string &str) const; };
接著,你可以提供這些函數的簡單實現,使得該模塊至少可以編譯和鏈接。例如,相關的.cpp文件可以像下面這樣:
voidStringEncryptor::SetKey(conststd::string &key) { } std::string StringEncryptor::Encrypt(conststd::string &str) { return str; } std::string StringEncryptor::Decrypt(conststd::string &str) { return str; }
這樣一來,你的同事就能夠使用這個API繼續工作而不被你的進度所耽擱。雖然目前你的API實際上不會加密任何字符串,但是這只是一個小的實現細節。重要的是已經有了一個雙方都認可的穩定接口,即一個契約,而且該接口的行為恰當,例如Decrypt(Encrypt("Hello"))
將會返回“Hello”。當你完成了工作,并以正確的實現更新了.cpp文件后,你同事的那部分代碼不需要進行任何修改就能直接運行了。
實際上,有些接口問題很可能在編寫代碼之前并沒有預料到,因此API設計可能需要多次迭代才能保證其恰到好處。在大多數情況下,API支持雙方能夠以最少的停頓并行工作。
這種方法還用利于測試驅動或者是測試先行的開發。事先確定了API,就可以編寫單元測試來驗證預期的功能,并且可以持續運行這些測試程序,以保證始終沒有打破你和同事之間的協議。
將該過程延伸到組織層面,你的項目可以有獨立的團隊,他們彼此也許相距很遠,甚至遵循不同的日程安排。通過預先確定各個團隊的依賴關系,并通過創建 API來為這些關系建模,各個團隊就可以獨立工作,而幾乎不必關心其他團隊如何實現API背后的工作。資源的有效利用以及削減相應的冗余通信,能夠為組織 節約大量整體成本。
何時應當避免使用API
設計并實現API相比編寫普通的應用程序代碼通常要花費更多精力,因為API的宗旨是提供健壯、穩定的接口供其他開發人員使用。因此,與僅在單一應用程序內部使用的軟件相比,API在質量、設計、文檔編寫、測試、支持及維護方面有更高的要求。
因此,如果編寫的是不需要和其他客戶端通信的內部模塊,那么為模塊創建并維護穩定公有接口的額外開銷就不值得了,然而這并不是編寫劣質代碼的理由。為堅持API設計原則而多花費些時間,從長遠看來并不浪費時間和精力。
另一方面,假設你是一位想在應用程序中使用第三方API的軟件開發人員。前一節討論了在軟件中重用外部API的一些理由,但有時也可能需要避免使用特定的API,在如下這些情況下,你應該花精力自己實現代碼或尋找替代的解決方案。
許可證限制。雖然API可以提供所需的各項精巧功能,但是許可證限制可能讓你望而卻步。例如,如果你想使用 GNU GPL(General Public License,通用公共許可證)發布的開源包,那么就必須使用GPL發布所有衍生作品。如果在程序中使用這個包,就必須發布整個應用程序的源代碼,這是 商業應用可能不會接受的約束。其他的許可證(如GNU Lesser General License GPL,LGPL)就更加寬松些,在軟件庫中也更加常見。許可證問題的另一種體現是:商業API的費用對你的項目來說可能過于昂貴,或者許可條款可能過于 嚴格,比如要求向每位開發者甚至每位用戶收取許可費用。
功能不匹配。雖然API看似能夠解決所面臨的問題,但是它有可能以一種與應用程序約束或功能需求不匹配的方式 執行。例如,可能你正在開發一個圖像處理工具,想要提供傅里葉變換功能。雖然有許多現成的FFT(Fast Fourier Transform,快速傅里葉變換)的實現,但是其中大多數是1D算法,而處理2D圖像數據需要使用2D FFT。此外,許多2D FFT算法只能在大小是2的整數冪的數據集上工作(如256×256
或512 × 512
)。或許你找到的API不能在必須支持的平臺上運行,或者它不能滿足你對程序制定的性能標準。
缺少源代碼。雖然有許多開源API,但是有時符合要求的***API可能是閉源產品。也就是說,只提供接口的頭 文件,而背后的C++源文件并不同庫一起發布。這有幾項重要的影響,其中之一就是當庫中存在錯誤時,不能通過檢查源代碼的方式定位問題。對于跟蹤錯誤進而 找到解決方案來說,閱讀源代碼是一個很重要的方法。
進一步說,不能訪問API的源代碼就喪失了通過修改源代碼修復錯誤的能力。這意味著軟件項目的進度可能會受到所使用的第三方API中不可預期問題的不利影響,并且需要等待該API的所有者處理你的錯誤報告并發布修復補丁。
缺乏文檔。雖然API看似可以完全滿足應用程序的需求,但是如果API的文檔編寫拙劣或根本沒有文檔,那么你 ***再去尋找別的解決方案。在這種情況下,有可能是API的用法不清楚影響了它的使用,也有可能是你無法確定特定情況下API的行為,甚至可能是你根本 無法信任那些連花點兒時間解釋代碼都做不到的開發者。
“為什么使用API”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。