SlideShare a Scribd company logo
1 of 58
Download to read offline
A single language for Backend and
Frontend: from AngularJS to Cloud
AngularConf 2016 - Turin
corley.it
Walter Dal Mut
github.com/wdalmut
twitter.com/walterdalmut
the problem
The REST webservice
Decoupling
Caching
Stateless
Quota planning (API Limits)
Extendable
Proxable
etc...
Planning
GET    → /book Access to a list of books
GET    → /book/:id Access to a single book
POST   → /book Create a new book
PATCH  → /book/:id Update a given book
DELETE → /book/:id Delete a given book
We can extends this using authentication header Authorization
We have a simple API
'use strict' ; 
angular.module( 'myApp').service( 'bookService' , function($http) { 
  return { 
    "list": function() { 
      return $http.get( "http://localhost:8085/book" ); 
    }, 
    ... // more methods  
  }; 
});
So we create a service
Or we can create a provider to configure the URLs etc
With a service we have a box
with different methods
bookService
Get all books: list()
Get a single book: get(:bookId)
Create a book: create(:bookModel)
...
The Book model is stable across our application
{title: "the book title" , isbn: "12345678" , available : true}
Or we resolve the book dependency with the book link (thanks to API uniquiness)
{ 
    name: "my favourites" , 
    books: [ 1,2,3] 
}
So:
$q.all( 
  [1,2,3].map(bookService.get)  
).then(function(books) {  
    //books is my favourites list with details  
});
Where the GET
'use strict' ; 
angular.module( 'myApp').service( 'bookService' , function($http) { 
  return { 
    "get": function(id) { 
      return $http.get( "http://localhost:8085/book/" +id); 
    }, 
    "list": function() { 
      return $http.get( "http://localhost:8085/book" ); 
    }, 
    ... // more methods  
  }; 
});
Return back to
A controller can request data
angular.module( 'myApp') 
  .controller( 'MainCtrl' , function ($scope, bookService) {  
    $scope.books = [];  
    bookService.list().success(function(books) {  
      $scope.books = books;  
    }); 
  });
Thanks to the controller we can pass our books to the view
The scope the communication channel for the data
Q: how can i verify the scope interface?
R: via testing (unit testing)?
Add a test case (1/2)
describe( "MainCtrl" , function() { 
    beforeEach(module( 'myApp')); 
    beforeEach(inject(function ($controller, $rootScope, $httpBackend) {  
        scope = $rootScope.$new();  
        httpBackend = $httpBackend;  
        MainCtrl = $controller( 'MainCtrl' , { 
            $scope: scope,  
            // other mocks  
        });  
    })); 
    // continue...  
});
Add a test case (2/2)
it('should attach a list of books to the scope' , function () {  
    // when someone require the "/book" endpoint reply with a valid response  
    httpBackend.whenGET( "http://localhost:8085/book" ).respond([  
      { id: 1, title: "This is a book" , isbn: "9835623" , available:  true }, 
      { id: 2, title: "Another super book" , isbn: "9835624" , available:  true }, 
      { id: 3, title: "A rare book to read" , isbn: "9835625" , available:  false } 
    ]); 
    // force the HTTP data resolution  
    httpBackend.flush();  
    // my expectation are that we books in the controller scope.  
    expect(scope.books.length).toBe( 3); 
    expect(scope.books.map((item) => item.title)).toEqual([  
      "This is a book" , 
      "Another super book" , 
      "A rare book to read"  
    ]); 
  });
$httpBackend act as a spy for HTTP requests
main.html
<!­­ books is in the current scope ­­>  
<books­list  books="books"></books­list >
The directive (web component)
angular.module("myApp") 
  .directive( 'booksList' , function() { 
    return { 
      replace:  true,
      templateUrl:  "app/views/books­list.html" , 
      restrict:  "E",
      scope: {  
        "books": "=", 
      }, 
      link:  function() {}, 
    }; 
  });
books-list.html
<div> 
    <book ng­if="book.available"  book="book" ng­repeat ="book in books" ></book> 
