Node/Express/Mongo(実際にはMEANスタックを使用)でエンタープライズアプリケーションを構築する方法を理解しようとしています。
2冊の本といくつかのグーグル(同様のStackOverflowの質問を含む)を読んだ後、Expressを使用して大規模なアプリケーションを構築する良い例が見つかりませんでした。私が読んだすべてのソースは、次のエンティティによってアプリケーションを分割することを提案しています:
しかし、この構造で見られる主な問題は、コントローラーがgodオブジェクトのようなものであり、検証に責任があるreq
、res
オブジェクトについて知っていることと、ビジネスロジックがあるが含まれていることです。
反対に、ルートはオーバーエンジニアリングのように思えます。なぜなら、ルートは、エンドポイント(パス)をコントローラーメソッドにマッピングするだけだからです。
私はScala/Javaのバックグラウンドを持っているので、コントローラー/サービス/ daoの3層のすべてのロジックを分離する習慣があります。
私にとって次のステートメントが理想的です:
コントローラーは、WEBパーツとの対話、つまり、マーシャリング/アンマーシャリング、いくつかの簡単な検証(必須、最小、最大、正規表現の電子メールなど)のみを担当します。
サービスレイヤー(NodeJS/Expressアプリでは実際に見逃していた)は、ビジネスロジック、一部のビジネス検証のみを担当します。サービス層はWEBパーツについて何も知りません(つまり、Webコンテキストからだけでなく、アプリケーションの他の場所から呼び出すことができます)。
DAOレイヤーに関しては、私にとっては明らかです。 Mongooseモデルは実際にはDAOであるため、ここで最も明確なことです。
私が見た例は非常に単純であり、Node/Expressの概念のみを示していると思いますが、ビジネスロジック/検証の多くが関与する現実世界の例をいくつか見たいと思います。
編集:
もう1つはっきりしないのは、DTOオブジェクトがないことです。この例を考えてみましょう:
const mongoose = require('mongoose');
const Article = mongoose.model('Article');
exports.create = function(req, res) {
// Create a new article object
const article = new Article(req.body);
// saving article and other code
}
req.body
からのJSONオブジェクトは、Mongoドキュメントを作成するためのパラメーターとして渡されます。嫌なにおいがする。生のJSONではなく、具体的なクラスで作業したい
ありがとう。
誰もがプロジェクトを特定のフォルダーに分割する独自の方法を持っています。私が使用する構造は
configフォルダーには、「プロダクション」、「開発」、「テスト」など、開発のすべてのフェーズのデータベース接続設定などの構成ファイルが含まれます
例
'use strict'
var dbsettings = {
"production": {
//your test settings
},
"test": {
},
"development": {
"database": "be",
"username": "yourname",
"password": "yourpassword",
"Host": "localhost",
"connectionLimit": 100
}
}
module.exports = dbsettings
ログフォルダには、デバッグ用の接続ログエラーログが含まれます
コントローラーは、要求データとビジネスロジックを検証するためのものです
例
const service = require("../../service")
const async = require("async")
exports.techverify = (data, callback) => {
async.series([
(cb) => {
let searchObject = { accessToken: data.accessToken }
service.admin.get(searchObject, (err, result) => {
if (err || result.length == 0) {
callback(err, { message: "accessToken is invalid" })
} else {
delete data.accessToken
service.tech.update(data, { verified: true }, (err, affe, res) => {
if (!err)
callback(err, { message: "verification done" })
else
callback(err, { message: "error occured" })
})
}
})
}
])
}
モデルは、dbスキーマを定義するためのものです
mongoDbスキーマの例
'use strict'
let mongoose = require('mongoose');
let schema = mongoose.Schema;
let user = new schema({
accesstoken: { type: String },
firstname: { type: String },
lastname: { type: String },
email: { type: String, unique: true },
image: { type: String },
phoneNo: { type: String },
gender: { type: String },
deviceType: { type: String },
password: { type: String },
regAddress: { type: String },
pincode: { type: String },
fbId: { type: String, default: 0 },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
one_time_password: { type: String },
forgot_password_token: { type: String },
is_block: { type: Boolean, default: 0 },
skin_type: { type: String },
hair_length: { type: String },
hair_type: { type: String },
credits: { type: Number, default: 0 },
invite_code: { type: String },
refered_by: { type: String },
card_details: [{
card_type: { type: String },
card_no: { type: String },
card_cv_no: { type: String },
created_at: { type: Date }
}]
});
module.exports = mongoose.model('user', user);
servicesは、データベースクエリを記述するためのものですコントローラでクエリを記述しないで、このフォルダにクエリを記述して、コントローラで呼び出してください
mongooseを使用したクエリ
'use strict'
const modelUser = require('../../models/user');
exports.insert = (data, callback) => {
console.log('mongo log for insert function', data)
new modelUser(data).save(callback)
}
exports.get = (data, callback) => {
console.log('mongo log for get function', data)
modelUser.find(data, callback)
}
exports.update = (data, updateData, callback) => {
console.log('mongo log for update function', data)
modelUser.update(data, updateData, callback);
}
exports.getWithProjection = (data, projection, callback) => {
console.log('mongo log for get function', data)
modelUser.find(data, projection, callback)
}
utilsは、暗号化、パスワードの復号化など、プロジェクトで一般的に使用される一般的なユーティリティ機能用です
例
exports.checkPassword = (text, psypherText) => {
console.log("checkPassword executed")
console.log(text, psypherText)
return bcrypt.compareSync(text, psypherText)
}
exports.generateToken = (userEmail) => {
return jwt.sign({ unique: userEmail, timeStamp: Date.now }, config.keys.jsonwebtoken)
}
シンプルで基本的なルール
関連付けられたコンポーネントを互いに近づけてください。
ページをコンポーネントに分割して作業する
すべての依存コンポーネントが一緒になっている必要があります
共有物は他のすべてのコンポーネントから独立しているべきです。
最後に、すべての言語は甘いです。それはあなたが言語にどれだけ精通しているかということです。あなたが剣に精通している場合にのみ、戦いに勝つことができます。
nodeJS、Angular2を使用してAngular2アプリケーションを開発しています。ディレクトリ構造を支援します。
`メインモジュール`
`サブモジュール構造`
`共有フォルダを別のモジュールとして保持する`
それが役に立てば幸い :)
rohit salariaの回答は基本的に、Javaで使用しているのと同じアプリ構造を説明しています。
私はいくつかの発言があります。最初の最も重要なことは、これはJavaではないということです。当たり前のように聞こえるかもしれませんが、あなたの質問を見て、Javaの世界で使用されているのと同じ概念で同じ開発経験を見てください。私の次の発言は、これの単なる説明です。
DTOがありません。 Javaでは、期間が必要です。 Java Webアプリケーションでは、データをリレーショナルデータベースに保存し、JSONでフロントエンドとデータを送受信しますが、データをJavaに変換するのは自然なことです_オブジェクト。ただし、Nodeアプリでは、すべてがJavaScriptとJSONです。これがプラットフォームの強みの1つです。 JSONは一般的なデータ形式であるため、コードを記述したり、ライブラリに依存してレイヤーのデータ形式を変換する必要はありません。
データオブジェクトをリクエストからモデルに直接渡します。何故なの?フロントエンドからデータベースまでの共通データ形式としてJSONを使用すると、すべてのレイヤー間でアプリのデータモデルを簡単に同期できます。もちろん、この方法で行く必要はありませんが、ほとんどの場合はそれで十分なので、使用しないのはなぜですか?検証に関しては、MVC理論に従って属しているモデルで行われます(怠andやプラグマティズムがしばしばそれを置くコントローラーではありません:))。
最後に付け加えておきますが、これはプロジェクトサイズのスケーリングに関しては最適なプラットフォームではないということです。それはまったくうなずきですが、Javaはその面で優れています。