什么是认知维度 
认知维度(也称作符号认知维度,Cognitive Dimensions or Cognitive Dimensions of Notations,简称CD)是一套关于符号标记、用户界面和编程语言的设计原则。
认知维度提供一种轻量级的方法来帮助分析设计,它包含了14条不同的维度来指导设计。API的可用性 
API和一般的产品一样,也需要具有良好的可用性。但API的不同之处在于,它一旦被发布出去,修改升级都比较困难。如果你变更了API,很多使用你API开发出来的产品就会受到影响,甚至无法正常工作。
所以我们在发布一套API之前,一定做了很多工作:严谨的设计、严格的测试等等。但是很少有人关注API的可用性,也没有行之有效的方法来指导API的可用性设计。
在微软,认知维度这个工具被拿来用在了API的可用性设计上,并对其进行适当的修改,形成了新的12个维度。
我们先来看看认知维度中的一个维度:Abstraction Level
Abstraction Level 
Abstraction Level在CD中的描述为Abstraction Gradient,其解释为:
What are the minimum and maximum levels of abstraction exposed by the notation? Can details be encapsulated?
用到API设计中,可以转化为如下解释:
What are the minimum and maximum levels of abstraction exposed by the API, and what are the minimum and maximum levels usable by a targeted developer.
这个维度可理解为API所暴露出来的抽象层次是什么样的。如果抽象层次高,开发者使用起来将会感觉非常简单、方便,但缺点是不够灵活,缺乏自定义性;如果抽象层次低,则系统具有较大的灵活性,但却牺牲了部分易用性,开发者学习起来的代价也比较大。
我们通过一个具体的使用场景来理解这个概念,下面的代码片段在地图上创建了两个按钮,点击这两个按钮可分别将地图进行放大一级和缩小一级的操作:// 示例一
map.addControl(new 
BMap.StandardMapControl({type: BMAP_STD_MAP_CONTROL_ZOOM_ONLY}));创建按钮实际上是向地图容器里添加了新的DOM元素,并指定了一些样式,最后再绑定两个click事件,并在事件监听函数中调用map的zoomIn和zoomOut方法。
在地图API中,这些细节都被封装成为抽象的控件,对于开发者来说只要new一个这样的控件,同时指定一种外观类型(BMAP_STD_MAP_CONTROL_ZOOM_ONLY指仅包含放大和缩小按钮),再add到地图当中就好了。
可以看出这样的接口使用起来简单,接口数量少,也容易理解。
BMap.StandardMapControl的样式是预先定义好的,最多支持开发者选择几种不同的展现形式,如果开发者希望自定义按钮的样式该如何做?
这时可以选用抽象层次较低的API,请看下面示例:// 示例二
// 定义一个控件类
var ZoomControl = function(){  // 默认停靠位置和偏移量
  this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT;
  this.defaultOffset = [10, 10];};
ZoomControl.prototype = new BMap.Control();
ZoomControl.prototype.initialize = function(map){  // 容器元素
  var container = document.createElement("div");  var divZoomIn = document.createElement("div");
  divZoomIn.appendChild(document.createTextNode("放大1级"));  var divZoomOut = document.createElement("div");
  divZoomOut.appendChild(document.createTextNode("缩小1级"));  container.appendChild(divZoomIn);
  container.appendChild(divZoomOut);
  // 设置样式  container.style.fontSize = "12px";
  divZoomIn.style.cursor = "pointer";  divZoomIn.style.border = "1px solid gray";
  divZoomIn.style.backgroundColor = "white";  divZoomOut.style.cursor = "pointer";
  divZoomOut.style.border = "1px solid gray";  divZoomOut.style.backgroundColor = "white";
  // 绑定事件
  divZoomIn.onclick = function(e){
    map.zoomIn();
  }
  divZoomOut.onclick = function(e){
    map.zoomOut();
  }
  // 添加DOM元素到地图中
  map.getContainer().appendChild(container);
  // 将DOM元素返回
  return container;
}// 创建控件
var myZoomCtrl = new ZoomControl();// 添加到地图当中
map.addControl(myZoomCtrl);在上面这个代码片段中,开发者使用了抽象层次较低的DOM API来实现元素创建、样式定义和事件绑定,同时还需要了解JavaScript的prototype继承机制以及地图API约定的继承控件BMap.Control的方法
(比如将new BMap.Control()赋值给prototype对象,initialize接口需要开发者自行实现等等)。
这样做极大地满足了开发者对灵活性的要求,但也要求开发者需要掌握更多的接口和内容(DOM编程、高级JavaScript编程、API使用方法等等),同时代码的数量和复杂程度也增大了。
再来看下面的例子,有个开发者希望创建一个地图,并且在地图上添加一些控件,使地图界面看起来和百度地图(http://map.baidu.com)的界面一样,那么以下代码可以实现这个需求:// 示例三// 依次创建导航控件、缩略地图和比例尺
map.addControl(new BMap.StandardMapControl());
map.addControl(new BMap.OverviewMapControl());
map.addControl(new BMap.ScaleControl());上面的代码通过多次添加不同的控件使该地图界面与百度地图保持一致。如果我们提供一个抽象层次更高的接口呢?可能会有如下的调用方式:// 示例四
map.addTypicalContorls();上面代码将之前的三句addControl换成了一句addTypicalContorls,添加多个控件的任务完全由addTypicalContorls方法内部去完成。
通过上面的示例我们看出,示例一和示例三的抽象程度属于中等,示例二的抽象程度低,示例四的抽象程度最高。
接口的抽象层次越高,开发者入门越容易,使用的接口数量少,但接口的灵活性低;反过来,接口的抽象层次越低,开发者需要了解的东西就越多,运用的接口数量也越多,代码写起来越复杂,但好处是接口灵活。
相信大部分开发者在刚接触一套新的API时,都喜欢通过少量的接口就能完成一些任务,这样学习成本低,开发起来起来也更轻松容易。
随着入门者逐渐使用API,他们当中就会出现一些具有一定开发经验且在灵活性上有很高要求的人,这就要求API能够提供一些层次较低、灵活程度较高的接口。
这些人也希望通过多个接口的组合来帮助自己实现功能。
在一套大型的API或者一个framework当中,需要考虑为不同的开发者提供不同抽象层次的接口,最大程度满足不同的需求。