首頁 >web前端 >js教程 >淺談關於JavaScript API設計的一些建議和準則_基礎知識

淺談關於JavaScript API設計的一些建議和準則_基礎知識

WBOY
WBOY原創
2016-05-16 15:53:111255瀏覽

 設計是一個很普遍的概念,一般是可以理解為即將做的某件事先形成一個計劃或框架。在牛津英語字典中,設計是一種將藝術,體系,五金或更多的東西編織到一塊的主線。軟體設計,特別是作為軟體設計的次類別的API設計,也是一樣的。但API設計常常很少關注軟體發展,因為為其他程式設計師寫程式碼的重要性要次於應用UI設計和最終使用者體驗。

但是API設計,作為我們自己寫的庫中提供的公共接口,能夠向調用我們代碼的開發者表現出我們庫的一些特點和功能,所以API設計和UI設計一樣重要。事實上,兩者都是為應用程式可以提供更好的用戶體驗具有基本的方式。應用UI在使用者UX中佔有很重要的位置,應用API是開發者的UX。因此,應用API設計應該被給予和我們提供給使用者的介面相同程度的考慮和關注。正像我們關注UI的功效,簡潔性和優美,我們也應該同樣的評估API的功效,簡潔性和程式碼的優美性!

API設計-javascript API設計的內容,呈現了唯一的挑戰對所有的開發者,不管是否你正在開發一個公共的函式庫或一個內部的函式庫。 javascript的動態性,庫使用者的匿名和需求的模糊性都給API設計者呈現了一個令人畏懼的挑戰。然而對於一個好的API設計是沒有捷徑的,但是可以從現代流行的一些javascript庫中提取出一些設計準則是可能的!

API設計: 天使與惡魔的鬥爭

javascript API中差的設計會為使用你API的開發者和你帶來高的花費。差的設計會導致浪費,使用你API的開發者會因為設法搞清楚你介面而浪費時間,而API的開發者會因為處理不斷增加的需求和解決使用者的困惑而浪費時間。然而幾乎所有的API當初被開發的時候,都是為了能夠提取相同的功能,方便呼叫並節省時間。但設計不好的API會使你的函式庫使用者和你產生疑惑,這些函式庫真的能節省時間嗎?

優秀的API設計,一方面,完成了提取的目標,同時也實現了自我描述。當一個API被良好的設計,使用者可以快速地和直觀地完成工作,完全不用不停的使用文件或持續的訪問支援或解答網站。你也可以透過封裝一些開發者需要自己花大量時間開發的一些特徵來節約庫開發者的時間。好的設計不僅節省開發者的時間,可以讓他們看起來更聰明、更有責任感。同樣幫助你的用戶看起來聰明和能幹也會使你看起來更加的牛逼!

對javascript來說,API設計特別重要

不管什麼程式語言或框架,API設計是重要的,API設計的重要性對於javascript來說是高於其它許多語言的。首先,作為一個動態的、後期綁定的語言,javascript沒有編譯器可以實作一個安全網或是偵測單元功能,所以javascript不可以發現你程式碼中的錯誤。 Linting 或檢定框架 如 JSLint JSHint 可以幫助我們。這些框架的功能可以指出javascript中的一些普遍的錯誤,但是當我們使用API​​時,他們不能發現javascript的錯誤。

這一切都取決於你,你可以開發一個具有良好設計的API,這個API可以幫助你的用戶掉進眾所周知的“成功坑”,這意味著你的庫對於開發者來說是舒服的和熟悉的,同時也提供了積極的強化和當開發者和你的程式碼互動時建立的信心。


「掉進成功的坑洞」最好的例子是jQuery 透過CSS選擇器語法取得DOM元素的運用。例如,如果我想要取得所有帶有類別名稱的article元素,我可以運用jQuery這樣做:
 

$("article.blogPost").fadeIn();

選擇器article.blogPost和下面展現使用完全一樣的語法,這絕不是偶然的!
 

article.blogPost {
 border-radius: 10px;
 background-color: salmon;
 box-shadow: 0px 0px 10px 2px #ccc;
}

