C++ API設計

API示例101.5.1 SWIG28611.2.3 外掛程式API31512.1.5

內容介紹

現代軟體開發中的一大難題就是如何編寫優質的API。API負責為某個組件提供邏輯接口並隱藏該模組的內部細節。多數程式設計師依靠的是經驗和冒險,從而很難達到健壯、高效、穩定、可擴展性強的要求。Martin Reddy博士在自己多年經驗基礎之上,對於不同API風格與模式,總結出了API設計的種種最佳策略,著重針對大規模長期開發項目,輔以翔實的代碼範例,從而有助於設計決策的成功實施,以及軟體項目的健壯性及穩定性的實現。
主要內容:
API簡介及其特點
API的一些設計模式及慣用法
影響API的設計的一些C++特性
把控API的風格與性能
版本控制與文檔化的實現
各種優秀的測試方法
如何創建腳本綁定,以便API能被諸如Ruby和Python等語言調用
可擴展性API的基本實現方式
類庫的編譯器實現

作者介紹

作者簡介:
Martin Reddy
博士是軟體行業的一名老兵,有著15年以上的從業經驗,共撰寫過40多篇論文,擁有3項軟體專利,並與他人合著了Level of Detail for 3D Graphics。另外,他還是ACM以及IEEE的會員。
早年,他曾在SRI International供職5年,主要從事分散式三維地形可視化技術方面的工作,他成功創建了在Web上描述3D地球空間信息模型的ISO標準,並且還連續兩年被選為Web3D協會的會長。
他曾在Pixar動畫工作室工作過6年,擔任內部動畫系統的首席工程師,設計並實現了很多高性能API,這些API在一些奧斯卡獲獎及提名影片的製作中都發揮了關鍵作用,這些影片有《海底總動員》、《超人總動員》、《賽車總動員》、《料理鼠王》,以及《機器人總動員》等。
他還開辦了一家諮詢公司Code Reddy,為各家軟體公司提供技術諮詢,主要客戶有Linden Lab和Planet 9 Studios,為大型線上3D虛擬世界《第二人生》設計了API並改善了其基本架構。
現在他擔任ToyTalk公司的首席技術官。
譯者簡介:
劉曉娜
中國科學院計算技術研究所員工,在職博士,從事網路大數據採集及挖掘方面的研究,愛好讀書、翻譯和旅遊。
臧秀濤
碩士畢業於中國科學院計算技術研究所。曾從事網路遊戲、作業系統方面的開發工作。熱愛技術、讀書和翻譯。
林健
中國科學院計算技術研究所博士生,從事機群與格線計算方面的研究,愛好DIY、開源軟體與技術寫作。

作品目錄

