Browsed by
标签: API

API设计原则 – Qt官网的设计实践总结

API设计原则 – Qt官网的设计实践总结

(感谢好友 @李鼎 翻译此文)

原文链接:API Design Principles – Qt Wiki
基于Gary的影响力上 Gary Gao 的译文稿:C++的API设计指导

译序

Qt的设计水准在业界很有口碑,一致、易于掌握和强大的API是Qt最著名的优点之一。此文既是Qt官网上的API设计指导准则,也是Qt在API设计上的实践总结。虽然Qt用的是C++,但其中设计原则和思考是具有普适性的(如果你对C++还不精通,可以忽略与C++强相关或是过于细节的部分,仍然可以学习或梳理关于API设计最有价值的内容)。整个篇幅中有很多示例,是关于API设计一篇难得的好文章。

需要注意的是,这篇Wiki有一些内容并不完整,所以,可能会有一些阅读上的问题,我们对此做了一些相关的注释。

PS:翻译中肯定会有不足和不对之处,欢迎评论&交流;另译文源码在GitHub的这个仓库中,可以提交Issue/Fork后提交代码来建议/指正。

API设计原则

一致、易于掌握和强大的API是Qt最著名的优点之一。此文总结了我们在设计Qt风格API的过程中所积累的诀窍(know-how)。其中许多是通用准则;而其他的则更偏向于约定,遵循这些约定主要是为了与已有的API保持一致。

虽然这些准则主要用于对外的API(public API),但在设计对内的API(private API)时也推荐遵循相同的技巧(techniques),作为开发者之间协作的礼仪(courtesy)。

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (47 人打了分,平均分: 3.45 )
Loading...
API设计:用流畅接口构造内部DSL

API设计:用流畅接口构造内部DSL

感谢@weidagang (Todd)向酷壳投递本文。

程序设计语言的抽象机制包含了两个最基本的方面:一是语言关注的基本元素/语义;另一个是从基本元素/语义到复合元素/语义的构造规则。在C、C++、Java、C#、Python等通用语言中,语言的基本元素/语义往往离问题域较远,通过API库的形式进行层层抽象是降低问题难度最常用的方法。比如,在C语言中最常见的方式是提供函数库来封装复杂逻辑,方便外部调用。

不过普通的API设计方法存在一种天然的陷阱,那就是不管怎样封装,大过程虽然比小过程抽象层次更高,但本质上还是过程,受到过程语义的制约。也就是说,通过基本元素/语义构造更高级抽象元素/语义的时候,语言的构造规则很大程度上限制了抽象的维度,我们很难跳出这个维度去,甚至可能根本意识不到这个限制。而SQL、HTML、CSS、make等DSL(领域特定语言)的抽象维度是为特定领域量身定做的,从这些抽象角度看问题往往最为简单,所以DSL在解决其特定领域的问题时比通用程序设计语言更加方便。通常,SQL等非通用语言被称为外部DSL(External DSL);在通用语言中,我们其实也可以在一定程度上突破语言构造规则的抽象维度限制,定义内部DSL(Internal DSL)。

本文将介绍一种被称为流畅接口(Fluent Interface)的内部DSL设计方法。Wikipedia上Fluent Interface的定义是:

A fluent interface (as first coined by Eric Evans and Martin Fowler) is an implementation of an object oriented API that aims to provide for more readable code. A fluent interface is normally implemented by using method chaining to relay the instruction context of a subsequent call (but a fluent interface entails more than just method chaining).

下面将分4个部分来逐步说明流畅接口在构造内部DSL中的典型应用。

1. 基本语义抽象

如果要输出0..4这5个数,我们一般会首先想到类似这样的代码:

//Java
for (int i = 0; i < 5; ++i) {
    system.out.println(i);
}

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (19 人打了分,平均分: 2.74 )
Loading...
千万不要把 bool 设计成函数参数

千万不要把 bool 设计成函数参数

我们有很多Coding Style 或 代码规范。但这一条可能会经常被我们所遗忘,就是我们经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性。不信?我们先来看看下面的代码。

当你读到下面的代码,你会觉得这个代码是什么意思?

widget->repaint(false);

是不要repaint吗?还是别的什么意思?看了文档后,我们才知道这个参数是immediate, 也就是说,false代表不立即重画,true代码立即重画。

Windows API中也有这样一个函数:InvalidateRect,当你看到下面的代码,你会觉得是什么意思?

InvalidateRect(hwnd, lpRect,  false);

我们先不说InvalidateRect这个函数名取得有多糟糕,我们先说一下那个false参数?invalidate意为“让XXX无效”,false是什么意思?双重否定?是肯定的意思?如果你看到这样的代码,你会相当的费解的。于是,你要去看一下文档,或是InvalidateRect的函数定义,你会看到那个参数是 BOOL bErase,意思是,是否要重画背景。

这样的事情有很多,再看下面的代码,想把str中的”%USER%”替换成真实的用户名:

str.replace("%USER%", user, false); // Qt 3

TNND,那个false是什么意思?不替换吗?还是别的什么意思,看了文档才知道,false代码大小写不敏感的替换。

其实,如果你使用枚举变量/常量,而不是bool变量,你会让你的代码更易读,如:

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (32 人打了分,平均分: 3.78 )
Loading...
Google未公开API:转MAC地址为经纬度

Google未公开API:转MAC地址为经纬度

这里有一个POC(Proof of Concept)可以通过你Web浏览器后面的路由器XSS攻击得到一个准确的GPS坐标。注意:路由器和Web浏览器以及IP地址并不包含任和地理信息。其方法是使用了一个Google未公开的API。大约方法如下:

  1. 访问一个网页,这个网页隐藏了一个基于你WiFi路由器的XSS( 参见: XSS  Verizon FiOS router
  2. 通过这个XSS 可以获得路由器的MAC 地址。
  3. 然后通过 Google Location Services我们可以把这个MAC地址映射到GPS坐标。Googel的这个服务是基于HTTP的服务。这并不是一个Google正式发布的API,而是通过 Firefox’s Location-Aware Browsing 发现的。

演示地点在这里:http://samy.pl/mapxss/

我试了一下,无论无线和有线都可以准确定位我的位置。很强大,你也试试看。

好烂啊有点差凑合看看还不错很精彩 (7 人打了分,平均分: 3.29 )
Loading...