国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Web框架的常用架構模式(JavaScript語言)

loostudy / 394人閱讀

摘要:只能在不同的時候選用不同的假設和不同的理論來解釋問題,許來西的文章講到科學一定程度上通過放棄一貫性換取了實用性,放棄自洽性換取了它洽性。然而遺憾的是本身只提供了模塊和洋蔥模型的最小封裝。

在寫干貨之前,我想先探(qiang)討(diao)兩個問題,模式的局限性?模式有什么用?

最近看到一篇文章對我啟發很大,許來西在知乎的回答《哲學和科學有什么關聯?》,全篇較長,這里摘錄我要引出的一點:

科學作為一種經驗主義的認識論,有著經驗主義的巨大缺陷:它永遠不能產生絕對正確的真理。這是歸納法的本質決定的。而且值得注意的是,歸納不具有唯一性。

舉一個簡單的例子,我們假設一個世界,如下圖:

科學家很快有了兩種歸納方式:

世界上所有的青蛙都戴眼鏡

世界上所有戴眼鏡的都是青蛙

在沒有更多的信息的時候,我們應該如何選擇正確的理論呢?答案是無法選擇。

舉個模式的例子,Scott Wlaschin 在《Functional Programming Design Patterns》(函數型編程模式)中對比了常用面向對象模式、原則,在函數型編程語言里面等價實現:

OOP 和 FP,到底哪種編程范式更加先進呢?答案同樣是無法選擇。只能在不同的時候選用不同的假設和不同的理論來解釋問題,許來西的文章講到科學一定程度上通過放棄一貫性換取了實用性,放棄自洽性換取了它洽性。科學追求實用和工具(實用主義和工具主義)。當我看完許來西的文章,欣喜若狂,一直對編程技術理論的善變和不自洽感到恐懼和厭惡,其實只是經驗主義科學發展的必然過程,善變代表更好的理論(更方便)在替換基礎理論,代表蓬勃發展。

所以我想引入第一個觀點:

模式是一套立足于特定背景,基于共性總結出的方案,它絕不是真理。

了解這些有助于幫助從對模式的盲目崇拜到探究它的實用性和工具性,也就是我要引出的第二個問題:模式有什么用?

不好好寫代碼看哲學文章不是偶然,在文章落筆之前,我有思考過在 JavaScript 這門動態,多范式,單線程,基于事件I/O的語言環境下,甚至在當前時代,模式是否還有意義?顯然我不是唯一這樣想的,還有篇深度好文《20年前GoF提出的設計模式,對這個時代是否還有指導意義?》。這篇文章引經據典,摘錄了GoF(又稱Gang of Four,即Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides)在設計模式一書中觀點:

這本書的實際價值也許還值得商榷。畢竟它并沒有提出任何前所未有的算法或者編程技術。它也沒能給出任何嚴格的系統設計方法或者新的設計開發理論——它只是對現有設計成果的一種審視。大家當然可以將其視為一套不錯的教程,但它顯然無法為經驗豐富的面向對象設計人員帶來多少幫助。

換言之,模式顯然毫無實際用處。

不僅如此,文章還列舉了一度模式濫用導致許多弊端,可謂警鐘長鳴。

但是……模式這一稱謂仍然不斷出現,直到今天我們亦在大量使用。為什么?GoF實際早設計模式的書中做出了預言:

“設計模式為設計師們提供一種共通的詞匯儲備,幫助其溝通、編寫文檔并探索設計方案。設計模式允許我們立足于高級抽象層面進行探討,而非設計標注或者編程語言,這就大大降低了系統復雜性。設計模式提升了我們設計及與同事進行設計探討時的切入點層級?!保ǖ?89頁)

簡言之,模式方便了我們的溝通,提升了思考問題的抽象層級。

這個意義非常巨大,想象一下沒有 MVC 架構模式,可能所有的 Web 框架必然的會實現一套幾乎解決同樣問題的方案,但是命名和文檔卻各不一樣,當你去看一個新的框架文檔的api 接口,從頭到尾看完以后才恍然大悟,這不就是之前用的框架里面的 XXX 類似嗎,這樣的編程世界簡直地獄。慶幸的是,得益于計算機科學家(碼農)對問題和方案持續的抽象成模式,使得當前高度復雜的計算機科學也能得到合理分層和適配,大大簡化了學習和溝通的成本。

為了感謝模式,是時候學習一波了,本文要介紹的主要有三種架構模式:Middleware,MVC,DI。

Middleware 中間件模式

相信做過 Node.js 服務端開發的同學對這個模式一定不陌生,考慮如下 Web 應用的場景:

在一個簡單的 HTTP 請求響應周期里,有如下條件處理,

記錄開始時間

需要驗證用戶的身份 authentication。

解析cookie 并加載body

根據路由返回不同的業務處理結果

沒有命中路由則返回404頁面

記錄日志

