摘要:寫好一個模板的最佳實踐是避免在模板中做任何處理。一個最好的實踐是應該永遠不會直接訪問數據庫。中間件的目的是為了提取常見的代碼,它將會在多個請求中執行,并且通常會修改請求響應對象。它的目的是加載發出請求的用戶。
Models 是你與你的數據庫交互的一些文件。它們包含了你處理你的數據的所有方法和功能。它們不僅僅包含了創建、讀取、更新和刪除的方法,還包含了業務邏輯。例如,如果你有一個 car model,你可以有一個 mountTyres 方法。
在你的數據庫中,針對每種類型的數據,你應該創建至少一個文件。在我們的例子中,我們有 users 和 comments,因此我們有 user model 和 comment model。有時候,當一個 model 文件很大,更好的做法是基于內部的邏輯將這個 model 文件分成好幾個文件。
你應該讓你的 models 獨立于外部。models 之間不應該相互引用。它們不需要知道哪個 controller 調用它們。它們永遠不要接收 request 或 reponse 對象,它們永遠不要返回 http 的錯誤,但是它們應該返回 model 的錯誤。
所有的這些將會使你的 models 更好維護。因為它們是獨立的,所以可以很好地測試它們。Models 可以移動到任何需要用到它的地方。改變一個 model,不會應該其他的東西,因為它是獨立的。
基于上面提的的點,讓我們來看看如何實現我們例子中的 model。下面是 comment model。
var db = require("../db") // Create new comment in your database and return its id // 在你的數據庫中創建一條新的 comment exports.create = function(user, text, cb) { var comment = { user: user, text: text, date: new Date().toString() } db.save(comment, cb) } // Get a particular comment exports.get = function(id, cb) { db.fetch({id:id}, function(err, docs) { if (err) return cb(err) cb(null, docs[0]) }) } // Get all comments exports.all = function(cb) { db.fetch({}, cb) } // Get all comments by a particular user exports.allByUser = function(user, cb) { db.fetch({user: user}, cb) }
user model 沒有包含進來。comment model 不關心它是什么,它僅僅關心它怎么存儲。
var db = require("../db") , crypto = require("crypto") hash = function(password) { return crypto.createHash("sha1").update(password).digest("base64") } exports.create = function(name, email, password, cb) { var user = { name: name, email: email, password: hash(password), } db.save(user, cb) } exports.get = function(id, cb) { db.fetch({id:id}, function(err, docs) { if (err) return cb(err) cb(null, docs[0]) }) } exports.authenticate = function(email, password) { db.fetch({email:email}, function(err, docs) { if (err) return cb(err) if (docs.length === 0) return cb() user = docs[0] if (user.password === hash(password)) { cb(null, docs[0]) } else { cb() } }) } exports.changePassword = function(id, password, cb) { db.update({id:id}, {password: hash(password)}, function(err, affected) { if (err) return cb(err) cb(null, affected > 0) }) }
除了創建和管理用戶所需要的功能之外,那還有用于用戶身份驗證和密碼管理的方法。再一次的,這個 model 不知道已經存在的其他的 model、controller 或者應用的其他部分。
Views這個文件夾包含了你應用所有需要渲染的模板。通常,團隊中的設計師會在這里工作。
你想每一個 controllers 所對應的模板都有一個子文件夾。這樣的話,你將會為相同的任務組合模板。
選擇一個模板語言會讓人困惑,因為有很多的選擇。我們最喜歡的模板語言,是 Jade 和 Mustache,我們一直在用。Jade 很適合生成 html 頁面。它使得寫 html 標簽更短和更加可讀。針對于條件和迭代,它也可以使用 JavaScript。Mustache 在另外一方面,專注于渲染各種各樣的模板,它提供了盡可能少的邏輯運算符并且處理數據的方法很少。這使得它非常適合編寫非常干凈的模板,這些模板專注于顯示你的數據而不是處理數據。
寫好一個模板的最佳實踐是避免在模板中做任何處理。如果你的數據需要在顯示之前進行處理,在你的 controller 中處理。也要避免添加太多的邏輯,尤其是這個邏輯可以被移至 controller。
doctype html html head title Your comment web app body h1 Welcome and leave your comment each comment in comments article.Comment .Comment-date= comment.date .Comment-text= comment.text
如你所見,在渲染這個模板時,數據預計已經被處理好了。
Controllers這是一個文件夾,你將會定義你應用所有的路由在這個文件夾中。你的 controllers 將會處理 web 請求,將模板提供給用戶,并且和你的 models 進行交互,以處理和檢索數據。這是膠水,能夠連接和控制你的 web 應用。
通常,對于你應用中的每一個邏輯部分,你至少會有一個文件。例如,一個文件處理評論,另外一個文件處理關于用戶的請求等等。來自同一個 controller 的所有路由都有相同的前綴,這是一個好的實踐。例如 /comments/all 和 /comments/new。
有時候很難決定什么應該進入 controller,什么應該進入 model。一個最好的實踐是應該永遠不會直接訪問數據庫。它永遠不應該調用 write,update,fetch 這些數據庫提供的方法,而應該依靠 model 中的方法。例如如果你有一個 car model,你想要把 4 個輪子安裝到這個 car 上,controller 不會調用 db.update(id, { wheels: 4 }),而是會調用像 car.mountwheels(id, 4) 這樣的方法。
下面是負責評論的 controller。
var express = require("express") , router = express.Router() , Comment = require("../models/comment") , auth = require("../middlewares/auth") router.post("/", auth, function(req, res) { user = req.user.id text = req.body.text Comment.create(user, text, function (err, comment) { res.redirect("/") }) }) router.get("/:id", function(req, res) { Comment.get(req.params.id, function (err, comment) { res.render("comments/comment", {comment: comment}) }) }) module.exports = router
在 controller 文件夾中,也有一個 index.js 文件夾。它的目的是加載所有其他的 controllers,和可能定義一些沒有相同前綴的路徑,例如 home 頁面路由。
var express = require("express") , router = express.Router() , Comment = require("../models/comment") router.use("/comments", require("./comments")) router.use("/users", require("./users")) // 與 comments 和 users 不同的是,home 頁面不需要前綴(comments 或 users) router.get("/", function(req, res) { Comments.all(function(err, comments) { res.render("index", {comments: comments}) }) }) module.exports = router
這個文件將會處理你所有的路由。你的應用在啟動的必須加載的唯一的路由器。
Middlewares在這個文件夾中,你將會存儲所有你 Express 的中間件。中間件的目的是為了提取常見的 controller 代碼,它將會在多個請求中執行,并且通常會修改 請求/響應 對象。
就像一個 controller,一個中間件永遠不應該訪問數據庫,相反,對于它要完成的每一項任務,它應該使用你的 models。
下面是一個 users 中間件,來自 middlewares/users.js 文件。它的目的是加載發出請求的用戶。
User = require("../models/user") module.exports = function(req, res, next) { if (req.session && req.session.user) { User.get(req.session.user, function(err, user) { if (user) { req.user = user } else { delete req.user delete req.session.user } next() }) } else { next() } }
這個中間件使用 user model,并且它沒有直接訪問數據庫。
下一步,authorization 中間件,當你想要阻止沒有權限訪問相同路由的時候,可以用到這個中間件。
module.exports = function(req, res, next) { if (req.user) { next() } else { res.status(401).end() } }
它沒有任何外部的依賴。如果你看看上面的 controllers 文件,你可以看看如何它是如何應用的。
Helpers這個文件夾包含實用的代碼,這些代碼被用在多個 models,middlewares 或者 controllers 中,但是 helpers 不屬于 models,middlewares 或 controllers 的范疇。通常,你對不同的常見任務,會有不同的文件。
一個例子就是 helper 文件提供一些方法來管理日期和時間。
Public這個文件件只是提供靜態文件。通常,它會有子文件夾,像 css,libs,img 用于 css 樣式,圖片和 JavaScript 庫就像 jQuery。這個文件夾能夠提供服務的最好實踐不是通過你的應用,而是通過一個 Nginx 或者 Apache 服務,它們比起 Node 在靜態文件的服務更好。
Tests每個項目都需要測試,并且你需要將所有的測試聚集到一起。為了幫助管理它們,你將它們分離在不同的子文件中。
controllers
helpers
models
middlewares
integration
ui
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95630.html
摘要:為應用增加新的特性和處理新的情況可能都會改變文件的結構。寫一個模板的最佳實踐是,不要在模板中處理數據。在上面這四個文件夾中,主要的測試代碼將是單元測試,這意味著你需要將被測試的代碼與應用分離開來。 前言 Node和Express并不嚴格要求它的應用的文件結構。你可以以任意的結構來組織你的web應用。這對于小應用來說,通常是不錯的,十分易于學習和實驗。 但是,當你的應用在體積和復雜性上都...
摘要:原文閱讀工程結構最佳實踐組件化按照功能劃分按照組件劃分層次化不要在中寫太多業務邏輯,專注層業務層要單獨抽出數據庫層單獨抽出化把常用組件做成包分離的和配置化環境感知根據不同環境使用不同配置 showImg(https://segmentfault.com/img/bVYQsC?w=2558&h=817); 原文閱讀: nodebestpractices 1 工程結構最佳實踐 1.1 組件...
摘要:前言這將是一個分為兩部分,內容是關于在生產環境下,跑應用的最佳實踐。潛在的攻擊者可以通過它們進行針對性的攻擊。 前言 這將是一個分為兩部分,內容是關于在生產環境下,跑Express應用的最佳實踐。第一部分會關注安全性,第二部分最會關注性能和可靠性。當你讀這篇文章時,假設你已經對Node.js和web開發有所了解,并且對生產環境有了概念。 概覽 生產環境,指的是軟件生命循環中的某個階段。...
摘要:前言這將是一個分為兩部分,內容是關于在生產環境下,跑應用的最佳實踐。第一部分會關注安全性,第二部分則會關注性能和可靠性。關于第一部分,請參閱在生產環境下的最佳實踐安全性。 前言 這將是一個分為兩部分,內容是關于在生產環境下,跑Express應用的最佳實踐。第一部分會關注安全性,第二部分則會關注性能和可靠性。當你讀這篇文章時,會假設你已經對Node.js和web開發有所了解,并且對生產環...
摘要:特意對前端學習資源做一個匯總,方便自己學習查閱參考,和好友們共同進步。 特意對前端學習資源做一個匯總,方便自己學習查閱參考,和好友們共同進步。 本以為自己收藏的站點多,可以很快搞定,沒想到一入匯總深似海。還有很多不足&遺漏的地方,歡迎補充。有錯誤的地方,還請斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應和斧正,會及時更新,平時業務工作時也會不定期更...
閱讀 816·2021-11-25 09:43
閱讀 1682·2021-09-29 09:42
閱讀 1898·2019-08-30 15:55
閱讀 3418·2019-08-30 15:54
閱讀 2624·2019-08-30 13:20
閱讀 3508·2019-08-29 13:25
閱讀 917·2019-08-28 18:03
閱讀 1783·2019-08-26 13:44