久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx

[成都網站制作]API設計新思維:用流暢接口構造內部DSL

2023-01-02    分類: 網站建設

API設計新思維:用流暢接口構造內部DSL

程序設計語言的抽象機制包含了兩個最基本的方面:一是語言關注的基本元素/語義;另一個是從基本元素/語義到復合元素/語義的構造規則。在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(inti=0;i<5;++i){ system.out.println(i); }

而Ruby雖然也支持類似的for循環,但最簡單的是下面這樣的實現: //Ruby

.times{|i|putsi}

Ruby中一切皆對象,5是Fixnum類的實例,times是Fixnum的一個方法,它接受一個block參數。相比for循環實現,Ruby 的times方式更簡潔,可讀性更強,但熟悉OOP的朋友可能會有疑問,times是否應該作為整型類的方法呢?在OOP中,方法調用通常代表了向對象發送消息,改變或查詢對象的狀態,times方法顯然不是對整型對象狀態的查詢和修改。如果你是Ruby的設計者,你會把times方法放入Fixnum類嗎?如果答案是否定的,那么Ruby的這種設計本質上代表了什么呢?實際上,這里的times雖然只是一個普通的類方法,但它的目的卻與普通意義上的類方法不同,它的語義實際上類似于for循環這樣的語言基本語義,可以被視為一種自定義的基本語義。times的語義從一定程度上跳出了類方法的框框,向問題域邁進了一步!

另一個例子來自Eric Evans的“用兩個時間點構造一個時間段對象”,普通設計: 3//Java TimePointfiveOClock,sixOClock; TimeIntervalmeetingTime=newTimeInterval(fiveOClock,sixOClock);

另一種Evans的設計是這樣: 2//Java TimeIntervalmeetingTime=fiveOClock

.until(sixOClock);

按傳統OO設計,until方法本不應出現在TimePoint類中,這里TimePoint類的until方法同樣代表了一種自定義的基本語義,使得表達時間域的問題更加自然。

雖然上面的兩個簡單例子和普通設計相比看不出太大的優勢,但它卻為我們理解流暢接口打下了基礎。重要的是應該體會到它們從一定程度上跳出了語言基本抽象機制的束縛,我們不應該再用類職責劃分、迪米特法則(Law of Demeter)等OO設計原則來看待它們。

2.管道抽象

在Shell中,我們可以通過管道將一系列的小命令組合在一起實現復雜的功能。管道中流動的是單一類型的文本流,計算過程就是從輸入流到輸出流的變換過程,每個命令是對文本流的一次變換作用,通過管道將作用疊加起來。在Shell中,很多時候我們只需要一句話就能完成log統計這樣的中小規模問題。和其他抽象機制相比,管道的優美在于無嵌套。比如下面這段C程序,由于嵌套層次較深,不容易一下子理解清楚: 2//C

min(max(min(max(a,b),c),d),e)

而用管道來表達同樣的功能則清晰得多: 2#!/bin/bash maxab|minc|maxd|mine

我們很容易理解這段程序表達的意思是:先求a,b的大值;再把結果和c取最小值;再把結果和d求大值;再把結果和e求最小值。

jQuery的鏈式調用設計也具有管道的風格,方法鏈上流動的是同一類型的jQuery對象,每一步方法調用是對對象的一次作用,整個方法鏈將各個方法的作用疊加起來。 2//Javascript $('li').filter(':event').css('background-color','red');

3.層次結構抽象

除了管道這種“線性”結構外,流暢接口還可用于構造層次結構抽象。比如,用Javascript動態創建創建下面的HTML片段:<divid="’product_123’"class="’product’"><imgsrc="’preview_123.jpg’"alt=""/><ul><li>Name:iPad232G</li><li>Price:3600</li></ul></div>

若采用Javascript的DOM API: //Javascript vardiv=document.createElement('div'); div.setAttribute(‘id’,‘product_123’); div.setAttribute(‘class’,‘product’); varimg=document.createElement('img'); img.setAttribute(‘src’,‘preview_123.jpg’); div.appendChild(img); varul=document.createElement('ul'); varli1=document.createElement('li'); vartxt1=document.createTextNode("Name:iPad232G"); li1.appendChild(txt1); … div.appendChild(ul);

而下面流暢接口API則要有表現力得多: //Javascript varobj= $.div({id:’product_123’,class:’product’}) .img({src:’preview_123.jpg’}) .ul() .li().text(‘Name:iPad232G’)._li() .li().text(‘Price:3600’)._li() ._ul()

._div();

