Your SlideShare is downloading. ×
Developing web-apps like it's 2013
Prochain SlideShare
Chargement dans... 5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Developing web-apps like it's 2013

3,892
views

Published on

A case-study of using node.js to develop entreprise applications. Includes real-world examples for express.js, mongoose.js and async.js

A case-study of using node.js to develop entreprise applications. Includes real-world examples for express.js, mongoose.js and async.js

Published in: Technologies

5 commentaires
15 mentions J'aime
Statistiques
Remarques
Aucun téléchargement
Vues
Total des vues
3,892
Sur Slideshare
0
À partir des ajouts
0
Nombre d'ajouts
1
Actions
Partages
0
Téléchargements
76
Commentaires
5
J'aime
15
Ajouts 0
No embeds

Signaler un contenu
Signalé comme inapproprié Signaler comme inapproprié
Signaler comme inapproprié

Indiquez la raison pour laquelle vous avez signalé cette présentation comme n'étant pas appropriée.

Annuler
No notes for slide

Transcript

  • 1. Developing web-apps like it’s2013 a case-study of using node.js to build entreprise applications 1
  • 2. Who?Laurent Van Basselaere@Laurent_VBI do stuff with codeat Arhs Developments 2
  • 3. ARHS Developments10 years, 300 peopleConsulting & fixed price projectsSoftware (Java)Business Intelligence 3
  • 4. testing 4
  • 5. Testing 5
  • 6. 6
  • 7. MS Access? SRSLY?MS AccessMultiple copiesSingle userNo remote useLame 7
  • 8. Fatman FTWMS Access BrowserMultiple versions CentralizedSingle user Unlimited usersNo remote use EverywhereLame Awesome 8
  • 9. We wrote a web-app 9
  • 10. Fatman tech stackBootstrap asyncKnockout underscoreExpress momentNodeMongooseMongoDB 10
  • 11. Elegant MongoDB object modeling forNode.jsORM seemed desirableClean object model to use in app code 11
  • 12. Schemavar mongoose = require(‘mongoose’);mongoose.connect(‘localhost’, ‘fatman’);var ProjectSchema = new mongoose.Schema({ id : String , name : String , users : [String]});var Project = mongoose.model(Project, ProjectSchema); 12
  • 13. CREATE/EDITvar project = new Project({ id: ‘AKCT’ , name: ‘GOCA Newsoft AKCT’ , users: [‘vanbasla’, ‘grosjech’]});project.save(function (err){ //… callback after save}); 13
  • 14. RETRIEVE// find project by idProject.where(‘id’, ‘AKCT’) .findOne(function(err, project) { // do something with search result });// find my projectsProject.find({‘users’: username}) .exec(function(err, projects){ // do something with search results }); 14
  • 15. MORE Schemafunction trim(value){ return value ? value.trim() : value;}function lessThan80chars(value){ return value.length <= 80;}var ProjectSchema = new mongoose.Schema({ id : {type: String, required: true, unique: true} , name : {type: String, set: trim, validate: [ lessThan80chars, Value too long. Max 80 characters.]}}); 15
  • 16. Advanced// staticsProjectSchema.statics.findById = function(projectId, cb){ Project.where(id, projectId).findOne(cb);};// methodsProjectSchema.methods.issueTrackerEnabled = function() { return this.issueTracker != null;};// middlewareProjectCaseSchema.pre(‘remove’, function(next) { // do something when a Project is deleted next();}); 16
  • 17. In fatmanWe use setters + pre-save middlewareto keep history of edits. 17
  • 18. In fatman// creates a setter for fieldfunction setter(field) { return function setField(newValue) { this._oldValues = this._oldValues || {}; this._oldValues[field] = this[field]; return newValue; }}var TestCaseSchema = new Schema({ id: {type:Number,index:true}, description: {type:String, set: setter(description)}, history: [Schema.Types.Mixed]}); 18
  • 19. In fatman// Populate history before save.TestCaseSchema.pre(save, function (next) { var self = this , oldValues = this._oldValues || {}; delete this._oldValues; this.modifiedPaths.forEach(function (field) { if (field in oldValues) { self.history.push({ ‘old: oldValues[field], ‘new’: self[field] }); } }); next();}); 19
  • 20. Express is a minimal and flexiblenode.js web application framework.Simple and modularNode de-facto standard
  • 21. Hello Expressvar express = require(express), consolidate = require(consolidate);// create an express appvar app = express();// configure view engineapp.engine(html, consolidate.handlebars);app.set(views, __dirname + /views);// configure a route with an url parameterapp.get(/hello/:name, hello);function hello(req, res, next){ res.render(hello.html, { name : req.params.name });}app.listen(1337);console.log(Listening on port 1337);
  • 22. controllerfunction list (req, res, next){ Project.findById(req.params.projectId, function(err, project){ if (err) return next(err); TestCase.find({‘project’: project}, function(err, testcases){ if (err) return next(err); res.render(‘testcases.html’, { ‘project’: project, ‘testcases’: testcases }); }); });}
  • 23. controllerfunction show (req, res, next){ Project.findById(req.params.projectId, function(err, project){ if (err) return next(err); TestCase.findOne({‘project’:project, ‘id’:id}, function(err, tc){ if (err) return next(err); res.render(‘testcase.html’, { ‘project’: project, ‘testcase’: tc }); }); });}
  • 24. controllerfunction save (req, res, next){ Project.findById(req.params.projectId, function(err, project){ if (err) return next(err); var tc = new TestCase(req.body); tc.project = project; tc.save(function(err, tc){ if (err) return next(err); // redirect after post res.redirect(req.url); }); });}
  • 25. MIDDLEWAREfunction loadProject(req, res, next){ Project.findById(req.params.projectId, function(err, project){ if (err) return next(err); res.locals.project = project; next(); });}// before all routes requiring a projectapp.all(/:projectId/*, loadProject);
  • 26. BETTERfunction list (req, res, next){ var project = res.locals.project; TestCase.find({‘project’:project}, function(err, testcases){ if (err) return next(err); res.render(‘testcases.html’, { ‘testcases’: testcases }); });}
  • 27. BETTerfunction show (req, res, next){ var project = res.locals.project; TestCase.findOne({‘project’:project, ‘id’:id}, function(err, tc){ if (err) return next(err); res.render(‘testcase.html’, { ‘testcase’: tc }); });}
  • 28. BETTerfunction save (req, res, next){ var tc = new TestCase(req.body); tc.project = res.locals.project; tc.save(function(err){ if (err) return next(err); res.redirect(req.url); });}
  • 29. pyramid of doomfunction search (req, res, next){ Project.findById(projectId, function(err, project){ if (err) return next(err); TestPlan.findByIdentifier(project, testPlanId, function(err, testPlan) { if (err) return next(err); var tags = getTagsFromRequest(req); TestCase.findByTag(testPlan, tags, function(err, tagQuery, testCases){ if (err) return next(err); TestCase.countTags(tagQuery, function(err, tagsResult) { if (err) return next(err); res.render(‘search’, { ‘testCases’ : testCases, ‘tagsResult’ : tagsResult, ‘project’ : project, ‘testPlan’ : testPlan, ‘tags’ : tags }); }); }); }); });}
  • 30. Async.jsAsync is a utility module which providesstraight-forward, powerful functions forworking with asynchronous JavaScript
  • 31. pyramid NO MOREAsync.jsfunction search (req, res, next){ async.waterfall([ function(cb){ Project.findById(projectId, cb); }, function(cb, project){ res.locals.project = project; TestPlan.findByIdentifier(project, testPlanId, cb); }, function(cb, testPlan){ res.locals.testPlan = testPlan; var tags = res.locals.tags = getTagsFromRequest(req); TestCase.findByTag(testPlan, tags, cb); }, function(cb, tagQuery, testCases){ res.locals.testCases = testCases; TestCase.countTags(tagQuery, cb); } ], function(err, tagsResult){ if (err) return next(err); res.render(‘search’, tagsResult); });}
  • 32. MORE async Async.jsvar ids = [‘AKCT’, ‘FATMAN’];var projects = [];ids.forEach(function(id){ Project.findById(id, function(err, project){ projects.push(project); });});res.render(‘projects’, {‘project’ : projects}); WRONG
  • 33. MORE async Async.jsvar ids = [‘AKCT’, ‘FATMAN’];var projects = [];async.each(ids, function(id, next){ Project.findById(id, function(err, project){ projects.push(project); next(); })}, function(err){ res.render(‘projects’, {‘projects’: projects});});
  • 34. MORE async Async.jsCollections Control floweach seriesmap parallelfilter whilstreject doWhilstreduce untildetect doUntilsortBy waterfall… …
  • 35. FATMAN60 days dev6 months prod12 projects (2 to 10 users)
  • 36. FATMAN
  • 37. FATMAN
  • 38. FATMAN