浅谈API设计
为什么需要了解一些API设计?
只要你编程,你就是API Designer
一个好的设计,模块之间的耦合应该也是API级别的
一个程序,如果你独立开发,那你既是API的Designer,也是API的User
如果你和你的同事一起开发,,你既是你开发的模块API的Designer,也是其他同事模块API的User
一个好的API应该具备哪些特点?
1. 易学易用(Easy to learn and use)
要做到易学易用,需要满足以下基本要求:
a. API命名的要适应用户的习惯并遵循一些模式。例如:使用类似于add/delete, get/set,push_bach/pop_back这种大家比较熟悉的命名方法。避免用户使用get获取一个数据,但是需要使用insert插入数据。
b. API的设计需要尽量简化用户的使用复杂度,我们看下STL vector的使用,非常简洁!
// vector::push_back
#include <iostream>
#include <vector> int main ()
{
std::vector<int> myvector;
int myint; std::cout << "Please enter some integers (enter 0 to end):\n"; do {
std::cin >> myint;
myvector.push_back (myint);
} while (myint); std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; return 0;
}
c.尽量提供一些方便用户的api方法
例如提供一个STL vector提供at方法供用户获取指定位置的元素
reference at (size_type n);
但同时也提供API供用户直接获取第一个和最后一个元素
reference front();
reference back();
2. 引导用户写出可读性高的代码(Leads to readable code)
好的API设计,可以引导用户写出高可读性的代码,下面这个例子非常生动:
实现 1:
slider = new QSlider(8, 128, 1, 6, Qt::Vertical, 0,
"volume");
实现 2:
slider = new QSlider(Qt::Vertical);
slider->setRange(8, 128);
slider->setValue(6);
slider->setObjectName("volume");
显然第二种设计更易引导用户写出可读性高的代码
3. 很难被误用
一个好的API设计,会使用户很容易写出正确的代码,而不是错误的代码。
这点非常重要,如果你的API很容易用错,那么,一方面用户会吐槽,另一方面,API的维护成本也很高
so,当你收到很多错误报告的时候,不要抱怨用户的使用方法有问题,review下自己的API,是不是很容易被误用
4. 方便扩展(Easy to extend)
api会变的越来越“大”,未来,api会提供新的类,类中会有新的方法,方法会有新的参数,枚举数据也会有新的枚举值。
因此,在API设计过程中,需要时刻提醒自己保证API的可扩展性
5. 完整(Complete)
所谓的完整,并不是指API满足用户所有的功能需求,而是说,基于这些API,可以满足所有功能需求。
我们还是拿STL::Vector来做说明,从获取数据的角度,API提供了reference at (size_type n); 就是完整的,另外提供的front back都是方便用户获取数据,用户完全可以个性化实现这样的功能。但是,如果只提供了front、back,而没有提供at这样的api,就是不完整的
兼容性
在设计API时,非常重要的点是要提前考虑API的发布方式,在发布过程中,兼容性非常重要
我们可以将兼容性分为:源代码兼容,二进制兼容,功能兼容
在Deliver新版本的API时,需要明确告知用户,API版本在哪些层面做到了向后兼容
源代码向后兼容:老的程序,使用新的API库依然能够正常工作
二进制向后兼容:直接升级库文件,老的程序不必重新编译就能使用新的库文件
功能兼容向后兼容:老的程序,使用新的API库,不影响已有功能
功能兼容是业务的范畴,这里不展开。着重讨论下源代码兼容和二兼职兼容。一个很有意思的讨论Source compatible vs. Binary compatible
一般来说,二进制兼容是源代码兼容的子集。如果你的代码打破了源代码兼容,基本上可以肯定你也打破了二进制兼容。相反则不成立,一个API是源代码兼容但不是二进制兼容表示你的代码无需如何修改,只要重新编译程序即能正常工作。
我们看下c++来,什么情况下我们会满足源代码兼容,但不满足二进制兼容
c++发布api有静态和动态库两种方式,这两种发布方式各有优劣,当采取动态库的发布方式,就面临二进制兼容问题
c++通过头文件使用动态库,编译时也据此产生二进制代码,因此,在考虑动态库兼容性的时候,只要考虑库使用已有的头文件是否和新的动态库兼容
c++使用动态库最常见的二进制兼容问题就是使用虚函数作为接口产生的。c++虚函数通过虚函数表实现,虚函数表具有以下特点:
1)虚函数按照声明顺序放在表中
2)父类的虚函数放在子类的虚函数之前
so,如果我们在新版本的动态库中插入新的接口定义,由于虚函数的顺序,导致二进制兼容问题
即使你在你的接口中将新增虚函数放在最后,由于接口可能被继承,而父类的虚函数在子类虚函数之前,因此还是会导致二进制兼容性问题
为了解决这个问题,我们可以采用pimpl来解决!
有一篇非常棒的文章,C++ 工程实践(5):避免使用虚函数作为库的接口
一些API开发的建议:
1. 践行TDD
2. 如果可能,尽早和API使用方沟通
3. 重视命名,它比你想象的更重要
Reference:
Joshua Bloch:How to Design a Good API and Why it matters
Jasmin Blanchette Trolltech :The Little Manual of API Design
Kinds of Compatibility: Source, Binary, and Behavioral
浅谈API设计的更多相关文章
- [UWP]浅谈按钮设计
一时兴起想谈谈UWP按钮的设计. 按钮是UI中最重要的元素之一,可能也是用得最多的交互元素.好的按钮设计可以有效提高用户体验,构造让人眼前一亮的UI.而且按钮通常不会影响布局,小小的按钮无论怎么改也不 ...
- 浅谈API网关(API Gateway)如何承载API经济生态链
序言 API经济生态链已经在全球范围覆盖, 绝大多数企业都已经走在数字化转型的道路上,API成为企业连接业务的核心载体, 并产生巨大的盈利空间.快速增长的API规模以及调用量,使得企业IT在架构上.模 ...
- 浅谈UI设计中妙用无穷的深色系背景
英文:medium 译者:优设网 - 陈子木 链接:http://www.uisdc.com/ui-benefits-of-dark-background# --------------------- ...
- 浅谈API安全设计
一.简述 安全是恒久的话题,如果不注意防范,会带来很严重的后果.比如: 1.接口被大规模调用消耗系统资源,影响系统的正常访问,甚至系统瘫痪 2.数据泄露 3.伪造(篡改)数据,制造垃圾数据 4.App ...
- 开源项目 PM 浅谈如何设计官网
有用户反馈进入官网首页光秃秃的一片,大家忙着做产品,忽略了官网的建设,惭愧惭愧. 确实,极简风格和极其简单还是有很大区别的. 旧的 Web 端 除了极其简单之外,它还有一个小问题, ...
- 浅谈BUFF设计
Buff在游戏中无处不在,比如WOW.DOTA.LOL等等,这些精心设计的BUFF,让我们击节赞叹,沉迷其中. 问:BUFF的本质是什么? BUFF 是对一项或多项数据进行瞬间或持续作用的集合.(持续 ...
- Redis系列六 - 浅谈如何设计秒杀系统
前言 设计一个系统之前,我们肯定要先确认系统业务场景是怎样的,下面就以某电商平台上的秒杀活动为场景,一起来探讨一个秒杀系统改如何去设计. 场景 我们现在要卖100件纸尿布,按照系统的用户量及以往经验来 ...
- mybatis缓存源码分析之浅谈缓存设计
本文是关于mybatis缓存模块设计的读后感,关于缓存的思考,关于mybatis的缓存源码详细分析在另一篇文章:https://www.cnblogs.com/gmt-hao/p/12448896.h ...
- 浅谈API和SDK的区别
首先了解一下他们的定义 API:application program interface 应用程序接口 通常表示一些事先定义好的函数,为了向外部提供一组功能的实现,实现和其他软件的交互 SDK:so ...
随机推荐
- jQuery学习-事件之绑定事件(五)
大家应该还记得dispatch方法中有这么一段代码: event = jQuery.event.fix( event ); event的修复是在fix这个方法中的,而在fix中是通过 new jQue ...
- Visual Studio 2012 Update3 安装失败错误“正在关闭管道'
问题描述: Visual Studio 2012 update3 安装失败错误“ 正在关闭管道' 环境: Windows 7 SP1(x86和x64) Windows 8(x86和x64) Windo ...
- Codeforces 325D
#include <cstdio> #include <algorithm> #include <cstring> #include <cstdlib> ...
- opennebula extend(expending) auth module ldap
LDAP Authentication addon permits users to have the same credentials as in LDAP, so effectively cent ...
- 优雅智慧女性课程班 - 公开课程 - 课程介绍 - 中国人民大学商学院EDP中心
优雅智慧女性课程班 - 公开课程 - 课程介绍 - 中国人民大学商学院EDP中心 优雅智慧女性课程班 课程总览 思想睿智成熟,外表美丽自信,气质优雅端庄,是魅力女性所应具备的特性.在当今不确定环境下, ...
- Spring流程
Spring Web Flow是Spring框架的子项目,作用是让程序按规定流程运行. 1 安装配置Spring Web Flow 虽然Spring Web Flow是Spring框架的子项目,但它并 ...
- C#复制数据库,将数据库数据转到还有一个数据库
本文章以一个表为例,要转多个表则可将DataSet关联多个表.以下给出完整代码.包含引用以及main函数与复制函数. 要说明的是,必须先用Sql语句复制表结构,才干顺利的使用下面代码复制数据. usi ...
- Thrift使用实例
首先下载thrift.exe,和对应lib包.注意版本一定要一致. 否则编译会不识别出现错误. 可能会出现org.slf4j这个错误,那么你要把slf4j-api.jar下载下来引入到你的projec ...
- php汉字生成首字母
function getfirstchar($s0){ $fchar = ord($s0{}); }); $s1 = iconv("UTF-8","gb2312" ...
- JAVA 年轻代收集器 第九节
JAVA 年轻代收集器 第九节 继续上一章所讲的,STW即GC时候的停顿时间,他会暂停我们程序中的所有线程.如果STW所用的时间长而且次数多的话,那么我们整个系统稳定性以及可用性将大大降低. 因此我 ...