“NodeJS在大搜車” 之 MVC基礎結構

jopen 9年前發布 | 54K 次閱讀 NodeJS Node.js 開發

長長而且無關的前言

經常會有同學來問我前端是否適合向NodeJS方向發展,其實大多數時候我是拒絕的,為什么呢?其實前端接觸一下NodeJS這個東西本身我是不 排斥的,畢竟是基于JS,能夠掌握一門手藝,拓展一下自己的技術視野,然后寫一些讀寫文件,grunt插件之類的工具,也是極好的。我所謂的拒絕,主要是 基于很多同學并非如此考慮,很多同學想借NodeJS輕輕松松的把魔爪伸向純服務端開發,NodeJS本身對于前端來說是極其容易掌握的,照著文檔寫一個 服務器也是極其簡單的,很多同學覺得自己一下子跨進了服務端開發的大門,然而,真是如此么?

現在很多技術方面的營銷文,荼毒!讓新人變得也浮躁起來。

在我看來,如果我面前有一個牛逼的前端和牛逼的PHP工程師,讓我選一個來轉型NodeJS服務端開發,我會毫不猶豫的選擇PHP。這樣我需要做 的就是讓他去看一個周的JS語法,給他花一天講解下callback(對php,java,ruby來說這個的確很難理解),花一點時間熟悉下 nodejs的模塊和寫法。然后下面就很順暢了。

而對于一個前端,好嘍,麻煩嘍,以為服務端開發只是簡單的堆積業務么?服務端邏輯那么緊密,如何hold住?服務端跟其他系統之間的耦合,如何 hold住?整體業務的把握,請求量太大天天掛,IO瓶頸了如何搞定,緩存該怎么用,應用架構如何設計,分層如何設計,數據庫如何優化,代碼如何調試,如 何分析內存泄露,單元測試寫沒寫過,HTTP原理了解多少,Nginx配置服務器部署知道幾何,性能監控跟蹤呢?

扯遠了。

其實我本來只是想說一下服務端開發思維在NodeJS開發方面也是非常重要的,而今天要分享的就是其中重要的一部分:MVC。

在寫NodeJS之前,我寫過一陣Java,基于spring框架,所以思維中對MVC模式也算有個比較簡單的理解,所以在構建NodeJS框架的過程中,多少帶入了一點Spring的思維。

基本要素:

1. Controller,Model,View。

三要素啦,不用質疑,再復述一遍。

Controller ,負責業務邏輯的控制,是中樞,連接數據和視圖之間的關系。不過controller一般不會直接操作數據,這中間需要再加一層,這個后面說。所以一個干 凈的controller里,應該調用各方數據,最后組裝成一個可用的數據,最后把數據傳給視圖。

Model,從概念上來說,Model就是一個數據層,不過在我們的NodeJS項目中,Model是通過一個ORM抽象成對象的,變成了實體定義,這個也是后面具體講。

View,視圖層,一般通過模板引擎把數據渲染成動態的頁面,我們公司統一使用Jade,Jade的結構嚴格清晰,速度也夠快,功能夠豐富,無它。

2. Service

這個名字是從Spring里面學過來的,感覺Service這個詞本身就很能代表這個分層所擔當的角色,那就是服務層。

什么是服務呢?它凌駕于數據層之上,對數據操作進行抽象,通過服務類型抽象成不同的服務,提供給不同的業務調用。例如在我們公司最基礎的幾個服 務:車輛數據服務,用戶數據服務,推送服務,搜索服務。這些服務大部分不是單純的操作某個數據表之類的,而是在頂層的封裝,因為車輛相關的業務可能有很多 數據表,例如車輛基礎信息,車輛審核信息,各種狀態變更記錄等一系列數據表,而且會橫跨在mysql,mongodb,以及redis緩存之間的各種邏 輯。我們把種種數據操作通過service層完全隱藏起來,把數據操作變成了一個個針對車輛的“操作”。這就是service最后提供出來的功能:“操 作”。

所以說,其實service層是整個架構中最重的一層,大部分業務邏輯都集中于這一層。

每個請求進來,進入controller的時候,controller就會調用各個service來拼裝服務數據,最后把數據返回給前端。到此,其實service層是做什么的,為什么有其存在的必要就很清楚了。