</div>
The book web component
angular.module("myApp") 
  .directive( 'book', function() { 
    return { 
      replace:  true,
      templateUrl:  "app/views/book.html" , 
      restrict:  "E",
      scope: {  
        "book": "=", 
      }, 
      link:  function() {}, 
    }; 
  });
book.html
<div>
    {{ book.title }}  
</div>
Components testing (1/3)
describe( "Books List" , function() { 
  var $compile,  
    $rootScope;  
  beforeEach(module( 'myApp')); 
  beforeEach(function() {  
    inject(function( _$compile_, _$rootScope _){ 
      $compile =  _$compile_; 
      $rootScope =  _$rootScope _; 
    }); 
  });
});
Components testing (2/3)
it("should expose our books" , function() { 
    $rootScope.books = [  
        { id:  1, title:  "This is a book" , isbn: "9835623" , available: true }  
        { id:  2, title:  "Another book" , isbn: "9835624" , available: true }  
        { id:  2, title:  "A secret book" , isbn: "9835625" , available: false }  
    ]; 
    var element = $compile( '<books­list books="books"></books­list>' )($rootScope);  
    $rootScope.$digest();  
    var html = element.html();  
    expect(html).toContain( "This is a book" ); 
    expect(html).toContain( "Another book" ); 
    expect(html).not.toContain( "A secret book" ); 
});
Components testing (3/3)
Single book directive testing
it("should expose a single book" , function() { 
    $rootScope.book = {  
        id:  1, 
        title:  "This is a single book" , 
        isbn:  "9835623" , 
        available: true  
    }; 
    var element = $compile( '<book book="book"></book>' )($rootScope);  
    $rootScope.$digest();  
    var html = element.html();  
    expect(html).toContain( "This is a single book" ); 
});
Add a book creation
We need the create book service method
We need another dummy web component
We use the controller to save the book model
The create method
angular.module( 'myApp').service( 'bookService' , function($http) {  
  return {  
    "create": function(book) {  
      return $http.post( "http://localhost:8085/book" , book); 
    }, 
    /* already implemented */  
    "get": function(id) {  
      return $http.get( "http://localhost:8085/book/" +id); 
    }, 
    "list": function() {  
      return $http.get( "http://localhost:8085/book" ); 
    }, 
  }; 
});
Dummy web component (1/3)
angular.module("myApp") 
  .directive( 'bookForm' , function() { 
    return { 
      replace:  true,
      templateUrl:  "app/views/book­form.html" , 
      restrict:  "E",
      scope: {  
        "book": "=", 
        "save": "=", 
      } 
    }; 
  });
We can also skip the book model pass-through
Dummy web component (2/3)
<div>
    <form> 
        Title: < input type="text" ng­model= "book.title"  /><br> 
        ISBN: < input type="text" ng­model= "book.isbn"  /><br> 
        Available: < input type="checkbox"  ng­model= "book.available"  /><br> 
        <button  type="button" ng­click= "save(book)" >Save</button>< br> 
    </form> 
</div>
Pay attention on ng-click that pass the book model
Dummy web component (3/3)
it("should expose a book", function(done) { 
  $rootScope.book = {}; 
  $rootScope.save = function(book) { 
    expect(book.title).toEqual("Some text"); 
    expect(book.isbn).toEqual("123456"); 
    expect(book.available).toBe(true); 
    done(); 
  }; 
  var element = $compile('<book­form book="book" save="save"></book­form>')($rootScope); 
  $rootScope.$digest(); 
  angular.element(element.find('input')[0]).val('Some text').triggerHandler('input'); 
  angular.element(element.find('input')[1]).val('123456').triggerHandler('input'); 
  angular.element(element.find('input')[2]).prop('checked', 'checked').triggerHandler('click'); 
  $rootScope.$apply(); 
  element.find('button')[0].click(); 
});
So we have validated that the directive calls the save method
But... Who have the save method? Controller + Book Service
Previous Controller (1/2)
angular.module( 'myApp') 
  .controller( 'MainCtrl' , function ($scope, bookService) {  
    $scope.book = {};  
    $scope.save = function(book) {  
      bookService.create(book).success(function(book) {  
        $scope.books = $scope.books.concat([book]);  
      });  
      $scope.book = {};  
    }; 
    // old parts...  
    $scope.books = [];  
    bookService.list().success(function(books) {  
      $scope.books = books;  
    }); 
  });
