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
 
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015NoSQLmatters
 

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
 
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
 

Dernier

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructureitnewsafrica
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
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
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 

Dernier (20)

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
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
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 

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)