和Javascript的標準DOM API相比,上面的API設計不再局限于孤立地看待某一個方法,而是考慮了它們在解決問題時的組合使用,所以代碼的表現形式特別貼近問題的本質。這樣的代碼是自解釋的(self-explanatory)在可讀性方面要明顯勝于DOM API,這相當于定義了一種類似于HTML的內部DSL,它擁有自己的語義和語法。需要特別注意的是,上面的層次結構抽象和管道抽象有著本質的不同,管道抽象的方法鏈上通常是同一對象的連續傳遞,而層次抽象中方法鏈上的對象卻在隨著層次的變化而變化。此為,我們可以把業務規則也表達在流暢接口中,比如上面的例子中,body()不能包含在div()返回的對象中,div().body()將拋出”body方法不存在”異常。(高端網站建設)

4.異步抽象

流暢接口不僅可以構造復雜的層次抽象,還可以用于構造異步抽象。在基于回調機制的異步模式中,多個異步調用的同步和嵌套問題是使用異步的難點所在。有時一個稍復雜的調用和同步關系會導致代碼充滿了復雜的同步檢查和層層回調,難以理解和維護。這個問題從本質上講和上面HTML的例子一樣,是由于多數通用語言并未把異步作為基本元素/語義,許多異步實現模式是向語言的妥協。針對這個問題,我用Javascript編寫了一個基于流暢接口的異步DSL,示例代碼如下: //Javascript $.begin() .async(newTask('task1'),'task1') .async(newTask('task2'),'task2') .async(newTask('task3'),'task3') .when() .each_done(function(name,result){ console.log(name+':'+result);}) .all_done(function(){console.log('good,allcompleted');}) .timeout(function(){ console.log('timeout!!'); $.begin() .async(newTask('task4'),'task4') .when() .each_done(function(name,result){ console.log(name+':'+result);}) .end();} ,3000)

.end();

上面的代碼只是一句Javascript調用,但從另一個角度看它卻像一段描述異步調用的DSL程序。它通過流暢接口定義了begin when end的語法結構,begin后面跟的是啟動異步調用的代碼;when后面是異步結果處理,可以選擇each_done, all_done, timeout中的一種或多種。而begin when end結構本身是可以嵌套的,比如上面的代碼在timeout處理分支中就包含了另一個begin when end結構。通過這個DSL,我們可以比基于回調的方式更好地表達異步調用的同步和嵌套關系。

上面介紹了用流暢接口構造的4種典型抽象,出此之外還有很多其他的抽象和應用場合,比如:不少單元測試框架就通過流暢接口定義了單元測試的DSL。雖然上面的例子以Javascript等動態語言居多,但其實流暢接口所依賴的語法基礎并不苛刻,即使在Java這樣的靜態語言中,同樣可以輕松地使用。流暢接口不同于傳統的API設計,理解和使用流暢接口關鍵是要突破語言抽象機制帶來的定勢思維,根據問題域選取適當的抽象維度,利用語言的基本語法構造領域特定的語義和語法。

新聞標題:[成都網站制作]API設計新思維:用流暢接口構造內部DSL
路徑分享:http://www.js-pz168.com/news9/227509.html

成都網站建設公司_創新互聯,為您提供用戶體驗建站公司網站維護做網站標簽優化品牌網站建設

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