<book­form book="book" save="save"></book­form>
Previous Controller (2/2)
it('should create a new book', function () {  
  // something uses the save method  
  var book = {title: "This is a book", isbn: "9835623", available: true }; 
  scope.save(book); 
  // then the backend should works as expected  
  httpBackend.whenGET("http://localhost:8085/book" ).respond([]); 
  httpBackend.whenPOST("http://localhost:8085/book" ).respond( 
    Object.assign({}, book, {id: 1}) 
  );
  httpBackend.flush(); 
  expect(scope.book).toEqual({}); 
  expect(scope.books.length).toBe(1); 
  expect(scope.books[0].id).toBe(1); 
  expect(scope.books[0].title).toEqual("This is a book"); 
  expect(scope.books[0].isbn).toEqual("9835623"); 
  expect(scope.books[0].available).toBe(true); 
});
We can develop the app but...
How to deliver a scalable and
cost-effective backend?
ServerLess environments
Those envs allows us to pay just for every single requests
No requests? No payments! [more or less]
No server maintenance (platform as a service)
Amazon Web Services
AWS API Gateway [✔]
AWS Lambda [✔]
AWS DynamoDB [✔]
AWS SNS [ ]
AWS SQS [ ]
AWS CloudWatch [ ]
so many services... [ ... ]
API Gateway
Thanks to API Gateway you can create/publish/maintain/monitor
and secure APIs at any scale
Essentially: with API Gateway you declare your APIs interfaces and delegate to another component (like Lambda,
EC2, etc) the functionality
Lambda is a compute service that can run the code on your behalf
using AWS infrastructure
Amazon DynamoDB is a fully managed NoSQL database service that
provides fast and predictable performance with seamless scalability.
["apiGateway", "lambda", "dynamodb"].reduce(myAppFn);
Dealing with
ApiGateway + Lambda
manually is tricky
AWS releases a project: ServerLess that
helps a lot the wiring
https://github.com/serverless/serverless
ServerLess is interesting but for REST API
is not super simple to use imho...
I prefer to use Claudia.js
https://github.com/claudiajs/claudia
Claudia expose a very simple interface
var ApiBuilder =  require('claudia­api­builder' ), 
    api =  new ApiBuilder();  
api.get('/hello', function (request, response)  { 
    return "Hello"; 
});
Similar to express or hapi
You can use return codes and more
features...
api.post('/account' , function (request) {  
    return api.ApiResponse ({ 
        name: "Walter", 
        surname: "Dal Mut"  
    }, 201); 
});
Claudia.js prepare the whole ApiGateway and Lambda
configuration (with CORS) automatically for you
claudia create   
    ­­name book­ module  
    ­­region eu­west­ 1  
    ­­api­module book  
    ­­config claudia­books.json
It creates a new module book-module and store in claudia-books.json the Claudia.js con guration
Claudia.js manage also all updates
claudia update  
    ­­config claudia­ conf.json
So we have to develop our API
Thanks to Joi we can add data validation to our API
var joi = require(' Joi');
var result = joi.object().keys({  
  id: joi.number().required(),  
  title: joi. string().min(1).required()  
}).validate(request.body);  
if (result.error) {  
    return new api. ApiResponse (result.error, 406);
} 
// continue
Claudia.js manage JSON data automatically
Claudia.js manage A+ Promises as a
return element
api.post( "/say­ok" , function(request)  { 
    var d = q.promise();  
    setTimeout( function() { 
        d.resolve( "OK"); 
    }, 2000); 
    return d.promise;  
});
So...
api.post( "/say­ok" , function(request)  { 
    // validation...  
    return db.save(request.body);  
});
For Node.js DynamoDB offers a
"Document client"
docClient =  new AWS.DynamoDB.DocumentClient({region:  "eu­west­1" }); 
docClient.put({  
  Item: {name:  "Walter", surname:  "Dal Mut" }, 
  TableName: tableName  
}).promise();  
docClient.get( ...); // primary key  
docClient.query( ...); // on a secondary index and/or primary key  
docClient.scan( ...); // search without index (table scan)
All methods have a A+ Promise implementation integrated
Put all together
api.post( "/book", function(request) {  
  var d = q.promise();  
  var result = joi.object().keys({  
    title: joi. string().min(1).required(),  
    isbn: joi. string().min(1).required(),  
    available: joi.boolean().required()  
  }).validate(request.body);  
  if (result.error) {  
    return new api. ApiResponse (result.error, 406);
  } 
  var id = uuid.v4();  
  var item = Object.assign({}, {id: id}, request.body);  
  docClient.put({ Item: item, TableName : tableName}).promise().then(function() {  
    d.resolve(item);  
  });; 
  return d.promise;  
});
Of course you can split all responsabilities to di erent components
Thank you for listening
If you are interested in workshops and/or training sessions feel free
to contact info@corley.it
Check out also our page for training at: corsi.corley.it
Check out our corporate website: corley.it

More Related Content

What's hot

Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsPractical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsasync_io
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 ModelsVincent Chien
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDBWelcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDBMongoDB
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway ichikaway
 
Eve - REST API for Humans™
Eve - REST API for Humans™Eve - REST API for Humans™
Eve - REST API for Humans™Nicola Iarocci
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryRebecca Murphey
 
2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)Dominik Gruber
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Treeadamlogic
 
Code Samples &amp; Screenshots
Code Samples &amp; ScreenshotsCode Samples &amp; Screenshots
Code Samples &amp; ScreenshotsNii Amah Hesse
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHPHow to use MongoDB with CakePHP
How to use MongoDB with CakePHPichikaway
 
Time to React!
Time to React!Time to React!
Time to React!STX Next
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple DevelopersPeter Friese
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestMyles Braithwaite
 
Rails 3 ActiveRecord
Rails 3 ActiveRecordRails 3 ActiveRecord
Rails 3 ActiveRecordBlazing Cloud
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsRebecca Murphey
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 

What's hot (20)

Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsPractical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.js
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 Models
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDBWelcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDB
 
Javascript - Beyond-jQuery
Javascript - Beyond-jQueryJavascript - Beyond-jQuery
Javascript - Beyond-jQuery
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
 
Eve - REST API for Humans™
Eve - REST API for Humans™Eve - REST API for Humans™
Eve - REST API for Humans™
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
 
MongoDB
MongoDBMongoDB
MongoDB
 
Code Samples &amp; Screenshots
Code Samples &amp; ScreenshotsCode Samples &amp; Screenshots
Code Samples &amp; Screenshots
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHPHow to use MongoDB with CakePHP
How to use MongoDB with CakePHP
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
 
Time to React!
Time to React!Time to React!
Time to React!
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple Developers
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
 
Rails 3 ActiveRecord
Rails 3 ActiveRecordRails 3 ActiveRecord
Rails 3 ActiveRecord
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 

Similar to A single language for backend and frontend from AngularJS to cloud with Claudia.js

Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackNelson Glauber Leal
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxSHIVA101531
 
Performances & SEO in AngularJS
Performances & SEO in AngularJSPerformances & SEO in AngularJS
Performances & SEO in AngularJSPhilos.io
 
First java-server-faces-tutorial-en
First java-server-faces-tutorial-enFirst java-server-faces-tutorial-en
First java-server-faces-tutorial-entechbed
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackNelson Glauber Leal
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformNelson Glauber Leal
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorialice27
 
A piece of sugar in your client-side development
A piece of sugar in your client-side developmentA piece of sugar in your client-side development
A piece of sugar in your client-side developmentNicolas Blanco
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsMatt Follett
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
Introduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10genIntroduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10genMongoDB
 

Similar to A single language for backend and frontend from AngularJS to cloud with Claudia.js (20)

Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
 
Performances & SEO in AngularJS
Performances & SEO in AngularJSPerformances & SEO in AngularJS
Performances & SEO in AngularJS
 
First java-server-faces-tutorial-en
First java-server-faces-tutorial-enFirst java-server-faces-tutorial-en
First java-server-faces-tutorial-en
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
Rails vu d'un Javaiste
Rails vu d'un JavaisteRails vu d'un Javaiste
Rails vu d'un Javaiste
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorial
 
A piece of sugar in your client-side development
A piece of sugar in your client-side developmentA piece of sugar in your client-side development
A piece of sugar in your client-side development
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
XQuery Rocks
XQuery RocksXQuery Rocks
XQuery Rocks
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
Java Script Best Practices
Java Script Best PracticesJava Script Best Practices
Java Script Best Practices
 
Php introduction
Php introductionPhp introduction
Php introduction
 
Introduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10genIntroduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10gen
 
"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues
 

More from Corley S.r.l.

Aws rekognition - riconoscimento facciale
Aws rekognition  - riconoscimento faccialeAws rekognition  - riconoscimento facciale
Aws rekognition - riconoscimento faccialeCorley S.r.l.
 
AWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container servicesAWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container servicesCorley S.r.l.
 
AWSome day 2018 - API serverless with aws
AWSome day 2018  - API serverless with awsAWSome day 2018  - API serverless with aws
AWSome day 2018 - API serverless with awsCorley S.r.l.
 
AWSome day 2018 - database in cloud
AWSome day 2018 -  database in cloudAWSome day 2018 -  database in cloud
AWSome day 2018 - database in cloudCorley S.r.l.
 
Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing Corley S.r.l.
 
Apiconf - The perfect REST solution
Apiconf - The perfect REST solutionApiconf - The perfect REST solution
Apiconf - The perfect REST solutionCorley S.r.l.
 
Apiconf - Doc Driven Development
Apiconf - Doc Driven DevelopmentApiconf - Doc Driven Development
Apiconf - Doc Driven DevelopmentCorley S.r.l.
 
Authentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructuresAuthentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructuresCorley S.r.l.
 
Flexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructuresFlexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructuresCorley S.r.l.
 
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented applicationCloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented applicationCorley S.r.l.
 
AngularJS: Service, factory & provider
AngularJS: Service, factory & providerAngularJS: Service, factory & provider
AngularJS: Service, factory & providerCorley S.r.l.
 
The advantage of developing with TypeScript
The advantage of developing with TypeScript The advantage of developing with TypeScript
The advantage of developing with TypeScript Corley S.r.l.
 
Angular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deployAngular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deployCorley S.r.l.
 
Corley cloud angular in cloud
Corley cloud   angular in cloudCorley cloud   angular in cloud
Corley cloud angular in cloudCorley S.r.l.
 
Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2Corley S.r.l.
 
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS LambdaRead Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS LambdaCorley S.r.l.
 
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...Corley S.r.l.
 
Middleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkMiddleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkCorley S.r.l.
 
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015Corley S.r.l.
 

More from Corley S.r.l. (20)

Aws rekognition - riconoscimento facciale
Aws rekognition  - riconoscimento faccialeAws rekognition  - riconoscimento facciale
Aws rekognition - riconoscimento facciale
 
AWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container servicesAWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container services
 
AWSome day 2018 - API serverless with aws
AWSome day 2018  - API serverless with awsAWSome day 2018  - API serverless with aws
AWSome day 2018 - API serverless with aws
 
AWSome day 2018 - database in cloud
AWSome day 2018 -  database in cloudAWSome day 2018 -  database in cloud
AWSome day 2018 - database in cloud
 
Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing
 
Apiconf - The perfect REST solution
Apiconf - The perfect REST solutionApiconf - The perfect REST solution
Apiconf - The perfect REST solution
 
Apiconf - Doc Driven Development
Apiconf - Doc Driven DevelopmentApiconf - Doc Driven Development
Apiconf - Doc Driven Development
 
Authentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructuresAuthentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructures
 
Flexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructuresFlexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructures
 
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented applicationCloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
 
React vs Angular2
React vs Angular2React vs Angular2
React vs Angular2
 
AngularJS: Service, factory & provider
AngularJS: Service, factory & providerAngularJS: Service, factory & provider
AngularJS: Service, factory & provider
 
The advantage of developing with TypeScript
The advantage of developing with TypeScript The advantage of developing with TypeScript
The advantage of developing with TypeScript
 
Angular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deployAngular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deploy
 
Corley cloud angular in cloud
Corley cloud   angular in cloudCorley cloud   angular in cloud
Corley cloud angular in cloud
 
Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2
 
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS LambdaRead Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
 
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
 
Middleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkMiddleware PHP - A simple micro-framework
Middleware PHP - A simple micro-framework
 
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
 

Recently uploaded

Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 

Recently uploaded (20)

Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Odoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting ServiceOdoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting Service
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 

A single language for backend and frontend from AngularJS to cloud with Claudia.js

  • 1. A single language for Backend and Frontend: from AngularJS to Cloud AngularConf 2016 - Turin
  • 5. The REST webservice Decoupling Caching Stateless Quota planning (API Limits) Extendable Proxable etc...
  • 6. Planning GET    → /book Access to a list of books GET    → /book/:id Access to a single book POST   → /book Create a new book PATCH  → /book/:id Update a given book DELETE → /book/:id Delete a given book We can extends this using authentication header Authorization
  • 7. We have a simple API 'use strict' ;  angular.module( 'myApp').service( 'bookService' , function($http) {    return {      "list": function() {        return $http.get( "http://localhost:8085/book" );      },      ... // more methods     };  }); So we create a service Or we can create a provider to configure the URLs etc
  • 8. With a service we have a box with different methods bookService Get all books: list() Get a single book: get(:bookId) Create a book: create(:bookModel) ...
  • 9. The Book model is stable across our application {title: "the book title" , isbn: "12345678" , available : true} Or we resolve the book dependency with the book link (thanks to API uniquiness) {      name: "my favourites" ,      books: [ 1,2,3]  } So: $q.all(    [1,2,3].map(bookService.get)   ).then(function(books) {       //books is my favourites list with details   });
  • 10. Where the GET 'use strict' ;  angular.module( 'myApp').service( 'bookService' , function($http) {    return {      "get": function(id) {        return $http.get( "http://localhost:8085/book/" +id);      },      "list": function() {        return $http.get( "http://localhost:8085/book" );      },      ... // more methods     };  });
  • 12. A controller can request data angular.module( 'myApp')    .controller( 'MainCtrl' , function ($scope, bookService) {       $scope.books = [];       bookService.list().success(function(books) {         $scope.books = books;       });    }); Thanks to the controller we can pass our books to the view The scope the communication channel for the data
  • 13. Q: how can i verify the scope interface? R: via testing (unit testing)?
  • 14. Add a test case (1/2) describe( "MainCtrl" , function() {      beforeEach(module( 'myApp'));      beforeEach(inject(function ($controller, $rootScope, $httpBackend) {           scope = $rootScope.$new();           httpBackend = $httpBackend;           MainCtrl = $controller( 'MainCtrl' , {              $scope: scope,               // other mocks           });       }));      // continue...   });
  • 15. Add a test case (2/2) it('should attach a list of books to the scope' , function () {       // when someone require the "/book" endpoint reply with a valid response       httpBackend.whenGET( "http://localhost:8085/book" ).respond([         { id: 1, title: "This is a book" , isbn: "9835623" , available:  true },        { id: 2, title: "Another super book" , isbn: "9835624" , available:  true },        { id: 3, title: "A rare book to read" , isbn: "9835625" , available:  false }      ]);      // force the HTTP data resolution       httpBackend.flush();       // my expectation are that we books in the controller scope.       expect(scope.books.length).toBe( 3);      expect(scope.books.map((item) => item.title)).toEqual([         "This is a book" ,        "Another super book" ,        "A rare book to read"       ]);    }); $httpBackend act as a spy for HTTP requests
  • 17. The directive (web component) angular.module("myApp")    .directive( 'booksList' , function() {      return {        replace:  true,       templateUrl:  "app/views/books­list.html" ,        restrict:  "E",       scope: {           "books": "=",        },        link:  function() {},      };    });
  • 19. The book web component angular.module("myApp")    .directive( 'book', function() {      return {        replace:  true,       templateUrl:  "app/views/book.html" ,        restrict:  "E",       scope: {           "book": "=",        },        link:  function() {},      };    });
  • 21. Components testing (1/3) describe( "Books List" , function() {    var $compile,       $rootScope;     beforeEach(module( 'myApp'));    beforeEach(function() {       inject(function( _$compile_, _$rootScope _){        $compile =  _$compile_;        $rootScope =  _$rootScope _;      });    }); });
  • 22. Components testing (2/3) it("should expose our books" , function() {      $rootScope.books = [           { id:  1, title:  "This is a book" , isbn: "9835623" , available: true }           { id:  2, title:  "Another book" , isbn: "9835624" , available: true }           { id:  2, title:  "A secret book" , isbn: "9835625" , available: false }       ];      var element = $compile( '<books­list books="books"></books­list>' )($rootScope);       $rootScope.$digest();       var html = element.html();       expect(html).toContain( "This is a book" );      expect(html).toContain( "Another book" );      expect(html).not.toContain( "A secret book" );  });
  • 23. Components testing (3/3) Single book directive testing it("should expose a single book" , function() {      $rootScope.book = {           id:  1,          title:  "This is a single book" ,          isbn:  "9835623" ,          available: true       };      var element = $compile( '<book book="book"></book>' )($rootScope);       $rootScope.$digest();       var html = element.html();       expect(html).toContain( "This is a single book" );  });
  • 24. Add a book creation We need the create book service method We need another dummy web component We use the controller to save the book model
  • 25. The create method angular.module( 'myApp').service( 'bookService' , function($http) {     return {       "create": function(book) {         return $http.post( "http://localhost:8085/book" , book);      },      /* already implemented */       "get": function(id) {         return $http.get( "http://localhost:8085/book/" +id);      },      "list": function() {         return $http.get( "http://localhost:8085/book" );      },    };  });
  • 26. Dummy web component (1/3) angular.module("myApp")    .directive( 'bookForm' , function() {      return {        replace:  true,       templateUrl:  "app/views/book­form.html" ,        restrict:  "E",       scope: {           "book": "=",          "save": "=",        }      };    }); We can also skip the book model pass-through
  • 27. Dummy web component (2/3) <div>     <form>          Title: < input type="text" ng­model= "book.title"  /><br>          ISBN: < input type="text" ng­model= "book.isbn"  /><br>          Available: < input type="checkbox"  ng­model= "book.available"  /><br>          <button  type="button" ng­click= "save(book)" >Save</button>< br>      </form>  </div> Pay attention on ng-click that pass the book model
  • 28. Dummy web component (3/3) it("should expose a book", function(done) {    $rootScope.book = {};    $rootScope.save = function(book) {      expect(book.title).toEqual("Some text");      expect(book.isbn).toEqual("123456");      expect(book.available).toBe(true);      done();    };    var element = $compile('<book­form book="book" save="save"></book­form>')($rootScope);    $rootScope.$digest();    angular.element(element.find('input')[0]).val('Some text').triggerHandler('input');    angular.element(element.find('input')[1]).val('123456').triggerHandler('input');    angular.element(element.find('input')[2]).prop('checked', 'checked').triggerHandler('click');    $rootScope.$apply();    element.find('button')[0].click();  });
  • 29. So we have validated that the directive calls the save method But... Who have the save method? Controller + Book Service
  • 30. Previous Controller (1/2) angular.module( 'myApp')    .controller( 'MainCtrl' , function ($scope, bookService) {       $scope.book = {};       $scope.save = function(book) {         bookService.create(book).success(function(book) {           $scope.books = $scope.books.concat([book]);         });         $scope.book = {};       };      // old parts...       $scope.books = [];       bookService.list().success(function(books) {         $scope.books = books;       });    }); <book­form book="book" save="save"></book­form>
  • 31. Previous Controller (2/2) it('should create a new book', function () {     // something uses the save method     var book = {title: "This is a book", isbn: "9835623", available: true };    scope.save(book);    // then the backend should works as expected     httpBackend.whenGET("http://localhost:8085/book" ).respond([]);    httpBackend.whenPOST("http://localhost:8085/book" ).respond(      Object.assign({}, book, {id: 1})    );   httpBackend.flush();    expect(scope.book).toEqual({});    expect(scope.books.length).toBe(1);    expect(scope.books[0].id).toBe(1);    expect(scope.books[0].title).toEqual("This is a book");    expect(scope.books[0].isbn).toEqual("9835623");    expect(scope.books[0].available).toBe(true);  });
  • 32. We can develop the app but...
  • 33.
  • 34. How to deliver a scalable and cost-effective backend?
  • 35. ServerLess environments Those envs allows us to pay just for every single requests No requests? No payments! [more or less] No server maintenance (platform as a service)
  • 36. Amazon Web Services AWS API Gateway [✔] AWS Lambda [✔] AWS DynamoDB [✔] AWS SNS [ ] AWS SQS [ ] AWS CloudWatch [ ] so many services... [ ... ]
  • 37. API Gateway Thanks to API Gateway you can create/publish/maintain/monitor and secure APIs at any scale Essentially: with API Gateway you declare your APIs interfaces and delegate to another component (like Lambda, EC2, etc) the functionality
  • 38.
  • 39. Lambda is a compute service that can run the code on your behalf using AWS infrastructure
  • 40.
  • 41. Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.
  • 42.
  • 44. Dealing with ApiGateway + Lambda manually is tricky
  • 45. AWS releases a project: ServerLess that helps a lot the wiring https://github.com/serverless/serverless
  • 46. ServerLess is interesting but for REST API is not super simple to use imho...
  • 47. I prefer to use Claudia.js https://github.com/claudiajs/claudia
  • 48. Claudia expose a very simple interface var ApiBuilder =  require('claudia­api­builder' ),      api =  new ApiBuilder();   api.get('/hello', function (request, response)  {      return "Hello";  }); Similar to express or hapi
  • 49. You can use return codes and more features... api.post('/account' , function (request) {       return api.ApiResponse ({          name: "Walter",          surname: "Dal Mut"       }, 201);  });
  • 50. Claudia.js prepare the whole ApiGateway and Lambda configuration (with CORS) automatically for you claudia create        ­­name book­ module       ­­region eu­west­ 1       ­­api­module book       ­­config claudia­books.json It creates a new module book-module and store in claudia-books.json the Claudia.js con guration
  • 51. Claudia.js manage also all updates claudia update       ­­config claudia­ conf.json
  • 52. So we have to develop our API
  • 53. Thanks to Joi we can add data validation to our API var joi = require(' Joi'); var result = joi.object().keys({     id: joi.number().required(),     title: joi. string().min(1).required()   }).validate(request.body);   if (result.error) {       return new api. ApiResponse (result.error, 406); }  // continue Claudia.js manage JSON data automatically
  • 54. Claudia.js manage A+ Promises as a return element api.post( "/say­ok" , function(request)  {      var d = q.promise();       setTimeout( function() {          d.resolve( "OK");      }, 2000);      return d.promise;   });
  • 55. So... api.post( "/say­ok" , function(request)  {      // validation...       return db.save(request.body);   });
  • 56. For Node.js DynamoDB offers a "Document client" docClient =  new AWS.DynamoDB.DocumentClient({region:  "eu­west­1" });  docClient.put({     Item: {name:  "Walter", surname:  "Dal Mut" },    TableName: tableName   }).promise();   docClient.get( ...); // primary key   docClient.query( ...); // on a secondary index and/or primary key   docClient.scan( ...); // search without index (table scan) All methods have a A+ Promise implementation integrated
  • 57. Put all together api.post( "/book", function(request) {     var d = q.promise();     var result = joi.object().keys({       title: joi. string().min(1).required(),       isbn: joi. string().min(1).required(),       available: joi.boolean().required()     }).validate(request.body);     if (result.error) {       return new api. ApiResponse (result.error, 406);   }    var id = uuid.v4();     var item = Object.assign({}, {id: id}, request.body);     docClient.put({ Item: item, TableName : tableName}).promise().then(function() {       d.resolve(item);     });;    return d.promise;   }); Of course you can split all responsabilities to di erent components
  • 58. Thank you for listening If you are interested in workshops and/or training sessions feel free to contact info@corley.it Check out also our page for training at: corsi.corley.it Check out our corporate website: corley.it