Developing web-apps like it's 2013
Upcoming SlideShare
Loading in...5
×
 

Developing web-apps like it's 2013

on

  • 4,476 vues

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

Statistiques

Vues

Total des vues
4,476
Vues sur SlideShare
4,362
Vues externes
114

Actions

J'aime
15
Téléchargements
76
Commentaires
5

5 Ajouts 114

http://faz.my 77
http://192.168.1.137 13
https://twitter.com 12
http://localhost 9
http://www.onlydoo.com 3

Accessibilité

Catégories

Détails de l'import

Uploaded via as Microsoft PowerPoint

Droits d'utilisation

© Tous droits réservés

Report content

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
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
  • i found this really cool and very informative
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
  • i found this very informative thanks a lot for sharing
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
  • i found this very informative thanks a lot for sharing
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
  • what's fun in read?
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
  • Cool!!!
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
Poster un commentaire
Modifier votre commentaire

Developing web-apps like it's 2013 Developing web-apps like it's 2013 Presentation Transcript

  • Developing web-apps like it’s2013 a case-study of using node.js to build entreprise applications 1
  • Who?Laurent Van Basselaere@Laurent_VBI do stuff with codeat Arhs Developments 2
  • ARHS Developments10 years, 300 peopleConsulting & fixed price projectsSoftware (Java)Business Intelligence 3
  • testing 4
  • Testing 5
  • 6
  • MS Access? SRSLY?MS AccessMultiple copiesSingle userNo remote useLame 7
  • Fatman FTWMS Access BrowserMultiple versions CentralizedSingle user Unlimited usersNo remote use EverywhereLame Awesome 8
  • We wrote a web-app 9
  • Fatman tech stackBootstrap asyncKnockout underscoreExpress momentNodeMongooseMongoDB 10
  • Elegant MongoDB object modeling forNode.jsORM seemed desirableClean object model to use in app code 11
  • 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
  • CREATE/EDITvar project = new Project({ id: ‘AKCT’ , name: ‘GOCA Newsoft AKCT’ , users: [‘vanbasla’, ‘grosjech’]});project.save(function (err){ //… callback after save}); 13
  • 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
  • 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
  • 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
  • In fatmanWe use setters + pre-save middlewareto keep history of edits. 17
  • 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
  • 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
  • Express is a minimal and flexiblenode.js web application framework.Simple and modularNode de-facto standard
  • 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);
  • 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 }); }); });}
  • 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 }); }); });}
  • 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); }); });}
  • 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);
  • 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 }); });}
  • 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 }); });}
  • 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); });}
  • 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 }); }); }); }); });}
  • Async.jsAsync is a utility module which providesstraight-forward, powerful functions forworking with asynchronous JavaScript
  • 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); });}
  • 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
  • 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});});
  • MORE async Async.jsCollections Control floweach seriesmap parallelfilter whilstreject doWhilstreduce untildetect doUntilsortBy waterfall… …
  • FATMAN60 days dev6 months prod12 projects (2 to 10 users)
  • FATMAN
  • FATMAN
  • FATMAN