記錄總共花費時間

處理異常并顯示頁面(開發環境)

有些處理會根據是否成功決定是否繼續后面的粗粒,有些處理會生成額外的數據,還有的要求攔截某些處理的開始和結束,最后異常處理和記錄日志要求一定被執行。

一般的解決方法是用嵌套條件判斷結合 try catch finally return 等控制語句,但是這樣的方案會導致代碼碎片化和復制粘貼的編碼風格,因為控制流和邏輯耦合到了一起。理想的方案應當如下:

中心化控制流

解耦處理模塊(重用性)

聲明式、可配置的服務(配置和代碼無關)

這些場景由來已久,很久以前J2EE總結了 Intercepting Filter 模式,有興趣大家可以看看這篇文(lun)章(wen),里面由淺入深提到三種方案,其中最初級的方案代碼如下:

public class DebuggingFilter implements Processor {
  private Processor target;
  public DebuggingFilter(Processor myTarget) {
    target = myTarget;
  }
  public void execute(ServletRequest req, 
  ServletResponse res) throws IOException, 
    ServletException    {
    // preprocess
    target.execute(req, res);
    // post-process
  }
}

這個和 express 和 Koa 的中間件模式極其相似,但是因為靜態語言本身一些特征,導致最后形成的企業級代碼極其繁瑣,并且有許多局限性。最主要的問題是處理模塊之間難以重用和共享數據,因為 ServletRequest ServletResponse 無法動態添加屬性。以至于 JavaEE 把這個模式的適用性加了許多限制,包括和核心處理邏輯分開。

在動態語言的世界里面,我們可以很方便的往 reqres 里面添加數據(基于約定),因為沒有了很多 OOP 世界里面的”束縛“,Node.js 的實現通常更加優雅和通用。

Express 中間件模式

express 實現如今廣泛接受的 Middleware 中間件模式。中間件的意思是在 請求響應 中間執行的函數(為了區分另一個中間件),簽名如下:

var express = require("express");
var app = express();

這個模式包含了一套聲明式的路由規則,和 middleware 函數上的 next 簽名,它們共同構成了整個中間件模式的控制流,如圖:

這個模式的核心構成不是權限解析等中間件邏輯,而是路由判斷,next中斷響應(驗證失敗、解析失敗),其作為中間件執行控制,解耦了具體的處理邏輯,使得更容易寫出通用的細粒度的中間件。express 內置的強大的聲明式路由,并且路由和 middleware 分離可以說是它最成功的設計之一。

然而在一些稍微復雜點的業務中,比如一個網站有管理端和用戶端,兩個端相當于獨立的app。express 4.0 提供了一個非常強大的功能 Router。Router 拓展了鏈式決策變成樹形決策,可以讓 express 更好的支持大型項目。

/*  
   文件  bird.js
*/
var express = require("express")
var router = express.Router()
  
router.get("/", function (req, res) {
  res.send("Birds home page")
}) 

module.exports = router

/*  
   文件  app.js
*/

var birds = require("./birds")

// ...

app.use("/birds", birds)

Koa 異步中間件模型

Koa 的異步中間件模式-洋蔥模型,相比 Express,其中間件函數返回 Promise,支持 async/await,并且可以輕松實現前置和后置的處理。毫無疑問這個模式更加先進,一些在 express 里面不好實現的攔截處理邏輯,比如異常處理和統計時間,在 Koa 里用一個中間件就能搞定。然而遺憾的是 Koa 本身只提供了 Http 模塊和洋蔥模型的最小封裝。

未來我看好 Koa,其實 express 也意識到這點,他們計劃在 5.0 版本里添加 Promise 的支持,然而作為一個老牌和完整生態的框架,要克服的困難遠不是技術層面上看似的簡單,直到目前仍然沒有看到 5.x 宣布支持 Promise, 讓我們拭目以待。

MVC 模式

MVC 模式也需要介紹嗎,我們天天都在聊 MVC,不管前、后端框架,說一句 MVC,對一下眼神,基本確定對方懂你了。

事實是,前端框架已經不適合用 MVC 討論,這個模式從1979年提出以來,作為萬精油模式,在各個框架和場景中被套用,背負了太多的歷史包袱,大家可以看 winter 的文章 談談UI架構設計的演化。撥亂反正我覺得有希望,討論前端框架大家以后統稱 MV 模式就好了,就是模型和視圖分離。

我們今天要講的 MVC 模式是指在服務器上(后端) MVC 模式,它的定義經受了時間和實踐的檢驗,在許多企業級 Web 框架的實現中高度一致。先列舉場景:

如果你的網站只有幾個簡單的頁面,所有邏輯都寫在 Controller 里面,是沒有問題的。隨后網站迅速的增長,你發現,

許多頁面里面的視圖是一致的,但是背后的數據模型不一致。比如:網站上幾乎沒有一個視圖或者組件是獨一無二的,表格,下拉框等。

