SlideShare a Scribd company logo
1 of 38
Developing web-
apps like it’s
2013
  a case-study of using node.js to build
         entreprise applications


                                           1
Who?
Laurent Van Basselaere
@Laurent_VB

I do stuff with code
at Arhs Developments


                         2
ARHS Developments



10 years, 300 people
Consulting & fixed price projects
Software (Java)
Business Intelligence

                                    3
testing




          4
Testing




          5
6
MS Access? SRSLY?
MS Access
Multiple copies
Single user
No remote use
Lame

                    7
Fatman FTW
MS Access Browser
Multiple versions Centralized
Single user Unlimited users
No remote use Everywhere
Lame Awesome

                                8
We wrote a web-app




                     9
Fatman tech stack
Bootstrap   async
Knockout    underscore
Express     moment
Node
Mongoose
MongoDB

                         10
Elegant MongoDB object modeling for
Node.js



ORM seemed desirable
Clean object model to use in app code


                                        11
Schema
var 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/EDIT
var project = new Project({
    id: ‘AKCT’
  , name: ‘GOCA Newsoft AKCT’
  , users: [‘vanbasla’, ‘grosjech’]
});

project.save(function (err){
    //… callback after save
});




                                      13
RETRIEVE
// find project by id
Project.where(‘id’, ‘AKCT’)
       .findOne(function(err, project) {
           // do something with search result
       });

// find my projects
Project.find({‘users’: username})
       .exec(function(err, projects){
           // do something with search results
       });




                                                 14
MORE Schema
function 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
// statics
ProjectSchema.statics.findById = function(projectId, cb){
  Project.where('id', projectId).findOne(cb);
};

// methods
ProjectSchema.methods.issueTrackerEnabled = function() {
  return this.issueTracker != null;
};

// middleware
ProjectCaseSchema.pre(‘remove’, function(next) {
  // do something when a Project is deleted
  next();
});

                                                            16
In fatman
We use
     setters
     +
     pre-save middleware
to keep history of edits.


                            17
In fatman
// creates a setter for field
function 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 flexible
node.js web application framework.



Simple and modular
Node de-facto standard
Hello Express
var express = require('express'),
    consolidate = require('consolidate');

// create an express app
var app = express();

// configure view engine
app.engine('html', consolidate.handlebars);
app.set('views', __dirname + '/views');

// configure a route with an url parameter
app.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');
controller
function 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
        });
      });
    });
}
controller
function 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
        });
      });
    });
}
controller
function 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);
      });
    });
}
MIDDLEWARE
function 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 project
app.all('/:projectId/*', loadProject);
BETTER
function 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
      });
    });
}
BETTer
function 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
      });
    });
}
BETTer
function 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 doom
function 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.js

Async is a utility module which provides
straight-forward, powerful functions for
working with asynchronous JavaScript
pyramid NO MOREAsync.js

function 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.js

var 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.js

var 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.js

Collections   Control flow

each          series
map           parallel
filter        whilst
reject        doWhilst
reduce        until
detect        doUntil
sortBy        waterfall
…             …
FATMAN
60 days dev
6 months prod
12 projects (2 to 10 users)
FATMAN
FATMAN
FATMAN

More Related Content

What's hot

Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureFDConf
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascriptkvangork
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
What's new in jQuery 1.5
What's new in jQuery 1.5What's new in jQuery 1.5
What's new in jQuery 1.5Martin Kleppe
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerNode.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerIslam Sharabash
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
AngularJS Services
AngularJS ServicesAngularJS Services
AngularJS ServicesEyal Vardi
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IVisual Engineering
 
Angular 1 + es6
Angular 1 + es6Angular 1 + es6
Angular 1 + es6장현 한
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
Slaven tomac unit testing in angular js
Slaven tomac   unit testing in angular jsSlaven tomac   unit testing in angular js
Slaven tomac unit testing in angular jsSlaven Tomac
 
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGroovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGuillaume Laforge
 
CLS & asyncListener: asynchronous observability for Node.js
CLS & asyncListener: asynchronous observability for Node.jsCLS & asyncListener: asynchronous observability for Node.js
CLS & asyncListener: asynchronous observability for Node.jsForrest Norvell
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Eyal Vardi
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?Christophe Porteneuve
 
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJSJavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJSphilogb
 

What's hot (20)

Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
AngularJs
AngularJsAngularJs
AngularJs
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
What's new in jQuery 1.5
What's new in jQuery 1.5What's new in jQuery 1.5
What's new in jQuery 1.5
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerNode.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Zenly - Reverse geocoding
Zenly - Reverse geocodingZenly - Reverse geocoding
Zenly - Reverse geocoding
 
AngularJS Services
AngularJS ServicesAngularJS Services
AngularJS Services
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
 
Angular 1 + es6
Angular 1 + es6Angular 1 + es6
Angular 1 + es6
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Slaven tomac unit testing in angular js
Slaven tomac   unit testing in angular jsSlaven tomac   unit testing in angular js
Slaven tomac unit testing in angular js
 
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGroovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
 
