C++ API 设计 03 序言

序言

使用C++来开发大型应用程序是一件困难和棘手的事。然而,要设计可重用的C++接口且健壮、稳定、易用和耐用,更是难上加难。要想在这方面取得成功的最好方法就是:坚持良好的应用程序编程接口(API)设计原则。

每个API都为某个软件组件提供一个逻辑接口,并隐藏需要实现的该组件的内部细节。它为一个模型提供了高层次的抽象,并促进通过允许多个应用程序共享相同功能促进代码重用。

现代软件开发已经高度依赖API,从底层的应用程序框架到数据格式API和图形用户界面(GUI)框架。事实上,常见的软件工程术语,如模块化开发、代码重用、组件化、动态链接库(DLL)、软件框架、分布式计算和面向服务的体系架构都非常依赖强有力的API设计能力。

你可能已经知道一些流行的C和C++的API,包括标准模板库(STL)、Boost、Microsoft Windows API (Win32)、Microsoft Foundation Classes(MFC)、libtiff、libpng、zlib、libxml++、OpenGL、MySQL++、Trolltech的Qt、wxWidgets、GTK+、KDE、SkypeKit、POSIX pthreads、英特尔的Threading Building Blocks(线程构建模块)、Netscape 插件API和Apache模块API。此外,还有很多Google的C++开源项目是C++的,sourceforge.net、bitbucket.org和freshmeat.net网站上也有很多。

这些API在软件开发的各个领域中都有用到,从桌面应用到移动计算和嵌入式系统,还有就是Web开发。例如,Mozilla的火狐Web浏览器就是建立在80多个动态库之上的,每个都为若干个API提供了实现。

因此,优雅和健壮的API设计是现代当代软件发展的重要方面。其中有个重要的地方和标准的应用开发不同,那就是更需要应变管理。我们都知道,变化是软件发展的必然因素:总会有新的需求、功能要求和错误修复,这些对软件的完善都是在刚开始设计时无法事先预计的。然而,修改有众多最终用户程序所共享的API,可能导致出现很大的问题,甚至让用户客户放弃这个API。因此,良好的API设计的主要目标就是为用户提供你客户所需要的功能。当你发布新版本时,同时对他们的代码造成的影响也降至最低­­­(最理想的情况是没任何影响)。

---此处插入黑色分割线---

为什么你需要读这本书

如果你编写的C++代码给其他工程师用的,你是一名API设计师的话,那么本书就是为你量身定做的。

接口是最为重要的代码,因为如果接口出现问题,那么修复它的代价比修复实现部分的代价要高很多。例如,改变一个接口可能导致基于它的所有程序都要进行相应的代码更新。然而,通过修改实现部分可以透明地集成到客户端程序中去,这样就可以轻松采用新的API版本。从经济角度上看,设计不良的接口将极大降低代码的生存期。学习如何编写高质量的接口是一个重要的工程学技能,这正是本书的中心点所在。

正如Michi Henning指出,比起20年前,今天的API设计更为重要了。这是因为,很多API都是近年开发出来的。这些API也提供更为丰富和复杂的功能,也被更多的终端程序所共享(Henning, 2009)。除了这些,现在市面上还没有一本专注于C++ API 设计的书。

值得一提的是本书并不是普通的C++编程指南,市面上已经有好多这种书了。我会讲到很多面向对象设计的例子和很多实用的C++技巧。不过,我会专注于C++简洁的模块化接口技术。因此,我不会深入说明这些接口里面的实现是如何完成的相关问题,例如到底该选择哪个算法或者某个函数体花括号里面的代码到底有什么限制。

不过,本书将涵盖API开发的所有阶段。从刚开始的设计到实现、测试、文档、发布、版本控制、维护和否决废弃译者注:废弃术语Deprecation 指软件中某些特性已经被否决废弃,应避免使用。虽然在当前版本中还有保留,不过使用它们的时候会给出警告信息)。我还会涵盖专门的API主题,如创建脚本和插件API。虽然这些主题也和普通的软件开发有关,但是这里的重点是针对API设计的特殊环节。例如,当讨论测试方法时,我会专注于自动化API测试技术,而不是包括终端用户应用程序测试技术,如GUI测试、系统测试或手动测试。

