SlideShare une entreprise Scribd logo
1  sur  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

Contenu connexe

Tendances

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
 

Tendances (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
 

Similaire à Developing web-apps like it's 2013

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
 

Similaire à Developing web-apps like it's 2013 (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
 

Dernier

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMKumar Satyam
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAnitaRaj43
 

Dernier (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 

Developing web-apps like it's 2013

  • 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)