浅谈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 ...
随机推荐
- Linux系统针对网卡中断的优化处理
摘要: 中断: 当网卡接收到数据包后,会触发硬中断,通知CPU来收包.硬中断是一个CPU和网卡交互的过程.这其实会消耗CPU资源.特别是在使用速度极快的万兆网卡 之后,大量的网络交互使得CPU很大一部 ...
- matlab绘制函数
>> x1=linspace(,*pi,); x2=linspace(,*pi,); x3=linspace(,*pi,); y1=sin(x1); y2=+sin(x2); y3=+si ...
- 手工制作OTG连接线 让小白实现OTG功能
说到OTG功能,很重要的一点是,现在不少网上的720P高清视频体积已经超过4GB,我的小白也支持exFat及NTFS磁盘格式,可存储播放大于4GB的高清影音文件,也能通过OTG读取播放NTFS格式U盘 ...
- poj1477---搭积木
#include<stdio.h> #include<stdlib.h> int main() { int n,i; int bricks[55],set=0; while(s ...
- LinqToSQL实例参见
/// <summary> /// (增)向表中插入数据 /// </summary> public void InsertData() { LinqToSQLDataCont ...
- HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意:给出一个带边权的图.对于每一个询问(S , ...
- 依赖注入及AOP简述(十三)——AOP应用举例(完结) .
2. AOP应用举例 在一般的应用程序开发中,有一些典型的AOP应用,使得开发者可以专注于业务逻辑本身,而不是与之完全无关的一些“方面”. l 首先就是关于前面介绍过的日志输出类 ...
- 使用Vitamio打造自己的Android万能播放器(4)——本地播放(快捷搜索、数据存储)
前言 关键字:Vitamio.VPlayer.Android播放器.Android影音.Android开源播放器 本章节把Android万能播放器本地播放的主要功能(缓存播放列表和A-Z快速查询功能) ...
- 如何更快速加载你的JS页面
确保代码尽量简洁 不要什么都依赖JavaScript.不要编写重复性的脚本.要把JavaScript当作糖果工具,只是起到美化作用.别给你的网站添加大量的JavaScript代码.只有必要的时候用一下 ...
- .net的页面在大并发下偶尔出现503错误
我们开发了一个回调页面,由一个工具负责调用,由于压力非常大,回调页面通过6台服务器负载均衡的: 最近业务系统又再次扩容,回调页面压力成倍增加,在高峰时间段偶尔出现了503错误. 拿到这个问题首先对系统 ...