這里注意一點,一個清晰的MVC里,controller里不應該有任何直接對數據庫的操作,所有操作都調用service層來操作數據,這樣controller才能稱為一個“干凈的controller”。

3. Route

咦,奇怪的一層,Route跟controller有啥區別?怎么說呢,很難分清。controller是每個請求進來之后處理的邏輯,而route則定義了請求應該進入那個controller。

這里把Route單獨拿出來說,只是為了展示下我們是如何管理Route的。那就是我們自己修改過的一個小庫:rainbowy。

這個玩意的作用是:用文件目錄結構自動生成route。恩就是這么簡單,然后我們給他集成了一些小特色,例如在route中直接定義接口文檔,然后最后匯總生成一個api文檔匯總頁面,供前端自己模擬請求接口。

具體文檔和代碼見: https://github.com/xinyu198736/rainbow

我們不是用包的方式引入的,而是直接內置到項目lib里,所以這里不能保證及時更新,其實原理很簡單。

不要小看這種route管理方式,當route變得成百上千的時候,文件夾嵌套的方式就變得非常實用了,可以快速定位到某個業務代碼中。

4. ORM

ORM是一種將數據庫操作抽象成語言原生對象操作的方法工具。在NodeJS里有不少orm庫,不過已經穩健成熟的不多,例如我們使用的 sequelize,已經發展很久了,基礎功能穩定了,但是很多功能還在beta,偶爾還會出現一些蛋疼的bug,例如他的promise,里面出現錯 誤,會導致兩次回調之類的。

不過既然用了那也沒話說了,ORM除了性能上有一定影響之外,好處還是大于壞處的,首先是數據操作很方便,幾句話搞定,然后維護更方便,增加字段之類的工作,基本就是分分鐘搞定。

一個木有ORM的MVC結構是不完美的。為了讓我們的結構更完美,我們很蛋疼的在ORM上面又封裝了一層。名字叫做SuperModel。

SuperModel是一個基于ORM的頂層封裝,作用有二:

A. 統計mysql和mongodb的操作接口,完全一致化,甚至你根本不知道你在用mysql還是mongo的說。

B. 把ORM封裝成統一的鏈式操作,跟mongoose的操作有點類似。

var userModel = new SuperModel(“user”);

這句話就會生成一個SuperModel實例,user是什么呢?是一個json格式的數據結構定義,一般放在項目里的model目錄下

“NodeJS在大搜車” 之 MVC基礎結構

一個典型的操作:

Example.findAll().where({id:{lt:3}}).offset(10).limit(10)
.order({id:"desc"}).fields(['id','title','content'])
.done(function(error,datas){

})

因為我們的項目是移植過來的,新版的業務才使用了ORM,所以只能看到很小一部分數據結構定義。

5. Util

這個跟MVC沒什么關系了,不過一般都會有些工具類單獨抽取出來,例如JSON請求統一返回類,字符串處理,日期處理類,編碼處理類,推送短信類,加密解密等。這些工具跟數據庫無關,純工具性質,所以抽取出來作為Util存在。

6. filter

這也是一個奇怪的層,是由rainbow引入的概念,將其作為controller的前置層,大概就是一個前置中間件的東西。

功能方面,主要做些 用戶登錄前置驗證等。所謂的filter,字面意思也是如此的,在進入純凈的controller之前過濾一下。

具體用法見 上面 rainbow的文檔。

小結。

其實說是要總結MVC基礎要素一樣的文章,最后目的只是為了分享下我們項目的應用結構。也算是我們的一點點最佳實踐,希望對初學者能夠有一定的啟發,對資深開發能夠有另外一種思路,也歡迎大家一起交流。

下面還會有其他一系列文章,事先預告下:

  1. 存儲,緩存,云服務 方面的一些最佳實踐和經驗。

  2. NodeJS服務性能監測,調優,調試,監控報警,應急處理方面的話題。

  3. NodeJS線上多機部署,測試環境部署和使用,方面的話題。

歡迎大家持續關注我們的專欄。

另外,我們的NodeJS服務端開發團隊也在招聘小伙伴一起加入工作學習研究。關于我們公司,這里就不多介紹啦,C輪剛過的二手車解決方案互聯網 企業,坐標杭州,300人團隊,大概100名開發產品設計,我的團隊現在大概16人,分為前端和NodeJS兩部分,都缺人,各種求才。簡歷直接發我郵箱 即可:sunxinyu@souche.com

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!