搜索引擎優化
久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx
欧美日韩亚洲综合在线 | 国产亚洲精品超碰| 国产精品久久久久国产精品日日| 日韩欧美一二三区| 国产精品九色蝌蚪自拍| 日韩中文字幕区一区有砖一区 | 国产在线观看一区| 一区二区精品视频| 精品国产不卡一区二区三区| 亚洲欧美日本在线| 国产麻豆精品视频| 精品国产_亚洲人成在线| 在线观看亚洲专区| 国产日韩欧美不卡在线| 色婷婷激情一区二区三区| 精品粉嫩超白一线天av| 亚洲一二三区视频在线观看| 成人午夜av电影| 欧美综合激情| 欧美大片免费久久精品三p| 一区二区三区四区不卡在线| 国产盗摄女厕一区二区三区| 欧美精品人人做人人爱视频| 91精品国产aⅴ一区二区| 91久久香蕉国产日韩欧美9色| 亚洲va欧美va人人爽午夜| 成人黄色电影在线| 秋霞久久久久久一区二区| 欧美精品精品一区| 国产精品视频一二三| 六月丁香综合在线视频| 国产视频一区二区三区四区| 欧美日韩国产区一| 亚洲人一二三区| 粉嫩一区二区三区在线看| 亚洲欧洲在线一区| 国产性色一区二区| 激情亚洲综合在线| 奇米视频888战线精品播放| 日韩视频在线观看一区二区| 亚洲v中文字幕| 俄罗斯精品一区二区三区| 欧美三区在线视频| 伊人开心综合网| 91香蕉视频污在线| 欧美在线播放高清精品| 亚洲猫色日本管| 97aⅴ精品视频一二三区| 在线观看视频一区| 亚洲精品成人少妇| 91麻豆免费在线观看| 欧美日韩国产高清一区二区| 一区二区久久久久久| 91免费在线看| 7777精品伊人久久久大香线蕉完整版 | 久久精品一区二区| 精品一区二区三区影院在线午夜| 国产精品久久影院| 五月开心婷婷久久| 99热在线播放| 欧美色窝79yyyycom| 日本一区二区电影| 丝袜美腿亚洲一区二区图片| 暴力调教一区二区三区| 日韩激情在线观看| 免费一级欧美片在线观看| 91在线视频播放地址| 中文字幕成人一区| 欧美极品aⅴ影院| 蜜桃视频在线观看一区二区| 999日本视频| 色婷婷久久久综合中文字幕 | 一本色道久久99精品综合| 欧美另类高清zo欧美| 亚洲欧美日韩国产一区二区三区| 亚洲人成网站影音先锋播放| 国产在线麻豆精品观看| 欧美日韩在线精品一区二区三区| 国产一区二区视频在线免费观看 | 在线视频精品一区| 国产人成亚洲第一网站在线播放| 国产午夜精品一区二区| 天天色图综合网| 久久综合毛片| 欧美国产禁国产网站cc| 成人ar影院免费观看视频| 制服丝袜亚洲色图| 日韩黄色免费电影| 欧美aaaaa成人免费观看视频| 大胆欧美人体老妇| 欧美日韩在线三区| 日韩精品久久理论片| 青娱乐一区二区| 亚洲美女一区二区三区| 精品一区久久| 国产精品久久久久久久浪潮网站| 精品制服美女久久| 在线视频一区二区三区| 日韩av在线免费观看不卡| 亚洲va中文字幕| 欧美日韩一区二区三区在线观看免 | 日韩欧美高清dvd碟片| 国产伦精品一区二区三区免费迷| 欧美一区二区三区在线播放 | 精品一区免费av| 在线精品亚洲一区二区不卡| 亚洲成人免费观看| 亚洲人成网站在线观看播放| 亚洲午夜精品久久久久久久久| 91亚色免费| 亚洲国产高清在线观看视频| 国产精品乱码| 综合欧美一区二区三区| 美日韩免费视频| 一区二区激情视频| 午夜精品一区二区三区四区| 亚洲www啪成人一区二区麻豆| 成人高清在线观看| 国产日韩v精品一区二区| 婷婷亚洲婷婷综合色香五月| 国产视频一区二区三区在线观看| 日韩激情视频网站| 欧美视频在线观看一区二区| 国产精品影视网| 国产欧美一区二区精品仙草咪| 蜜臀av一区二区在线观看| 在线不卡一区二区| 97久久超碰国产精品| 国产精品美女www爽爽爽| 亚洲精品国产一区| 综合久久久久久| 日产国产精品精品a∨| 亚洲成av人片一区二区| 在线精品国精品国产尤物884a| 日韩理论片网站| 日本精品二区| 日韩精品免费专区| 欧美视频完全免费看| 国产成人精品亚洲午夜麻豆| 久久无码av三级| 国产一区二区在线网站 | 久久精品久久综合| 欧美日本在线视频| www.日韩精品| 国产精品久久午夜| 日韩视频专区| 4438x亚洲最大成人网| 成人三级在线视频| 国产精品嫩草99a| 欧美一区免费视频| 美国精品在线观看| 欧美老女人在线| 欧美一区2区三区4区公司二百| 欧美性色欧美a在线播放| 日韩欧美国产综合在线一区二区三区| 久久91精品国产91久久小草| 久久亚洲欧美国产精品乐播| 亚洲一区二区三区涩| 99视频免费观看蜜桃视频| 久久精品999| 亚洲精品国产无套在线观| 9i在线看片成人免费| 人人狠狠综合久久亚洲| 国产精品视频在线看| 日韩一级二级三级精品视频| 91毛片在线观看| 日本伊人午夜精品| 亚洲自拍的二区三区| 国产精品一卡二| 国产精品人人做人人爽人人添| 99r国产精品| 一区二区三区精品在线| 精品视频123区在线观看| 91免费观看| 天使萌一区二区三区免费观看| 亚洲一区二区三区乱码| 丁香婷婷深情五月亚洲| 亚洲人成7777| 欧美男女性生活在线直播观看| 精品一区免费av| 国产精品视频一区二区三区不卡| 国产精品一级久久久| 五月婷婷激情综合| 欧美不卡在线视频| 日产精品久久久一区二区| 国产宾馆实践打屁股91| 亚洲另类色综合网站| 91精品婷婷国产综合久久| 麻豆av一区二区三区| 国产精品18久久久久久久网站| 亚洲精品一区二区三区在线观看| 91美女福利视频| 日日摸夜夜添夜夜添精品视频| 在线观看免费一区| 成人羞羞视频免费| 麻豆91免费看| 自拍av一区二区三区| 欧美精品tushy高清| 欧美精品人人做人人爱视频| 国产成人亚洲综合a∨猫咪|