《C++ API设计》是一本不错的讲解C++接口设计以及软件工程的书籍,作者是前皮克斯架构师。值得一读。本文是在咬文嚼字,并非质疑作者观点。
书名 | API C++Design for C++ |
---|---|
中译本 | 《C++ API设计》 |
出版社 | 人民邮电出版社 |
版次 | 2013年9月第1版 |
2.4.3节 一致性
本节观点没有问题,就是阐述设计API时,要接口保持一致性,比如同一词语的缩写、相关函数中参数列表的顺序等等。
第37页(中译版)有一小段文字列举了一些违背API设计一致性的案例:
另一个例子是,标准C函数read( )和write( )将文件描述符作为其第一个参数,而fgets( )和fputs( )函数把文件描述符作为最后一个参数(Henning,2009)。
错误一目了然:
- 首先read( )和write( )并非标准C函数,而是属于Unix/Linux系统调用(system call)。出自POSIX标准,而非ANSI C;
- 其次fgets( )和fputs( )函数的最后一个参数不是文件描述符,而是文件指针。
注意:fgets( )和fputs( )函数属于ANSI C的标准库函数,标准库中的IO函数都是操纵的文件流指针(** FILE * **)而非文件描述符(file descriptor,实为整型)
原文给出了参考文献(Henning,2009)
,通过查阅附录,我找到这篇论文的信息:
M. Henning, API Design Matters, Commun. ACM 52 (5) (2009) 46-56
然后我就说ACM官网检索并下载了这篇论文,发现该论文原文其实是没有异议的,原文该段落写的不错,整体摘录如下:
Consistency is important because not only does it make things easier to use and memorize, but it also enables transference of learning: having learned a part of an API, the caller also has learned much of the remainder of the API and so experiences minimal friction. Transference is important not only within APIs but also across APIs—the more concepts APIs can adopt from each other,the easier it becomes to master all of them. (The Unix standard I/O library violates this idea in a number of places. For example, the read() and write() system calls place the file descriptor first, but the standard library I/O calls, such as fgets() and fputs(), place the stream pointer last, except for fscanf() and fprintf(), which place it first.This lack of parallelism is jarring to many people.)
关键的部分是我加粗显示的部分。阅读上下文可知,该处大意是说 “Unix 标准IO库在很多地方违反了一致性原则。比如,系统调用read()和write()将文件描述符放置在第一个参数,而标准库的函数,比如fgets()和fputs()等都是将流指针(即FILE *)放置在最后一个参数(除fscanf()和fprintf()以外)”
系统调用IO和标准库IO有着不一致性,同时标准库IO自身也存在着不一致性:fscanf()和fprintf()放置文件流指针在第一个参数位置,而其他标准库IO的函数则是放置在最后一个位置上。
笔者:其实fscanf()和fprintf()这么设计,是为了保持和scanf()/printf()、sscanf()/sprintf()的一致性嘛。但是为什么不把整个标准C库的文件流指针设计成第一个参数呢。。。
后记
多了解一些违反一致的例子,可以方便记忆整个库的API。