为用户设计良好的接口

前言

  作为一名优秀的程序员,必须保证自己的代码能提供正确的,完善的接口,如此方能和同事,甲方更好的沟通合作,也让自己的代码更加地容易维护。

  本文将介绍一些设计优秀接口的思路。

思路一:导入新的类型

  下面还是先看这个例子,我定义了一个存储日期的 Date 类:

1 class Date
2 {
3 public:
4     Date(int month, int day, int year);
5     // ......
6 };

  可用以下方法定义一个 Date 对象:

1 Date d(30, 3, 1995);

  可有些用户会犯很蠢的错误,比如:

1 Date d(30, 3, 1995);

  显然,他用户将接口的参数输错位了。然而,优秀的接口应当能够友好反馈错误信息给用户,这种情况下,最好的策略就是定义新的类型,请参考下面这个 Date 类的设计:

 1 class Day
 2 {
 3 public:
 4     explicit Day(int d)
 5         :val(d) {}
 6     // ......
 7 private:
 8     int val;
 9 };
10
11 class Month
12 {
13 public:
14     static Month Jan() {
15         return Month(1);
16     }
17     static Month Feb() {
18         return Month(2);
19     }
20     // ......
21
22 private:
23     explicit Month(int m) {
24         val = m;
25     }
26     // ......
27
28     int val;
29     // ......
30 };
31
32 class Year
33 {
34 public:
35     explicit Year(int y)
36         :val(y) {}
37 private:
38     int val;
39 };

  而定义一个 Date 对象,可采用如下方式:

1 Date d(Month::Feb(), Day(30), Year(1995));

  在日,月,年各个类中,还可以实现更高级的封装。

思路二:引导用户进行正确编码

  这里继续上一篇文章中提到的智能指针的一个例子,这里要说明的是,当时给出的那个工厂函数:

1 class Investment
2 {
3     // ......
4 };
5
6 Investment * createInvestment();

  并不是很好的一种设计。

  为啥?因为用户可能忘了使用智能指针把 Investment * 接过去。而使用下面的工厂函数接口设计可以有效的避免这个问题:

1 std::tr1::shared_ptr<Investment> createInvestment();

  这样就让用户你不用智能指针都不行了,哈哈。

  甚至你还可以更过分,指定智能指针在资源被指数为0的时候要调用的析构函数:

 1 std::tr1::shared_ptr<Investment> createInvestment()
 2 {
 3     // 指定智能指针类型及删除器
 4     std::tr1::shared_ptr<Investment>retVal (static_cast<Investment *>(0), getRidOfInvestment);
 5
 6     // retVal = ...
 7     // 令 retVal 指向正确的对象
 8
 9     return retVal;
10 }

  上段代码中的getRidOfInvestment是你自己指定的删除器。

思路三:限制类型什么事情可以做什么事情不能做

  使用 const,explicit等限制性关键字,屏蔽无用的拷贝构造函数等可以做到这点。

  这些在以前的文章中均有讲解。

思路四:使你的类尽量表现得像内置类型

  要做到这点可不简单,你需要以"当初语言设计者设计语言内置类型时"那般谨慎的思考class的设计,对设计出的class,我们需要问自己以下几个问题:

  1. 新的对象资源在何时创建? 何时销毁?

    这部分同样涉及到构造函数,析构函数的编写。

  2. 对象的初始化和赋值应该有什么样的差别?

    这部分涉及到构造函数,拷贝构造函数,赋值运算符的编写。不要混淆这两个概念。

  3. 如果对象发生了值传递,意味着什么?

    你得仔细考虑这期间发生的资源相关的一些问题。

  4. 哪些对象是合法范畴?

    对象的成员是不是合法,这点很重要。它影响到了你诸多成员函数的错误检查工作,也影响到了抛出的异常。

  5. 新的类需不需要配合某个继承图系?

    如果这个类的子类要实现多态,那么成员函数就得声明为虚函数;如果这个类继承自其它类,那么当你自定义拷贝构造函数或者重载赋值运算符的时候,也得对父类部分做出处理。

  6. 什么样的操作符和函数对这个新的类型来说是合理的?

    需要考虑这个类型应该对哪些运算符重载,还有哪些函数被当做成员函数,哪些用非成员函数实现。

    具体的选取规则,以后会有篇文章专门讲。

  7. 什么样的标准函数应当驳回?

    将它声明为 private

  8. 新的类型成员将被哪些对象取用?

    这个涉及到变量private,protected,以及友元相关机制。

  9. 新的类型是否应当满足一般化的要求?

    如果你要定义的是一个类家族,那么你需要的不止是一个类,而是一个类模板

小结

  1. 类的设计不要贪快。要尽量满足,实现这些规则,贪快会导致开发后期事倍功半。

  2. 本文应当在实际项目中进行类设计的时候边设计边看,如此,方能有显著的提高。

时间: 2024-10-08 20:40:06

为用户设计良好的接口的相关文章

第十二篇:为用户设计良好的接口