jQuery的选择器引擎被设计为了使我和其他开发者能够使我对CSS选择器的理解和它的引擎进行交互。结果可想而知,如果jQuery需要我用一种新的,为特定目的形成的语法,我将失去快速,明显和高效。

我们可以获得灵感从这些框架中,如jQuery,或者其他框架,并应用这些灵感到我们的设计中。然而,获得灵感并不是抄袭,有个度的问题,任何设计过API的人如果是仅仅的基于别人的想法,不管好与坏,他都将继承。如果我们将在好的javascript中获得的准则运用到其他领域中,我们能开发拥有好的API的框架,这些API设计能被运用在任何情况下。

出色的Javascript APIs设计秘诀

虽然软件不具有与绘画或建筑类似的视觉评价标准,我们仍倾向于使用与物理实体一样的形容词来描述软件质量。例如,使用“优雅的”与“漂亮的”来赞美软件并不罕见。如果用与物理实体相似的形容词描述软件接口是合理的话,那么当然也可以使用与之相同的原则来评价软件设计。

在本节,将四个来自艺术领域的流行设计原则扩展至API设计中:

  1.     和谐一致
  2.     平衡
  3.     对称
  4.     重点突出

对每一个原则,将列出一到多个实例来说明,这些例子表明流行的Javascript库API设计是怎样遵循这些原则的。

原则1:一致性&协调性

在艺术作品中,一致性是一个作品背后不可缺少的观念,或者说设计者如何把一些事物组成连贯的一个整体。协调性,从另一方面来说,是一个作品相似元素的布局,这会在考虑整体时产生一种简洁的感觉。

对于API的设计者,这些原则可以通过在类库使用类似的和(或者)统一的元素来实现。就拿Kendo UI来说吧,一个创建富web应用程序的javascript框架。Kendo UI提供了一系列的UI控件和工具,这些都可以通过一个简单的语法初始化。比如,如果我想从一个无序列表创建一个树形控件(TreeView),我只需调用以下方法:
 

$("ul.tree").kendoTreeView({ /* Configuration goes here */ });

2015624141513720.png (634×294)

Kendo UI树形组件

如果我想通过一个列表创建一个面板PanelBar,我只需稍微改成不同的调用方法.
 

$("ul.panel").kendoPanelBar({ /* Configuration goes here */ });

2015624141539614.png (634×402)

Kendo UI 面板组件

Kendo UI 对所有组件使用一致的kendoX语法,促进整体的协调。更重要的,这样的设计依赖jQuery对象为DOM元素封装了统一的一层,使设计有利于所有熟悉jQuery开发者。数百万开发者使用类似的“土语”(jQuery语法),Kendo UI可以顺利地跨库使用。

另一个协调的案例是Backbone的[object].extend语法创建对象,继承和扩展Backbone的Models,Views,Collections和Routers的功能。用如下代码就可以创建一个Backbone Model,带有Backbone的完整支持,也可以自定义我需要的功能:
 

var Book = Backbone.Model.extend({
 initialize: function() { ... },
 author: function() { ... },
 pubDate: function() { ... },
});

统一和协调的目的是让API新手感觉熟悉和舒服。通过虽然功能不同,但是语法相同或相似,使API变得熟悉,大大减轻了开发者使用新工具的负担。

原则 2 :平衡

下一条原则是平衡,组织元素时不会让某个部分过于重量级而盖过其它部分,使用时不稳定。艺术作品里,平衡就是视觉权重。即使不对称,作品中仍能感觉到不对称下的平衡,因为它遵循某种模式。上下文中的API设计的平衡,我特指代码的视觉权重和可预测性(看得出功能)。

平衡的API让人觉得其组成部分属于彼此,他们行为相同,或互补地完成一个目标。通过扩展,APIs也可以感觉平衡,它们允许开发人员简单的预测其他API并使用。如Modernizr的属性测试,它们的平衡性在两个方面,a)属性名对应HTML5和CSS术语和API名称,b)每个属性测试统一地返回true或false值。
 

// All of these properties will be 'true' or 'false' for a given browser
 Modernizr.geolocation
 Modernizr.localstorage
 Modernizr.webworkers
 Modernizr.canvas
 Modernizr.borderradius
 Modernizr.boxshadow
 Modernizr.flexbox

 

