在應用程式開發的領域裡,相當重視「關注點分離 (separation of concerns, SOC) 」的設計原則,從字面上的意思,就是把整個應用程式分拆成不同功能層 (layer) 或程式碼模組 (module),每個區塊有各自的關注點,彼此分工合作。
當我們把關注點分離的概念落實到軟體架構 (architectural pattern) 時,最常見的分工是把「管理資料的功能」和「呈現視覺的功能」分離。這裡會介紹一個很常用的設計模式叫作 MVC 設計模式,在這個模式裡,會把軟體分成 Model、View、Controller 三大功能層。每一次 request/response 週期的背後,都由這三大功能層來合作完成。
什麼是 MVC?
Model、View、Controller 的區分,是希望能把應用程式的內部運作歸納成不同的部門,讓每個部門各自負責不同的關注點。具體的行為是「把不同意義的程式碼放在不同的檔案裡」。
Model
Model 常譯為「模型」,負責和資料庫溝通。這裡我們要先注意:應用程式和資料庫是兩個不同的東西,在應用程式裡想要做「新增/瀏覽/修改/刪除」的動作,就需要先有 Model 層幫忙去資料庫裡取出必要的資料,把資料放進應用程式裡的某個程式物件,然後才能用 JavaScript 去操作該物件。
這種放資料、與資料庫連動的物件,會被稱為 Model 物件,由 Model 層來統一管理。
Model 管理的功能層被稱做「邏輯層」,更明確一點說,是和「商業邏輯」有關的功能,例如:
電商網站:
- 會員購物有九折、訂單超過一定的金額免運費
- 檢查登入帳號的類型,並依此開放不同權限
社交網站:判斷使用者彼此之間的友好程度
To-do List:過了期但沒被執行的 to-dos 不能被刪除
這些邏輯出自於產品本身的需求或是規則。它們是獨立於網頁介面的商業邏輯,如果之後又另外開發了如手機 App 等相關應用程式,這些商業邏輯在大部分情況是通用的。和這些邏輯相關的程式碼應該被分類到對應的 Model 檔案裡。
View
View 常譯為「視圖」,View 所管理的功能層叫作「表現層 (presentation layer)」,顧名思義是負責管理畫面的呈現,也就是 HTML 樣板 (template)。
在開發框架裡,因為 HTML template 會有需要以動態顯示資料的情況 (也就是由 Model 取出的資料內容),所以 View 會再進一步運用樣板引擎 (template engine) 將資料帶入 template。我們很快就會在實作中看到相關細節。
Controller
Controller 常譯為「控制器」,它掌握使用者互動邏輯,也是應用程式收發 request/response 的核心。來自路由的 request 會先被送到 Controller,再由 Controller 通知 Model 調度資料,並且把資料傳遞給 View 來產生樣板 (template),並將呈現資料的 HTML 頁面回傳給客戶端。
你可以把 Controller 想做是 MVC 架構的中間人,它決定了應用程式的工作流程 (workflow),並且蒐集不同元件的工作結果,統一回傳給使用者。以下常見的設計問題,會由 Controller 來控制:
- 使用者是否需要先登入 (認證) 才可以看到網頁內容?
- 使用者是否只能閱讀資料,但不能修改或刪除?
- 使用者新增了資料之後,會重新導向至哪個頁面?
在 Controller 上會設置很多不同的「動作 (action)」,有點類似電視遙控器上的按鈕,只要觸發了不同的 action,Controller 就會啟動後續一系列的行為。
MVC 模式的實作
MVC 是一種理念,重點是分化程式的職責,而不同的框架有不同的運用方式,運用 MVC 模式最著名的框架是 Ruby on Rails,Rails 框架的檔案架構規劃了非常嚴謹的 models、controllers、views 架構,而且環繞著 MVC 模式發展出一系列的命名慣例:
相比之下,Express.js 也運用了 MVC 模式的思維,只是在檔案架構上並沒有強制分成不同的資料夾,例如以下例子是一個輕量的專案,檔案架構是透過 Express.js 的程式碼產生器 (express-generator) 自動產生的。由於程式碼不多,因此直接由 routes 下的程式碼來負責 Controller 的工作,在下圖中沒有 Model,若需要連結資料庫的話,需要再自己實作 Model 的部分。
若專案規模變大,為了提高閱讀和維護的效率,會再把程式碼獨立出來、並歸類到資料夾裡,有可能會出現如 Rails 那樣的完整 MVC 架構:
採用 MVC 架構三大好處
- 重複使用已寫好的程式碼:由於 MVC 三塊彼此獨立、各司其職,你可以使用同一套 model,針對使用場景不一樣,產出不同的 view 來呈現適合的資料,最大化程式碼的使用效率。
- 更容易維護程式碼:由於 MVC 三塊彼此獨立且互不干擾,可以讓你在不破壞現有架構下,進行擴充或修改,大幅提升開發效率。
- 方便團隊合作:同先前所說,由於 MVC 架構將應用程式切分為三塊,在實際工作時,也可以比照相同的方式,將工程師、設計師的負責部分切開,加快開發速度
[optin-monster-inline slug=”q9c8jelrbkhccctuc740″]
如何有效學習MVC
大部分的人第一次學習 MVC 時,常常是搭配在「第一次使用框架」的經驗裡,因此會有點搞不懂因果關係。在進入 Express.js 框架之前,AC的軟體開發實務入門課程就特地設計一個純 JavaScript 的小專案《翻牌遊戲》,在純 JavaScript 裡討論程式碼的分工,讓學生可以針對 MVC 的架構來理解程式碼分工的好處。有了這一層的鋪墊,之後學生學到框架時,就有更多的背景知識來了解「框架裡的 MVC 架構」。
至於學習是否有效,我們可以看看學員的真實回饋。