就我写这本书的能力而言,我做为作为API开发的主管,已经为几个合作机构、内部动画系统(他们以此获得过奥斯卡奖)提供过可共享的研究代码,还有开源的供全世界数以百万计人使用的客户端/服务器端API。纵观这些不同的经历,我一如既往地感受到高质量API设计的重要性。因此,本书向您介绍了从实践中得到的极其实用的API设计精华。

谁是本书面向的读者

虽然本书不是关于C++的新手教程,但我还是尽最大努力让您容易易于阅读并清楚地解释所有的术语和行话。因此,本书对有一点C++基础的程序员新手也非常有价值,如果他们想提高自己的设计能力的话。当然,对那些已经很有经验并想学习新技术的高级软件工程师和软件架构师来说,也是一样有价值的。

当我写这本书时,我就在脑子里划定了几个读者群:

1.在职的软件工程师和架构师 初级和高级开发人员,他们在开发某个API项目,并需要实用的建议来告诉他们如何实现最为优雅和耐久的设计。

2.技术经理 程序和产品经理,他们负责开发一个API产品,他们更需要深入理解技术问题的细节和API设计的流程。

3.学生和教育者 计算机科学和软件工程的学生,他们要学习如何编程,并想学习从大型项目实践经验中得到的软件设计资源。

 

关注C++

虽然有很多通用的API设计方法可以学习,这些技能可以同样应用在任何编程语言或环境,但是API最终都必须用一个特定的编程语言来实现。因此,重要的是掌握这个特定语言的特点,这有助于设计标准的API。限于篇幅,本书只专注于基于C++的API设计中的问题,而不是其它所有语言。如果读者希望使用其它语言来开发API,如Java或者C#,仍然可以通过本书获益,本书是面向C++工程师的,他们为其他工程师开发和维护API。

C++仍然是大型软件项目中最广泛使用的编程语言之一,特别是需要编写对性能要求较高的代码时,C++还是最受欢迎的。因此,你的程序可以利用很多C和C++ 开发的API(其中一些我前面已经列出)。我将集中精力讲述如何利用C++开发优秀的API,并通过大量的示例代码来更好地说明这些概念。这意味着,我将涵盖C++的这些主题,例如模板、封装、继承、名空间、运算符、正确使用const常量正确性(const correctness)、内存管理、STL的使用和pimpl等。

此外,本书出版的时候将是处于一个C++变革的激动人心的时刻。目前,一个新版本的C++规范正在通过ISO / IEC标准化审核。大多数C++编译器还是符合1998年公布的标准,也就是著名的C++ 98标准。之后的一个版本是2003年修订的,纠正了一些缺陷。自那时起,标准委员会就一直致力于制定一个重要的新版本。这个版本的非正式名称是C++0x,直到该标准被批准和正式发布日期确定后才会确定正式名称。当你阅读本书时,新标准可能已经公布了(译者注:在本书翻译时,正式新标准尚未公布最新的草案版本在2011年4月5日公布,有兴趣的读者可以参阅Wiki百科)。然而,在本书编写时,它仍然被称为C++0x。

尽管如此,C++0x已经提上标准化议事日程,很多新特性是可以预期的。事实上,一些主流C++编译器已经开始开发着手实现这些新特性。就API设计而言,其中的一些新特性可以用来设计更优雅和稳固的接口。同样地,在全书中我将尽力关注和解释C++0x这些方面的内容。C++0x还要几年才能正式出来,所以本书讲述的关于C++0x的相关资源还是不会有什么变化。

约定

