条款18:让接口容易被正确使用,不易被误用

简介: 条款18:让接口容易被正确使用,不易被误用
程序设计中经常遇到的便是如何设计接口,让用户能够直观的、快速的了解并上手使用接口。让接口容易被正确使用,不易被误用便是本条款所强调的。
理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不应该通过编译;如果代码通过了编译,他的作为就该是客户所想要的。

比如这样一个表示时间的类:

class Date {
public:
    Date(int month, int day, int year);
};

如果我们不对接口做一些“强制性“的约束,该接口就可能被误用:

Date date(2022, 2, 25); //传参顺序不对
Date date(31, -1, 0); //参数非法

虽然上述调用可以通过编译,但却可能与用户意图违背。为此我们可以采用类型系统:

class Month {
public:
    explicit Month(int m) : month(m) {
    }
private:
    int month;
};
class Day {
public:
    explicit Day(int d) : day(d) {
    }
private:
    int day;
};
class Year {
public:
    explicit Year(int y) : year(y) {
    }
private:
    int year;
};
class Date {
public:
    Date(const Month &m, const Day &d, const Year &y);
};

这时,我们对用户使用该类的方式做了一些约束,比如:

Date date(2022, 2, 25);       //报错,explicit禁止隐式类型转换
Date date(Day(25), Month(2), Year(2022));//报错,传参顺序不对
Date date(Month(2), Day(25), Year(2022));//正确

虽然我们对传参的顺序,方式做了一定的约束,但是还是避免不了传入非法值,比如:

Date date(Month(22), Day(25), Year(2022));

月份为22显然不合法。为此,我们可以预先定义所有有效的值(即告知用户,只能使用这几个值哦):

class Month {
public:
    static Month Jan() { return Month(1); }
    static Month Feb() { return Month(2); }
    //...
private:
    explicit Month(int m);
};

再使用时,只能这样,这样总不会写错了吧?:

Date date(Month::Jan(), Day(25), Year(2022));

预防用户错误的另一个做法是,限制类型内什么事可做,什么事不可做。常见的限制是加上const。

比如:我们重载了*并且返回值被const限定,当用户一不小心将==写成=时,程序可以告知用户,唉?你这里是不是要做比较?而不是赋值??

if (a * b = c) // ?

后面部分理解不是很透彻,再续。

关于shared_ptr删除器的使用:

void del(int *p) {
  cout << "del" << endl;
}
void func() {
  shared_ptr<int> p(new int(3), del);
  cout << p << endl;
  shared_ptr<int> p1(new int(4), [](int *p) { cout << p << endl; cout << "lambda" << endl; });
  cout << p1 << endl;
}
相关文章
|
4月前
|
Rust 安全 程序员
Rust与C++的区别及使用问题之NSA建议停止使用C++的问题如何解决
Rust与C++的区别及使用问题之NSA建议停止使用C++的问题如何解决
|
SQL 自然语言处理 安全
如何撰写高质量的接口设计文档?这12个注意点要牢记!
如何撰写高质量的接口设计文档?这12个注意点要牢记!
377 1
|
数据采集 算法
拒绝想当然,不看文档导致GNE 的隐秘 bug
拒绝想当然,不看文档导致GNE 的隐秘 bug
101 0
|
设计模式 Java 程序员
怎样才能写出规范的好代码?
最近发现一件事情,自己写的代码和公司里工作5到10年的前辈写的代码虽然功能一样,但是他们的代码更规范,更优雅。比如有时候我会给一个需求写一个方法,但是有些人就可以好几个需求通过同一个方法实现。因此有了今天这个疑问,怎样才能写出规范的好代码?
|
安全 程序员 编译器
代码防御性编程的十条技巧
代码防御性编程的十条技巧
257 0
代码防御性编程的十条技巧
|
Java 程序员
用了这么久的equals,你知道还要遵守约定么(上)
重写equals 方法看起来很简单,但是还会有多种方式导致出错,后果可能是严重的。最简单,最容易避免出错的方式是 避免重写equals方法 ,采用这种方式的每个类只需要和自己对比即可,这样永远不会出错。如果满足了以下任何一个约定,也能产生正确的结果:
用了这么久的equals,你知道还要遵守约定么(下)
重写equals 方法看起来很简单,但是还会有多种方式导致出错,后果可能是严重的。最简单,最容易避免出错的方式是 避免重写equals方法 ,采用这种方式的每个类只需要和自己对比即可,这样永远不会出错。如果满足了以下任何一个约定,也能产生正确的结果:
|
算法 程序员 编译器
程序员特有的小习惯,你中招了吗
  在一个行业里待得越久,也就越有可能养成一些工作时的小习惯。今天我们就一起走近程序员的世界,看看程序员们都有些什么小习惯,这些小习惯你中招了几个?   1.熟练使用Ctrl+S、Ctrl+C、Ctrl+V的快捷键。有时候会下意识Ctrl+S,出来保存页面的框时又默默地关掉。   2.看到不错的页面,习惯按F12.   3.浏览器只用谷歌。   4.每次写完一行代码,或者修改了一个小地方,左手会拼命按Ctrl+S进行保存。   5.聊天喜欢使用Ctrl+Alt+Z提取消息,打完字按Alt+S发送,然后马上按Alt+C关闭聊天窗口。   6.熟练使用win+D来切换窗体,躲避老板。
98 0
泛型带你规避风险 | 带你学《Java面向对象编程》之六十四
本节由转型风险引出了一个新的概念-泛型,并为读者简单介绍了泛型的定义方法与泛型类实例化方法。
|
开发者 前端开发
[译] 如何避免我作为初级开发者时所犯下的 7 个错误
我们应该从中吸取教训。在成为高级开发者的过程中,我犯过许多错误。本文讲述了当我还是初级开发者时犯过的 7 个严重错误,以及如何避免这些错误。
892 0