2015624141604498.png (634×267)

 访问一个单一的属性来告诉开发者需要了解到的相关属性,以便通过它访问每一个其他属性,一个高质量API的强大之处就在于它的简单。平衡性也保证了我写和Modernizr交互的代码在每次读写时具有相同的视觉加权。如何在我使用和访问API时看起来和感觉上一样,而不顾我的惯例。另一方面,如果Modernizr添加了一个polyfill Canvas的API,不仅仅是类库的视觉加权受到新API的影响,Modernizr的范围和用途也将大大扩大,并且我在和API交互时可预测性也受到了限制。

达到平衡的另一种方式是通过依靠开发人员对概念的熟悉获得可预测性的结果。一个典型的例子就是jQuery's selector syntax(jquery选择器的语法),它映射css1-3的选择器到自己的DOM选择器引擎:
 

$("#grid") // Selects by ID
$("ul.nav > li") // All LIs for the UL with class "nav"
$("ul li:nth-child(2)") // Second item in each list

通过使用一个熟悉的概念并且映射到自己的类库,jquery避免了新的选择器语法,同事也创建了一个机制让新用户通过一个可预测的API快速的把类库应用到生产.。

原则 3: 相称性

接下来的原则是相称性,它是用来衡量一个作品中元素的大小和数量的。与其说一个好的API是一个小的api,相称性是相对于用途的大小。一个相称的API它的API表面和它的能力范围相匹配。

例如,Moment.js,一个流行的日期转换和格式化类库,可以把它视为具有相称性,因为它的API表层是紧凑的,它和类库的目的明确的匹配。Moment.js用于处理日期,它的API提供了便利的功能用来处理javascript Date对象:
 

moment().format('dddd');
moment().startOf('hour').fromNow();

2015624141630224.png (634×270)

 对于一个有针对性的类库,像Moment.js,保持API的专注和简单是非常重要的。对于更大和更广阔的类库,API的大小应当能够反映出类库自身的能力。


Underscore来说,作为一个多种用途功效的库,它提供大量便利的函数,这些被设计的函数是用来帮助开发者处理javascript集合,数组,函数和对象。它的API量远远超过像Moment.js这样的库,但是Underscore也是成比例的,因为库中每个函数都有自己的功效目的。考虑下面的例子,前两个例子用Underscore来处理数组,最后一个来处理字符串。
 

_.each(["Todd", "Burke", "Derick"], function(name){
 alert(name);
});
 
_.map([1, 2, 3], function(num){
 return num * 3;
});
 
_.isNumber("ten"); // False

2015624141653770.png (634×272)

 当一个库逐渐成长的过程中,维持比例的挑战变的更加具有严峻。为了确保添加进库的每个功能和函数都能加强库的目的,需要更多的考虑投入。对于一个大的库像kendo UI,易扩展性的目的并不是意味着我们需要往库中添加每个特性。对于一个像kendo一样大的库,功能对象和特性应该证明它们的价值才能被库包含。例如, Kendo UI's JavaScript 基于DataSource, 它能够被用来查询和处理远程数据。
 

var dataSource = new kendo.data.DataSource({
 transport: {
  read: {
   url: "http://search.twitter.com/search.json",
    dataType: "jsonp",
    data: { q: "API Design" }
   }
  },
 schema: { data: "results" }
});

初看第一眼,它好像一个习以为常的数据源,感觉超出了库本身的基本目的。然而今天网站的装饰都需要动态数据的支持。数据源的引入允许Kendo UI可以使用一个稳定,并舒适的范式在整个库范围内来解决远程数据。
 

让一个API转变为一个名符其实的javascript垃圾抽屉,对于一个库的扩展这是危险的,但对于库来说,这也不是唯一的危险。掉入一个不让你的API伴随着库的成长圈套,或者由于某些人为原因,限制你库的大小,这些同样都是危险的!

不处理API增长最好的一个例子是jQuery的 jQuery or $ function。和我一样有成千上万的开发者喜欢jQurey, 但它的门户方法是有点乱的,从DOM选择到在jQuery对象中包含DOM元素,这个方法提供了超过11个独立超负荷选择方式。

