NodeJSは美しく、モジュール式で、オブジェクトであるか、redisとnohmでそのようにします

最近、サーバーサイドJavaScript、特にNodeJSをめぐってITコミュニティで多くの誇大宣伝がありましたが、奇妙なことに、モジュラーオブジェクトコードの記述方法に関する情報を見つけることは非常に困難であることが判明しました。 どういう意味ですか? 実際、私は最近jsに精通しており、それ以前は小さなJavaアプリケーションを作成し、自由時間にはPHPでオンラインゲームのサーバーサイドを作成しました。オブジェクト指向の代わりに、いわゆるプロトタイプ指向プログラミングを使用します。 さらに、JavaScriptは、Object.prototypeと__proto__に関して、この問題でも多くの混乱をもたらします。 私が最初に思いついたのは、他の多くの開発者と同様、「使い慣れたOOP」を実装することでした。 少し考えた後、nodeJSを使用するのは理にかなっていないと判断しました。 短命ではありますが、実際のオブジェクト指向アプローチを必要とするタスクを達成することはできませんでした。つまり、継承、ポリモーフィズム、さらにカプセル化の必要性を意味します(もちろん、これはすべて必要ですが、jsが提供する範囲で)。



nodeJSでかなりの数のアプリケーションを研究した結果、何らかの理由で、ほとんどのPHPフレームワークで現在受け入れられているMVCパターンをほとんど使用しないことに気付きましたが、このモデルは非常に便利であり、作成にかかるコスト(最初は非常に深刻です)実を結ぶでしょう。



実際のプロジェクト

タスクは私のために設定されました-node.jsにゲーム機のアプリケーションサーバーを実装することは、非常に簡単に思えます。 これをやった人からたくさんのコードをもらいました。 データベースとして、Redisが使用されます。 アプリケーションの構造は次のようになりました。

-ルート

--application.js

--config.js

--constants.js

--import_data.js

--slots_module.js

--user_activity.js

--social.js

--node_modules /

---ここにnode.jsのモジュールがあります



ノードのかなり馴染みのある構造ではありませんか? :=)



しかし、アプリケーションの要件が増大し、あらゆる種類の機能の量が増えると、予想されるように、このアプリケーションの保守が非常に難しくなりました。 アプリケーションと構成はそれぞれ5,000行になり、多くのコードの複製やその他の楽しみがあり、プロジェクトの検索を使用しないと、どこにあるかを判断することはほとんど不可能になりました。



そして最後に、私たちは要点に来ました。 沸騰します。 アプリケーションの徹底的なリファクタリングと再編成を行うことにしました。 まず、オブジェクトリレーショナルマッピング(ORM)のようなものがあることを思い出し、驚いたことに、NodeJSとRedisのORMのかなり良い実装を見つけました。 これは、私にとって馴染みのあるアーキテクチャを使用する大きな推進力となりました。 nohmモジュールを使用すると、モデル、そのプロパティ、およびメソッドを非常に簡単に記述できるため、コードを削減し、より構造的で美しいものにすることができます。 以下は、ユーザーモデル(User.js)の説明と使用の簡単な例です。

/** * User: hlogeon * Date: 31.07.13 * Time: 23:36 * TODO: continue creating this * read http://maritz.github.io/nohm/ */ var nohm = require('nohm').Nohm; var redis = require('redis').createClient(); nohm.setClient(redis); nohm.model('User', { properties: { balance: { type: "integer", defaultValue: 0, index: false }, ad_id: { type: "string", index: true }, bonus_games_pending: { type: "boolean", index: false }, chips: { type: "integer", defaultValue: 0 }, source: { type: "string" }, spins_count: { type: "integer", defaultValue: 0 }, mute: { type: "boolean", defaultValue: false }, sound: { type: "boolean", defaultValue: false }, charges_base: { type: "boolean", defaultValue: false }, parent_ref: { type: "string", index: true }, sid: { type: "string", index: true }, bonus_to: { type: "integer", defaultValue: 0 }, points_count: { type: "integer" }, parent_id:{ type: "string", index: true }, invitation_accepted: { type: "string" }, ref_type: { type: "string", index: true }, spins_temporary: { type: "integer" }, enter_date: { type: "integer" }, free_spins: { type: "integer" }, screen: { type: "string" }, last_game: { type: "string" }, startOffer: { type: "boolean", index: true }, last_activity: { type: "integer" }, win_turn: { type: "integer" }, double_game_pending: { type: "integer" }, level: { type: "integer", index: true }, last_spin: { type: "integer" }, uid: { type: "string", index: true }, status: { type: "string" }, bonus_games_temporary: { type: "integer", defaultValue: 0 }, browser: { type: "string" }, builded: { type: string, } }, methods: { getContryFlag: function () { return 'http://example.com/flag_'+this.p('country')+'.png'; }, updateBalance: function (value){ var balance = this.p('balance'); this.p('balance', balance+value); this.save(); }, updateChips: function(value){ var chips = this.p("chips"); this.p("chips", chips+value); this.save(); }, incrSpins: function(){ var spins = this.p('spins_count'); this.p('spins_count', spins+1); this.save(); }, swichMute: function(){ var mute = this.p('mute'); this.p('mute', !mute); this.save(); }, swichSound: function(){ var sound = this.p('sound'); this.p('sound', !sound); this.save(); }, setPointsCount: function (value){ this.p('points_count', value); this.save(); return value; }, incrPointsCount: function(){ var count = this.p('points_count'); this.p('points_count', count+1); this.save(); }, incrSpinsTmp: function(){ var tmp = this.p('spins_temporary'); this.p('spins_temporary', tmp+1); this.save(); }, incrFreeSpins: function(){ var spins = this.p('free_spins'); this.p('free_spins', spins+1); this.save(); }, incrLevel: function(){ var level = this.p('level'); this.p('level', level+1); this.save(); return this.p('level'); } } }); var user = nohm.factory('User'); exports.user = user;
      
      







使用例:



 var user = require('./UserTest').user; app.get('/', function (req, res) { //       var activeUser = nohm.factory('User'); activeUser.save(function(errs){ if(errs){ //  ,     res.json(errs); } else{ //  ,         res.json(activeUser.allProperties()); } }); //  -? app.get('/findUser', function (req, res) { var id = req.body.id; // user.load(id, function(err, aUser){ if(err){ //  ,  ! res.json(err); } else{ //  ,   - ,     ! console.log(aUser.getCountryFlag()); res.json(aUser.allProperties); } }) });
      
      







同意します。これは定数redis.hgetall()よりもはるかに簡単です。特に、モデルやリレーションでユーザーメソッドを定義できるようになったためです。



このアプローチのおかげで、アプリケーションをモジュールに分割し、新しい構造は次のようになります。

-ルート

--application.js

--constants.js

--config.js

-モデル/

--- User.js

--- Slotmachine.js

--- Event.js

-ヘルパー/

--- Social.js

--node_modules /



さらにいくつかのファイルがありましたが、コードサポートが大幅に簡素化され、行数が大幅に減少し、読みやすさが驚くほど向上しました! これで、10レベルのネストのコールバック関数から麺を解く必要はありません。 すべてが透明で、シンプルで明確です。



nodejsの初心者からのこの小さな記事が誰かに役立つことを願っています。 批判に非常に感謝します!



All Articles