目 錄
第1章 API簡介1
1.1  什麼是API1
1.1.1  契約和承包人2
1.1.2  C++中的API3
1.2  API設計上有什麼不同4
1.3  為什麼使用API5
1.3.1  更健壯的代碼6
1.3.2  代碼復用6
1.3.3  並行開發8
1.4  何時應當避免使用API9
1.5  API示例10
1.5.1  API層次10
1.5.2  真實示例12
1.6  檔案格式和網路協定13
1.7  關於本書15
第2章 特徵17
2.1  問題域建模17
2.1.1  提供良好的抽象17
2.1.2  關鍵對象的建模19
2.2  隱藏實現細節20
2.2.1  物理隱藏:聲明與定義20
2.2.2  邏輯隱藏:封裝22
2.2.3  隱藏成員變數23
2.2.4  隱藏實現方法26
2.2.5  隱藏實現類28
2.3  最小完備性29
2.3.1  不要過度承諾29
2.3.2  謹慎添加虛函式30
2.3.3  便捷API31
2.4  易用性33
2.4.1  可發現性34
2.4.2  不易誤用34
2.4.3  一致性36
2.4.4  正交38
2.4.5  健壯的資源分配40
2.4.6  平台獨立43
2.5  松耦合44
2.5.1  僅通過名字耦合45
2.5.2  降低類耦合45
2.5.3  刻意的冗餘47
2.5.4  管理器類48
2.5.5  回調、觀察者和通知50
2.6  穩定的、文檔詳細且經過測試的API53
第3章 模式54
3.1  Pimpl慣用法55
3.1.1  使用Pimpl56
3.1.2  複製語義59
3.1.3  Pimpl與智慧型指針60
3.1.4  Pimpl的優點61
3.1.5  Pimpl的缺點62
3.1.6  C語言的不透明指針62
3.2  單例64
3.2.1  在C++中實現單例64
3.2.2  使單例執行緒安全66
3.2.3  單例與依賴注入68
3.2.4  單例與單一狀態69
3.2.5  單例與會話狀態71
3.3  工廠模式71
3.3.1  抽象基類72
3.3.2  工廠示例73
3.3.3  擴展工廠示例74
3.4  API包裝器模式76
3.4.1  代理模式76
3.4.2  適配器模式79
3.4.3  外觀模式81
3.5  觀察者模式83
3.5.1  MVC架構83
3.5.2  實現觀察者模式84
3.5.3  推與拉觀察者87
第4章 設計88
4.1  良好設計的例子89
4.1.1  積累技術債89
4.1.2  償還技術債90
4.1.3  為長期而設計91
4.2  收集功能性需求92
4.2.1  什麼是功能性需求93
4.2.2  功能性需求舉例94
4.2.3  維護需求94
4.3  創建用例95
4.3.1  開發用例95
4.3.2  用例模板95
4.3.3  編寫高質量用例96
4.3.4   需求與敏捷開發98
4.4  API設計的元素100
4.5  架構設計102
4.5.1  架構的開發103
4.5.2  架構的約束104
4.5.3  識別主要抽象105
4.5.4  創造關鍵對象106
4.5.5  架構模式109
4.5.6  架構的交流110
4.6  類的設計111
4.6.1  面向對象概念112
4.6.2  類設計選項113
4.6.3  使用繼承113
4.6.4  Liskov替換原則115
4.6.5  開放?封閉原則118
4.6.6  迪米特法則119
4.6.7  類的命名120
4.7  函式設計121
4.7.1  函式設計選項121
4.7.2  函式命名122
4.7.3  函式參數123
4.7.4  錯誤處理125
第5章 風格129
5.1  純C API129
5.1.1  ANSI C特性130
5.1.2  ANSI C API的優點132
5.1.3  使用ANSI C編寫API132
5.1.4  從C++中調用C函式134
5.1.5  案例研究:FMOD C API135
5.2  面向對象的C++ API136
5.2.1  面向對象API的優點136
5.2.2  面向對象API的缺點136
5.2.3  案例研究:FMOD C++ API137
5.3  基於模板的API138
5.3.1  基於模板的API示例138
5.3.2  模板與宏139
5.3.3  基於模板的API的優點140
5.3.4  基於模板的API的缺點141
5.4  數據驅動型API141
5.4.1  數據驅動型Web服務142
5.4.2  數據驅動型API的優點143
5.4.3  數據驅動API的缺點144
5.4.4  支持可變參數列表144
5.4.5  案例研究:FMOD數據驅動型API147
第6章 C++用法149
6.1  命名空間149
6.2  構造函式和賦值150
6.2.1  控制編譯器生成的函式152
6.2.2  定義構造函式和賦值操作符153
6.2.3  explicit關鍵字154
6.3  const正確性155
6.3.1  方法的const正確性155
6.3.2  參數的const正確性157
6.3.3  返回值的const正確性157
6.4  模板158
6.4.1  模板術語158
6.4.2  隱式實例化API設計160
6.4.3  顯式實例化API設計162
6.5  操作符重載164
6.5.1  可重載的操作符164
6.5.2  自由操作符與成員操作符165
6.5.3  為類添加操作符166
6.5.4  操作符語法168
6.5.5  轉換操作符170
6.6  函式參數171
6.6.1  指針與引用參數171
6.6.2  默認參數172
6.7  避免使用#define定義常量173
6.8  避免使用友元175
6.9  導出符號176
6.10  編碼規範179
第7章 性能181
7.1  通過const引用傳遞輸入參數182
7.2  最小化#include依賴184
7.2.1  避免“無所不包型”頭檔案184
7.2.2  前置聲明184
7.2.3  冗餘的#include警戒語句186
7.3  聲明常量188
7.4  初始化列表190
7.5  記憶體最佳化192
7.6  除非需要,勿用內聯196
7.7  寫時複製198
7.8  疊代元素202
7.8.1  疊代器202
7.8.2  隨機訪問203
7.8.3  數組引用204
7.9  性能分析205
7.9.1  時效性分析205
7.9.2  基於記憶體的分析207
7.9.3  多執行緒分析208
第8章 版本控制209
8.1  版本號209
8.1.1  版本號的意義209
8.1.2  小眾的編號方案210
8.1.3  提供API的版本信息211
8.2  軟體分支策略213
8.2.1  分支策略213
8.2.2  分支方針213
8.2.3  API和並行分支214
8.2.4  檔案格式和並行發布產品215
8.3  API的生命周期216
8.4  兼容性級別217
8.4.1  向後兼容性217
8.4.2  功能兼容性218
8.4.3  原始碼兼容性218
8.4.4  二進制兼容性219
8.4.5  向前兼容性221
8.5  怎樣維護向後兼容性222
8.5.1  添加功能222
8.5.2  修改功能223
8.5.3  棄用功能224
8.5.4  移除功能226
8.6  API審查226
8.6.1  API審查的目的226
8.6.2  API預發布審查227
8.6.3  API預提交審查228
第9章 文檔230
9.1  編寫文檔的理由230
9.1.1  定義行為230
9.1.2  為接口契約編寫文檔232
9.1.3  告知行為的改變233
9.1.4  文檔涉及的內容234
9.2  文檔的類型236
9.2.1  自動生成的API文檔237
9.2.2  概述文檔237
9.2.3  示例和教程238
9.2.4  發布說明238
9.2.5   授權信息239
9.3  文檔可用性241
9.4  使用Doxygen242
9.4.1  配置檔案242
9.4.2  注釋風格和命令242
9.4.3  API注釋243
9.4.4  檔案注釋245
9.4.5  類注釋245
9.4.6  方法注釋246
9.4.7  枚舉注釋247
9.4.8  帶有文檔的示例頭檔案247
第10章 測試250
10.1  編寫測試的理由250
10.2  API測試的類型252
10.2.1  單元測試253
10.2.2  集成測試255
10.2.3  性能測試257
10.3  編寫良好的測試259
10.3.1  良好測試的特徵259
10.3.2  測試對象260
10.3.3  關注測試工作量261
10.3.4  與QA一起工作261
10.4  編寫可測試的代碼262
10.4.1  測試驅動開發262
10.4.2  樁對象和模擬對象264
10.4.3  測試私有代碼267
10.4.4  使用斷言269
10.4.5  契約編程270
10.4.6  記錄並重放功能272
10.4.7  支持國際化273
10.5  自動化測試工具273
10.5.1  自動化測試框架274
10.5.2  代碼覆蓋率277
10.5.3  缺陷跟蹤系統279
10.5.4  持續構建系統280
第11章 腳本化282
11.1  添加腳本綁定282
11.1.1  擴充或嵌入282
11.1.2  腳本化的優點283
11.1.3  語言兼容性問題284
11.1.4  跨越語言障礙285
11.2  腳本綁定技術286
11.2.1  Boost Python286
11.2.2  SWIG286
11.2.3  Python-SIP287
11.2.4  COM自動化287
11.2.5  CORBA288
11.3  使用Boost Python添加Python綁定289
11.3.1  構建Boost Python290
11.3.2  使用Boost Python包裝C++ API290
11.3.3  構造函式292
11.3.4  擴充Python API293
11.3.5  C++中的繼承295
11.3.6  跨語言多態296
11.3.7  支持疊代器298
11.3.8  綜合套用298
11.4  使用SWIG添加Ruby綁定300
11.4.1  使用SWIG包裝C++ API301
11.4.2  調整Ruby API303
11.4.3  構造函式304
11.4.4  擴充Ruby API304
11.4.5  C++中的繼承305
11.4.6  跨語言多態307
11.4.7  綜合套用307
第12章 可擴展性310
12.1  通過外掛程式擴展310
12.1.1  外掛程式模型概覽311
12.1.2  外掛程式系統設計問題313
12.1.3  以C++實現外掛程式314
12.1.4  外掛程式API315
12.1.5  外掛程式示例317
12.1.6  外掛程式管理器318
12.1.7  外掛程式版本控制321
12.2  通過繼承擴展322
12.2.1  添加功能322
12.2.2  修改功能323
12.2.3  繼承與STL324
12.2.4  繼承與枚舉325
12.2.5  訪問者模式326
12.2.6  禁止子類化331
12.3  通過模板擴展332
12.3.1  基於策略的模板332
12.3.2  奇特的遞歸模板模式334
附錄A  庫336
參考文獻351
索引355

相關詞條

相關搜尋

熱門詞條

聯絡我們