前言 作为一名优秀的程序员,必须保证自己的代码能提供正确的,完善的接口,如此方能和同事,甲方更好的沟通合作,也让自己的代码更加地容易维护. 本文将介绍一些设计优秀接口的思路. 思路一:导入新的类型 下面还是先看这个例子,我定义了一个存储日期的 Date 类: 1 class Date 2 { 3 public: 4 Date(int month, int day, int year); 5 // ...... 6 }; 可用以下方法定义一个 Date 对象: 1 Date d(30, 3, 19

NTP精准授时核心板定制设计 安全性好 接口丰富 授时容量大

NTP精准授时核心板定制设计 安全性好 接口丰富 授时容量大 NTP精准授时核心板是我公司自主研发设计,总结和归纳了以前产品的优缺点和用户体验后优化完善的产品.已广泛应用于电力自动化,通信基站,应急通信,数字广电,轨道交通,航空航天,金融自动化领域等需要精密时钟服务的场所. 一.授时核心板模块功能特点: 1.支持IEE1588-2008协议. 2.授时精度可达ns级,背靠背授时精度优于50ns. 3.支持组播和单播传输模式. 4.支持MASTER.SLAVE模式可灵活配置,2个10/100/10

微信小程序的Web API接口设计及常见接口实现

微信小程序给我们提供了一个很好的开发平台,可以用于展现各种数据和实现丰富的功能,通过小程序的请求Web API 平台获取JSON数据后,可以在小程序界面上进行数据的动态展示.在数据的关键 一环中,我们设计和编写Web API平台是非常重要的,通过这个我们可以实现数据的集中控制和管理,本篇随笔介绍基于Asp.NET MVC的Web API接口层的设计和常见接口代码的展示,以便展示我们常规Web API接口层的接口代码设计.参数的处理等内容. 1.Web API整体性的架构设计 我们整体性的架构设计

2.35 Java基础总结①抽象②接口③设计抽象类和接口的原则④接口和抽象类的区别

java基础总结①抽象②接口③设计抽象类和接口的原则④接口和抽象类的区别 一.抽象 abstract作用:不能产生对象,充当父类,强制子类正确实现重写方法和类相比仅有的改变是不能产生对象,其他的都有,包括构造.属性等等任何一个类只要有一个抽象的方法就成了抽象类 抽象方法 public abstract A();①方法是抽象的,这个类也是抽象的:②子类必须重写抽象方法,除非子类也是抽象类 抽象类可以没有抽象方法,但一般不这么设计 二.接口 interface 接口也是Java的一种引用数据类型(J

设计原则之接口隔离原则

segregate   v.隔离 se 蛇  gre green格林  gate门 蛇被格林用门隔离了. 设计原则之接口隔离原则 动机:         客户不应该被强制实现他们不用的方法.应该用多个小的接口代替庞大功能全的接口. 结论:        该原则在代码设计的时候就要考虑.可以使用适配器模式将胖接口隔离. Bad Example:    缺点:         1.如果新增一个robot机器人工人,那么eat方法就是多余的了. // interface segregation pri

PHP实现的注册,登录及查询用户资料功能API接口示例

这篇文章主要介绍了PHP实现的注册,登录及查询用户资料功能API接口,结合具体实例形式分析了php服务器端用户注册.登陆.查询及curl登陆查询功能实现技巧,需要的朋友可以参考下 本文实例讲述了PHP实现的注册,登录及查询用户资料功能API接口.分享给大家供大家参考,具体如下: 服务端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 3

领域模型中的用户设计

领域模型中的用户设计 上一篇:<DDD 领域驱动设计-如何控制业务流程?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新,并增加了应用层代码) 在 JsPermissionApply 领域模型中,User 被设计为值对象,也就是 JsPermissionApply 实体中的 UserId 属性,这个没啥问题,但后来再实现代码的时候,就出现了一些问题,在 JS 权限申请和审核系统中,用户的一些操作如下: 申请:根据当

计算机组成与设计硬件/软件接口 (MIPS版) a y

买了一本<计算机组成与设计硬件/软件接口(MIPS版)>,非科班出身的我,从事计算机行业已经8年了,却对计算机的基础什么也不专业.有点惭愧,因为对时间的流逝而感到遗憾!行了,但有言说,多无实义!言归正传,看书!思考! 这本书的英文名称是<Computer Organization and Design The HardWare / Software Interface> Fifth Edition Asian Edition, 可以这样翻译<计算机组成与设计--硬件/软件接口

[Effective JavaScript 笔记]第57条:使用结构类型设计灵活的接口

想象创建wiki的库.wiki网站包含用户可以交互式地创建.删除和修改的内容.许多wiki都以简单.基于文本标记语言创建内容为特色.通常,这些标记语言只提供了HTML可用功能的一个子集,但是却有一个更简单.更清晰的源格式.例如,环绕星号的文本被格式化为粗体,环绕下划线的被格式化为带有下划线的文本,环绕斜杠的被格式化为斜体.用记可以输入如下格式: this sentence contains a *bold phrase* within it. this sentence contains a _