CLS & asyncListener: asynchronous observability for Node.js
CLS & asyncListener: asynchronous observability for Node.jsCLS & asyncListener: asynchronous observability for Node.js
CLS & asyncListener: asynchronous observability for Node.js
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
 
meet.js - QooXDoo
meet.js - QooXDoomeet.js - QooXDoo
meet.js - QooXDoo
 
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJSJavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
 

Similar to Developing web-apps like it’s 2013 with Node.js

Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express Jeetendra singh
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js frameworkBen Lin
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Morris Singer
 
Build web application by express
Build web application by expressBuild web application by express
Build web application by expressShawn Meng
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-senseBen Lin
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.jsFDConf
 
0 to App faster with NodeJS and Ruby
0 to App faster with NodeJS and Ruby0 to App faster with NodeJS and Ruby
0 to App faster with NodeJS and RubyRebecca Mills
 
Cassandra Day Chicago 2015: 0 to App Faster with Node.js and Ruby
Cassandra Day Chicago 2015: 0 to App Faster with Node.js and RubyCassandra Day Chicago 2015: 0 to App Faster with Node.js and Ruby
Cassandra Day Chicago 2015: 0 to App Faster with Node.js and RubyDataStax Academy
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs偉格 高
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael HacksteinNoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael Hacksteindistributed matters
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript Glenn Stovall
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with ExpressAaron Stannard
 
Dependency Management with RequireJS
Dependency Management with RequireJSDependency Management with RequireJS
Dependency Management with RequireJSAaronius
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.jsdavidchubbs
 

Similar to Developing web-apps like it’s 2013 with Node.js (20)

Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
Build web application by express
Build web application by expressBuild web application by express
Build web application by express
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-sense
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.js
 
0 to App faster with NodeJS and Ruby
0 to App faster with NodeJS and Ruby0 to App faster with NodeJS and Ruby
0 to App faster with NodeJS and Ruby
 
Cassandra Day Chicago 2015: 0 to App Faster with Node.js and Ruby
Cassandra Day Chicago 2015: 0 to App Faster with Node.js and RubyCassandra Day Chicago 2015: 0 to App Faster with Node.js and Ruby
Cassandra Day Chicago 2015: 0 to App Faster with Node.js and Ruby
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael HacksteinNoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael Hackstein
 
Express JS
Express JSExpress JS
Express JS
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
Dependency Management with RequireJS
Dependency Management with RequireJSDependency Management with RequireJS
Dependency Management with RequireJS
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.js
 
NoSQL meets Microservices
NoSQL meets MicroservicesNoSQL meets Microservices
NoSQL meets Microservices
 

Recently uploaded

unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 

Recently uploaded (20)

unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 

Developing web-apps like it’s 2013 with Node.js

  • 1. Developing web- apps like it’s 2013 a case-study of using node.js to build entreprise applications 1
  • 2. Who? Laurent Van Basselaere @Laurent_VB I do stuff with code at Arhs Developments 2
  • 3. ARHS Developments 10 years, 300 people Consulting & fixed price projects Software (Java) Business Intelligence 3
  • 6. 6
  • 7. MS Access? SRSLY? MS Access Multiple copies Single user No remote use Lame 7
  • 8. Fatman FTW MS Access Browser Multiple versions Centralized Single user Unlimited users No remote use Everywhere Lame Awesome 8
  • 9. We wrote a web-app 9
  • 10. Fatman tech stack Bootstrap async Knockout underscore Express moment Node Mongoose MongoDB 10
  • 11. Elegant MongoDB object modeling for Node.js ORM seemed desirable Clean object model to use in app code 11
  • 12. Schema var 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/EDIT var 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 id Project.where(‘id’, ‘AKCT’) .findOne(function(err, project) { // do something with search result }); // find my projects Project.find({‘users’: username}) .exec(function(err, projects){ // do something with search results }); 14
  • 15. MORE Schema function 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 // statics ProjectSchema.statics.findById = function(projectId, cb){ Project.where('id', projectId).findOne(cb); }; // methods ProjectSchema.methods.issueTrackerEnabled = function() { return this.issueTracker != null; }; // middleware ProjectCaseSchema.pre(‘remove’, function(next) { // do something when a Project is deleted next(); }); 16
  • 17. In fatman We use setters + pre-save middleware to keep history of edits. 17
  • 18. In fatman // creates a setter for field function 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 flexible node.js web application framework. Simple and modular Node de-facto standard
  • 21. Hello Express var express = require('express'), consolidate = require('consolidate'); // create an express app var app = express(); // configure view engine app.engine('html', consolidate.handlebars); app.set('views', __dirname + '/views'); // configure a route with an url parameter app.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. controller function 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. controller function 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. controller function 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. MIDDLEWARE function 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 project app.all('/:projectId/*', loadProject);
  • 26. BETTER function 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. BETTer function 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. BETTer function 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 doom function 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.js Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript
  • 31. pyramid NO MOREAsync.js function 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.js var 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.js var 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.js Collections Control flow each series map parallel filter whilst reject doWhilst reduce until detect doUntil sortBy waterfall … …
  • 35. FATMAN 60 days dev 6 months prod 12 projects (2 to 10 users)