29、OSPF配置实验之被动接口
924
2022-11-13
本文目录一览:
接口设计一般出现在软件开发的概要设计阶段,概要设计要根据需求划分模块,而模块之间的联系就是通过定义接口实现的。例如有模块A,B。A,B互相不知道对方实现的细节,当A要用到B中的功能时,就要使用模块B提供的外部接口,接口可以理解为一些功能函数的原型,包括函数名,参数列表和返回值。
在稍大型一点的项目中,总会有一个base层,我们认为它封装了最最底层和基础的一些列功能,因为底层的东西追求稳定和运行效率,所以90%是用C/C++写的,一般以头文件+DLL的方式给上层使用(不考虑它是基于COM的,如果是COM,VARIANT的参数类型就不在讨论范围内了)。头文件中定义了一些列导出函数或者导出类,这些导出函数或类的成员函数,都会有一些列参数,由于C/C++是强类型语言,所有强类型语言对类型转换都是极其严格的,不能像javascript里那样用var j = ... 的形式搞定一切。所以,底层接口中函数的参数如何设计是非常重要的。
假设有一个接口void A(int a),就只能接受一个int类型作为参数。
1、当需求变了,需要处理string类型时,就要修改A或者增加新的接口A1;
void A(int a);
void A(const string str);
或void A1(const string str);
2、当参数个数变了,需要接受两个int时,仍然需要修改;
void A(int a, int b);
如果两天后上层又提需求,说需要三个int参数...好吧,再改
void A(int a, int b, int c);
如果确实修改了这个接口A的参数类型或者参数个数或者增加新的接口A1,则必然导致至少两中问题:
1、所有引用这个头文件的cpp文件重编,而一个底层模块在整个项目中使用的普遍性是非常高的,那么最严重的情况就是,修改了一个头文件,造成整个项目重编;
2、所有调用过这个接口的上层代码都需要重新修改,更悲剧的是,还需要重新测试。
所以,如何才能涉及出具有很强适应力和扩展性的接口及参数类型,对于底层的接口是很重要的,也是必须的。
大概总结了一些,目测有这么几种方案,有些是坑爹的,有些在某些场合特定场合比较使用,有些比较通用。
1. void*
void*做参数在纯C语言写的代码里还是挺常见的,比如一个接口void A(void* p);
那如果你在A里对p进行某些类型转换,比如double *pd = (double*)p; 而传入的p原先是int* pn,那就惨了,多半*pd 不是原来的*pn,这就是用void*做参数的悲剧之处,它不携带原来的类型信息,对于使用者来说不知道应该怎么转,而且转了就有风险。这种void*参数现在几乎是绝对不允许使用的。
2.联合体类型
[html] view plain copy
struct param
{
int id;
union BaseArg
{
struct CommonEventArg
{
RECT rcItem;
}CommonEventArgs;
struct RightMenuArg
{
BOOL bShowDesk;
BOOL bWndMoved;
int nIconSize;
}RightMenuArgs;
struct ItemDragArg
{
RECT rcBegin;
RECT rcEnd;
}ItemDragArgs;
struct ItemSelectArg
{
BOOL isSelected;
}ItemSelectArgs;
struct BoxItemUpdateArg
{
RECT rcBegin;
}BoxItemUpdateArgs;
struct BoxRenameArg
{
wchar_t *pszName;
}BoxRenameArgs;
struct FileChangeArg
{
LPITEMIDLIST pItem;
LPITEMIDLIST pAdditionItem;
}FileChangeArgs;
struct RightMenuResponseArg
{
int nX;
int nY;
}MenuResponse;
struct StringArg
{
const wchar_t *pszName;
}StringArgs;
}Data;
};
比如这样一个结构体参数param,它包了一个联合体,这样做的思路也很清晰,接口这么定义:void A(const param p);当需要变时,就去改param里面的结构就好,外头不用动。里面增加了联合体的包装,其实是把这种思路优化了一把,因为如果param使用场合很多,用到N多种结构体,那么一个param对象就占用很多内存,而我们知道联合体并不会给它的每一个成员分配内存,而是用它内存需要最多的那个成员的内存长度作为整个联合体的内存长度,这样,就着实省了一把内存。
这样的涉及,比较常见的应用场合貌似是消息的响应,似乎MFC里的消息响应就是这么涉及的,Mouse消息、LBtn消息等等各自有不同的子struct包在联合体内。
3.json做参数
json做为一种小巧轻便易解析,最重要的强大的可修改性和可扩展性(这点有上面第二点struct+union的意思,但更强大)的玩意,不做参数实在是有点可惜,貌似我知道的的比较早的使用在网络传输,以及客户端和web方通信上比较多,其实网络传输也可以看成是一次函数调用嘛,那json就可以理解成这个函数调用的参数了。
4.模版
模版生来就是为了泛化的,经典的 int Add(int a, int b)经过模版化后就可以处理所有数值类型的加法操作了,但问题是什么呢?问题就是模版函数或模板类不适合作为模块接口,如果是在模块内用模版那是完美的设计,但如果在模块接口一级用模版,那就悲催了。因为上面说了,模块一般是以头文件+DLL的方式提供,而模版的一个特点就是不支持分离编译(这个不清楚的自行google),就是说,模版的实例化是要在编译时才决定的,你把模版函数的声明和实现分别放在头文件和cpp中,那是不行滴,必须都放在头文件中,那这样也就不叫模块话了,直接全给头文件就行了,boost大部分是这么搞的。
5.boost::any
这个东西是boost提供的又一牛逼东西,实现了类似于var j = ...的傻瓜式参数类型,相当于把本身强类型的C/C++中的参数封装成javascript中的弱类型。
[html] view plain copy
void my_func(boost::any a)
{
if(a.type() == typeid(int))
{
//int类型
}
else if(a.type() == typeid(string))
{
//string类型
}
//...
}
my_func(10);
my_func("123");
class custom
{
int b;
double d;
};
custom cus;
my_func(cus);
[html] view plain copy
span style="font-family: Arial, Helvetica, sans-serif;"
/span
[html] view plain copy
span style="font-family: Arial, Helvetica, sans-serif;"或/span
[html] view plain copy
span style="font-family: Arial, Helvetica, sans-serif;"
/span
[html] view plain copy
typedef std::listboost::any list_any;
list_any.push_back(10);
list_any.push_back("123");
class custom
{
int b;
double c;
char *p;
};
custom cus;
list_any.push_back(cus);
[html] view plain copy
span style="font-family: Arial, Helvetica, sans-serif;"
/span
[html] view plain copy
span style="font-family: Arial, Helvetica, sans-serif;"一个python中的列表就诞生了。/span
[html] view plain copy
span style="font-family: Arial, Helvetica, sans-serif;"貌似设计模式里的开放封闭原则套到函数参数的设计上也是适用的吧,提高参数扩展性,尽量不修改。/span
对于接口测试,首先测试人员要懂代码,你只需要知道接口的作用是什么就可以了(有文档更好,但大部分都没有);其次,自己去读开发的代码;然后,根据该接口功能及代码写测试用例;
用例设计:
1:写一个程序去调用该接口,看是否能够达到该接口所定义的功能
2:根据该接口参数,构造不同的用例,测试接口在参数合法及非法情况下能否达到预期效果
3:根据该接口中的逻辑,设计不同条件的用例,测试该接口实现代码的逻辑
4:进行容错及健壮性测试
5:静态检测代码,看是否有内存泄露、或永远走不到的分支、代码规范及逻辑是否合理。
6:对于一些接口,需要进行多线程测试
接口测试发现的典型问题:
(1)传入参数处理不当,导致程序crash;
(2)类型溢出,导致数据读出和写入不一致;
(3)因对象权限未进行校验,可以访问其他用户敏感信息;
(4)状态处理不当,导致逻辑出现错乱;
(5)逻辑校验不完善,可利用漏洞获取非正当利益等。
用例设计:
1:入参类型:
数值型 :
如果参数规定了值的范围,则需要考虑等价类取值范围内、取值范围外,取值的边界,如有需要,可能会遍历取值范围内的各个值。
类型的特殊值:-1,0
数据类型的边界值:int的最小值最大值;
特殊值处理不当导致程序异常退出;
类型边界溢出
取值范围外值未返回正确的错误信息等
字符串型:
字符串型的参数,主要考虑字符串的长度和内容:
特殊值:空字符;
边界值:String的最大长度;
字符串内容可考虑类型:数字,非数字;
特殊字符。
超长字符未进行处理,导致存储、显示等异常
数组或链表类型
参数类型为数组或链表时,用例可以考虑:
例如批量提交任务的接口submitTask(int[] taskID),参数用例设计考虑:
正常取值:1-5个权限,范围外:6个权限;
边界值:1-35的边界值,请求允许最大最小值;
特殊值:0个;
合法ID和不合法的;
重复的ID等。
可能存在的问题和风险:
0个item时程序异常退出;
重复的item处理时未去重导致结果异常等。
2:针对逻辑设计
约束条件分析
(1)数值限制:分数限制、金币限制、等级限制等等。
例如:兑换Q币活动要求积分50才可参与。
(2)状态限制:登录状态等。
例如:同步用户信息需要先登录账号。
(3)关系限制:绑定的关系,好友关系等。
例如:帮家人防骗功能只能查询绑定家人的来电信息。
(4)权限限制:管理员等。
3: 针对输出结果
接口处理正确的结果可能只有一个,但是错误异常返回结果有很多情况很多值。如果知道返回结果有很多种,就可以针对不同结果设计用例。例如提交积分任务的时候我们通常能想到的是返回正确和错误,错误可能想到:无效任务,无效登录态,但是不一定能否完全覆盖所有错误码,而接口返回定义的返回码可以设计更多用例:
覆盖返回码也是用例设计的一种思路。
常见问题和风险:
(1)错误前端处理不足,导致前端异常;
(2)错误提示处理不当,导致用户看到晦涩的错误码;
(3)错误提示不当,导致用户不知道哪里出了问题,如何解决。
4:接口超时
( 1)未进行超时处理,导致整个流程阻塞
(2)超时后又收到接口返回,导致逻辑出现错乱
接口设计的主要依据是形象;因为在平面设计中,一组相同或相似的形象组成,其每一组成单位成为基本形,基本形是一个最小的单位,利用它根据一定的构成原则排列、组合、便可得到最好的构成效果。
接口设计主要包括:
1.形状的渐变:一个基本形渐变到另一个基本形,基本形可以由完整的渐变到残缺,也可以由简单到复杂,由抽象渐变到具象;
2.方向的渐变:基本形可在平面上作有方向的渐变;
3.位置的渐变:基本形作位置渐变时需用骨架,因为基本形在作位置渐变时,超出骨架的部分会被切掉;
4.大小的渐变:基本形由大到小的渐变排列,会产生远近深度及空间感;
5.色彩的渐变:在色彩中,色相、明度、纯度都可以出渐变效果,并会产生有层次感的美感;
6.骨格的渐变:是指骨格有规律的变化,使基本形在形状、大小、方向上进行变化。划分骨格的线可以做水平、垂直、斜线、折线、曲线等个总骨格的渐变。渐变的骨格精心排列,会产生特殊的视觉效果,有时还会产生错视和运动感。
扩展资料:
接口设计随着现代科技的发展、知识社会的到来、创新形态的嬗变,设计也正由专业设计师的工作向更广泛的用户参与演变,以用户为中心的、用户参与的创新设计日益受到关注,用户参与的创新2.0模式正在逐步显现。
用户需求、用户参与、以用户为中心被认为是新条件下设计创新的重要特征,用户成为创新2.0的关键词,用户体验也被认为是知识社会环境下创新2.0模式的核心。
设计不再是专业设计师的专利,以用户参与、以用户为中心也成为了设计的关键词,Fab Lab、Living Lab等的创新设计模式的探索正在成为设计的创新2.0模式。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~