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

Similaire à 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
 

Dernier

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
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
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
 
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
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"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
 
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
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
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
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 

Dernier (20)

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
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
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
 
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
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"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
 
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
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
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
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
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
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 

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)