許多頁面里面的數據模型是一樣的,但是展現的視圖不一致。比如:同時支持PC和移動端,國際化本地化。

我們做一個數學模型模擬極端情況,大家很容易能看到問題

假設左邊是我們的系統最終的樣子,它剛好可以表示成 M(模型)和 V(視圖)的內積,我們更傾向于右邊的表達,因為它更簡潔而且沒有重復。這里的內積操作大家就可以理解成控制器,實際上不會如此巧合,但是分離模型和視圖幫助我們提高代碼復用,降低設計復雜度的好處是很顯然的,一個更通用的表達

模型視圖和控制器之間都是單向鏈接,所以整個系統的行為非常可控且容易測試,多帶帶把路由分開是想強調 Router 和 Controller 是兩個概念,Router 只是一個觸發器(或者提供了一種映射關系),在寫測試的時候,我們也可以跳開 Router 多帶帶調用 Controller。

看到上面的兩種模式,是不是已經開始想,那有沒有一個框架同時是 Koa + Router + MVC 呢,推薦大家一個非常好用的企業級 Web 框架 ThinkJS 3.0,最新版的 ThinkJS 集成了大量最佳實踐和完善的文檔,不管是學習或者企業級開發都非常推薦。而且 ThinkJS 同樣實現了接下來要講的模式。

DI 依賴注入模式

還是先說場景,假如服務端需要實現session,前期考慮到成本和用戶量,單臺服務器存到文件就夠用了。后期如果用戶量大的時候,需要橫向擴展(Scale-out),就把 session 實現基于中心化的 Redis 服務。

我們系統設計目標是:

不需要修改業務邏輯代碼實現替換

不需要關注服務的創建和生命周期

解決這類系統擴展性問題有一個非常著名的設計原則 控制反轉(IoC Inversion of control),而 依賴注入(DI dependency injection) 就是其中的一個實現模式。

DI 的基本思路是這樣,首先我們的代碼不能依賴具體的服務,需要總結歸納出一套抽象接口,業務實現依賴接口,而服務實現接口,最后通過框架專門負責創建和提供接口的實例。

這里的 IoC 容器或者說 Ioc 框架,會在啟動的時候讀取配置文件,并在運行的時候根據需要創建實例提供給使用者,在靜態語言如 java,c# 需要用到反射等高級語法,而 JavaScript 本身是動態的,接口基于約定,并且使用的方式也更加靈活。比如 ThinkJS 3.0 里面的 extendadapter 就可以理解成接口和實現,如圖:

那之所以稱為 extend,是因為框架會直接把接口注入到 controller 或者 think 對象中。這樣的好處是使用起來更方便,缺點是不同 extend 需要約定好不能重名。

最后

本文介紹的三個架構模式,你會發現幾乎在所有的Web框架實現都大同小異,這就是模式的好處。模式的意義類似于 IoC,我關注抽象和接口,抹平了具體語言特性下的細節問題,幫助我們更好的學習,溝通和思考。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95023.html

相關文章

  • 全棧開發自學路線

    摘要:前言這里筑夢師是一名正在努力學習的開發工程師目前致力于全棧方向的學習希望可以和大家一起交流技術共同進步用簡書記錄下自己的學習歷程個人學習方法分享本文目錄更新說明目錄學習方法學習態度全棧開發學習路線很長知識拓展很長在這里收取很多人的建議以后決 前言 這里筑夢師,是一名正在努力學習的iOS開發工程師,目前致力于全棧方向的學習,希望可以和大家一起交流技術,共同進步,用簡書記錄下自己的學習歷程...

    galaxy_robot 評論0 收藏0
  • 全棧開發自學路線

    摘要:前言這里筑夢師是一名正在努力學習的開發工程師目前致力于全棧方向的學習希望可以和大家一起交流技術共同進步用簡書記錄下自己的學習歷程個人學習方法分享本文目錄更新說明目錄學習方法學習態度全棧開發學習路線很長知識拓展很長在這里收取很多人的建議以后決 前言 這里筑夢師,是一名正在努力學習的iOS開發工程師,目前致力于全棧方向的學習,希望可以和大家一起交流技術,共同進步,用簡書記錄下自己的學習歷程...

    Scorpion 評論0 收藏0
  • JavaScript 就要統治世界了?

    摘要:歡迎使用中文文檔架構概覽是網易項目團隊開發的一個基于進行開發的應用層框架,提供了一個輕量級的容器來編寫簡單可維護的。 JavaScript 可以……嘛,不就是操作一下 DOM,可以讓元素飛來飛去嗎JavaScript 是……不就是用 jQuery 讓網頁動起來,頂多就是再用用 Ajax 和后端進行一下數據交換嗎JavaScript 是一門……最討厭和鄙視這種弱類型不需要編譯的腳本語言...

    AbnerMing 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<