用户”(user)这个术语在传统概念中是表示软件程序的使用人,如微软 Word字处理软件用户或者Mozilla火狐浏览器用户。在API设计语境中,表示一个软件开发人员,他利用某个API来开发一个程序。换句话说,我通常都是在讨论API用户,而不是什么程序软件的用户。还有就是术语“客户”(client)的意思也是一样的。不过要注意的是,这个术语“客户”也可以是使用你所设计的API的那个人,还可以表示调用API功能的软件。

虽然标识C++源文件和头文件的扩展名有很多种,如.cpp 、.cc、.cxx、.h、.hh和.hpp,但是全书中我都统一以.cpp和.h为标准。我也会交替使用模块和组件这两个术语来表示一组.cpp和.h文件对。这些显然和一个类是不一样的,因为一个模块或者组件可以包含多个类。我还会用术语“库”表示一个物理上的集合或包。这几者的关系是库>模块/组件>类。

方法(method)”这个术语,就是和面向对象编程领域中大家理解的一样,并不是严格的C++术语。它起初是从Smalltalk语言发展过来的。同等的C++术语应该叫成员函数(member function),不过有些工程师喜欢更精确的定义:虚成员函数(virtual member function)。本书中,我并不是特别关注这些术语的微妙差异,我会交替使用方法和成员函数。同样地,虽然术语“数据成员”(data member)更符合C++的表述风格,但是我还是会使用“成员变量”(member variable)来表示同样的意思。

就排版约定而言,所有的包含源代码的例子都使用固定宽度的字体,还有所有文件名、文中出现的编程语言的关键字也一样。我给出的所有类名和函数名都采用首字母大写的“骆驼拼写法”(译者注:camel case 在英语中,依靠单词的大小写拼写复合词的做法)。例如,CamelCase来取代camelCase或snake_case,不过我在引用外部代码时会保留如下写法:std::for_each()。我还会遵循如下约定,在使用数据成员时会加一个前缀“m”,例如:mMemberVar,而“s”用在静态变量(static variable)之前,例如:sStaticVar。

应该指出的是本书中的带有源码的例子常常是一个代码片段(code snippet),并不是带有完整功能的例子。本书中,我还经常省略掉例子的注释,这样做的原因是为了简洁和清晰。特别地,我常常省略头文件(header file)中的所有“预处理保卫”(译者注:preprocessor guard 避免出现重复 #include 头文件的情况)语句。我认为读者已经知道每个C/C++头文件都要放在保卫语句之内,还有就是把所有的API声明都放在某个一致的名空间之内(这将在第三章和第六章中讲述)。换句话说,我给出的每个头文件都隐含了如下代码:

[P4 代码 P20 第一段1]

#ifndef MY_MODULE_H

#define MY_MODULE_H

// required #include files...

namespace apibook {

// API declarations ...

}

#endif

 

提示

        我在全书中也会着重讲述API设计的各种建议和关键概念。这个“提示”标记方便你想重读某个概念时可以快速地找到它。如果你的时间非常紧迫,你可以简单地浏览书中的这些提示,然后再阅读周围的文字,这样你就可以找到那些你最感兴趣的主题。

 

本书网址

本书还有一个配套的网站,http://APIBook.com/。在这个网站,你可以找到关于本书的综合信息,以及配套资料,如完整的源码例子。你可以随意下载并自由使用。它们被设计成尽可能的简单,不过做为作为例子也还是很有用的。我已经使用了跨平台的CMake构建系统,这样方便编译和链接例子,他们应该都可以运行在Windows,Mac OS X和UNIX操作系统上。

我也会在网站上发布所有新的勘误信息,还包括网上的其它有用的API资源的链接,例如有趣的工具、文章和程序。

本书网站还提供了一个我写的API Diff的程序。该程序可以让你比较某个API的两个版本,浏览它们代码间的差异或并排格式可视化显示并排格式的可视化注释。你还可以给指定的发布版本给客户API生成所有变动的报告,这样客户就可以清楚地找到什么是他们需要的。这个程序可以在Windows,Mac OS X和Linux操作系统上运行。

Power by  YOZOSOFT
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值