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