就大部分而言,有些不是十分相关的特性被硬塞进同一个API。从全局看,jQuery是一个大的库并且能被认为库比例是合理的。另一方面,当我们尝试将一个功能硬塞进一个单一接口并且不考虑库比例,jQuery方法也可以实现这样的功能。

如果你发现你正在将一个不相干的特性强塞进已经存在的方法,或者正在想法设法使一个并不适合API的函数的添加合理化,你需要做的改变是松开皮带并且让库呼吸。你的用户在调用一个新的可以自我描述名字的函数时,将会更加节省时间,并且不会给另一个已经存在的方法添加负担。

原则 4: 强调性

在艺术作品中,强调是利用对比来使作品中某一方面脱颖而出形成一个焦点。在许多API中,焦点可能是一个通道或者类库主要方法的锚点。另外一个关于强调性的例子可以参考“链接”方式或者fluent API,它通过增加强调性效果突出了类库中心对象。jquery倾向于从许多功能演示中的强调这个对象:

$('ul.first').find('.overdue')
 .css('background-color','red')
 .end()
 .find('.due-soon')
 .css('background-color', 'yellow');

对于许多现代的类库,另一个关于强调的例子是可扩展性:类库创建者没有提供的那部分,会为你提供一个工具你可以自己完成相关扩展。

一个典型的例子可以参考jQuery'sfn(pronounced “effin”) namespace, 一般的扩展点可以通过数不清的插件和补充的类库来完成:

(function($) {
 $.fn.kittehfy = function() {
  return this.each(function(idx, el) {    
   var width = el.width,
    height = el.height;
   var src= "http://placekitten.com/";
   el.src= src + width + "/" + height;
  });
 };
})(jQuery);

另一个扩展性的例子是Backbone的“extend”的函数,我们已经在本文中看到过:

var DocumentRow = Backbone.View.extend({
 tagName: "li",
 className: "row",
 events: {
  "click .icon": "open",
  "click .button.edit": "openEditDialog"
 },
 render: function() { ... }
});

2015624141715183.png (634×258)

 可擴充作為強調性的一方面是因為它讓我們意識到這樣的一個事實,已有的類別庫並不意味著一切是完美的,同時也鼓勵我們擴展適合自己的類別庫。當類別庫支援擴充時,它們不僅開啟了新的用途,也使無數開發者受益於一般的用途。一個最好的例子是Backbone.Marionette框架,一個擴展於Backbone的類別庫,它的目標是「簡化大型的javascript應用程式的結構」。如果不是像Backbone那樣的類別庫擴展,Marionette之類的類別庫就會變得非常複雜,甚至不可能實作。

API 設計:不只為函式庫程式碼編寫者

如果你不是一位 JavaScript 函式庫的編寫者,而是一位 JavaScript 應用程式開發者或函式庫的實作者,你可能會認為本文中的原則並不適用於你。畢竟,我們大多數人在聽到「API」的時候,往往想到的是第三方函式庫,一如我在本文中的範例

事實是,API ,如同其定義所言,無非就是一個提供給他人利用的隔離功能的介面。 現在,讓我用一句老話來強調很重要的一點:寫一個模組化的 JS 程式碼是為了實用,使用的次數並不重要。


正如本文所引用的類別庫,你可以把自己的javascript程式碼公開介面給其他人。即使你的程式碼的使用者是一小部分或內部團隊——甚至你建立自己的一個私有類別庫——你不必像一個公開類別庫的作者那樣考慮本文中API設計原則和這些原則的實作。利用API設計的好處是即使只針對一個使用者,也要像對數百萬用戶一樣設計。

因為API的設計代表著對開發者的使用者體驗,它就像UI設計對最終使用者的重要性。就像我們可以透過學習一些原則和參考一些好的或壞的例子來發展出優秀的UI一樣,我們也可以透過同樣的方式學習到更好的API設計。應用文中提到的四個原則,以及其他你自己發現的原則,可以幫助你建立出優秀的API,並且讓使用者得到良好的體驗。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn