SlideShare a Scribd company logo
1 of 77
Download to read offline
FRONT MVC
@DRPICOX
THINGS WRONG THAT I DID TO FIT THINGS IN SLIDES
DISCLAIMER
• Directives should use controller and bindToController
• Directives should never load resources, this should be done by
routes or under demand
• Use .factory to simplify and homogenize code

(not .service neither .value)
• In a previous talk I said that model was plain JS data, sorry 

(plain data is the form, but does not defines a model)
• Use better variable names
MVC - MODEL THE
GREAT FORGOTTEN
FRONT MVC
TYPICAL ANGULAR CODE
AS SEEN ON SOME DOCS
(AND FROM SOME BEGINNERS)
TYPICAL ANGULAR CODE
<APP-BOOKS-LIST>
app.component(‘appBooksList’, {
template: ‘…’,
controller($http) {
$http.get(‘/api/v1/books’).then(response => {
this.books = response.data;
});
},
});
TYPICAL ANGULAR CODE
<APP-SCI-FI-BOOKS-LIST>
app.component(‘appSciFiBooksList’, {
template: ‘…’,
controller($http) {
$http.get(‘/api/v1/books’).then(response => {
this.books = response.data.filter(isSciFi);
});
},
});
REFACTORING - SERVICE
THERE IS REPLICATED CODE
¡LET’S DO A SERVICE!
REFACTORING - SERVICE
booksService
app.service(‘booksService’, ($http) => {
this.getList = () => {
return $http.get(‘/api/v1/books’).then(function(response) {
return response.data;
});
};
});
Acquires the responsibility for:
• R1: Know the API context Url
• R2: Create a remote connection
• R3: Transform response into usable object
REFACTORING - SERVICE
<APP-BOOKS-LIST> & <APP-SCI-FI-BOOKS-LIST>
app.component(‘appBooksList’, {
template: ‘…’,
controller(booksService) {
booksService.getList().then(books => {
this.books = books;
});
},
});
app.component(‘appSciFiBooksList’, {
template: ‘…’,
controller(booksService) {
booksService.getList().then(books => {
this.books = books.filter(isSciFi);
});
},
});
PERFORMANCE - CACHING
OPS! WE ARE LOADING DATA TWICE
¡LET’S DO A CACHE!
PERFORMANCE - CACHING
booksService
Notice that:
• Repairs all directives at once
• Acquires one new responsibility (R4: manage cache)
app.service(‘booksService’, ($http) => {
this.getList = () => {
return $http.get(‘/api/v1/books’, {cache:true}).then(response => {
return response.data;
});
};
});
PERFORMANCE - CACHING
booksService
Notice that:
• Repairs all directives at once
• Acquires one new responsibility (R4: manage cache)
app.service(‘booksService’, ($http) => {
this.getList = () => {
if (!this.list) {
this.list = $http.get(‘/api/v1/books’).then(response => {
return response.data;
});
}
return this.list;
};
});
Alternate
NEW FEATURE - ONE BOOK
WE HAVE A VIEW THAT ONLY SHOWS ONE BOOK
NEW FEATURE - ONE BOOK
<APP-BOOK-VIEW BOOK-ID=“ID”>
app.component(‘appBookView’, {
template: ‘…’,
bindings: { bookId: ‘<‘ },
controller: function(booksService) {
booksService.get(this.bookId).then(book => { this.book = book; });
},
});
NEW FEATURE - ONE BOOK
booksService (step1)
Notice that:
• What about repeating loading of books (R4: manage cache)
app.service(‘booksService’, ($http) => {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true}).then(response => {
return response.data;
});
};
this.load = (id) => {
return $http.get(‘/api/v1/books/’+id).then(response => {
return response.data;
});
};
});
NEW FEATURE - ONE BOOK
booksService (step2)
• Uhmmmm… about R4… managing caches
app.service(‘booksService’, ($http) => {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true}).then(response => {
return response.data;
});
};
this.load = (id) => {
return $http.get(‘/api/v1/books/’+id, {cache:true}).then(response => {
return response.data;
});
};
});
NEW FEATURE - ONE BOOK
WE ARE LOADING TWICE THE SAME BOOK!
It happens when:
• Loading one book
• Loading all books
NEW FEATURE - ONE BOOK
OK… MAY BE IT’S OK LOAD TWICE
BUT NOT MORE TIMES
THE SAME BOOK
“We keep it simple…”
NEW FEATURE - UPDATE BOOK
WE HAVE A VIEW THAT MAKES AN UPDATE OF A BOOK
AND SHOWS THE CHANGES INTRODUCED BY API
NEW FEATURE - UPDATE BOOK
<APP-BOOK-UPDATE BOOK-ID=“ID”>
app.component(‘appBookUpdate’, {
template: ‘…’,
bindings: { bookId: ‘<‘, }
constructor(booksService) {
booksService.load(this).then(book => {
this.book = book;
});
this.update = () => {
booksService.update(this.book).then(updatedBook => {
this.book = updatedBook;
});
};
};
});
NEW FEATURE - ONE BOOK
booksService (step2)
• Uhmmmm… about R4… managing caches
app.service(‘booksService’, ($http) => {
this.getList = () => {
return $http.get(‘/api/v1/books’, {cache:true}).then(response => {
return response.data;
});
};
this.get = (id) => {
return $http.get(‘/api/v1/books/’+id, {cache:true})
.then(response => { return response.data; });
};
this.update = (book) => {
return $http.put(‘/api/v1/books/’+book.id)
.then(function(response) { return response.data; });
};
});
NEW FEATURE - UPDATE BOOK
SHIT!
NEW FEATURE - UPDATE BOOK
SHIT!
What about:
• Cache?
• What if we have a list side-by side, it is updated?
• What if we have view and update side-by-side?
NEW FEATURE - UPDATE BOOK
SHIT!
How to solve it?
• New services?
• Callbacks?
• RxJS?
• More caches?
• Events?
NEW FEATURE - UPDATE BOOK
WHAT IS THE REAL PROBLEM?
NEW FEATURE - UPDATE BOOK
WHAT IS THE REAL PROBLEM?
R4 (manage caches) is hidden another responsibility:
• Single source of true
We need a model!
WHAT A MODEL IS NOT?
• A model is not styles in the web
• A model is not objects in the scope
• A model is not objects stored in the browser (local,websql,…)
• A model are not instances of any sort of data
• A model is not plain data
SINGLE SOURCE OF TRUE
WHAT IS A MODEL?
• You can find your model
• There is only one instance for each “concept”

(all books with the same id are the same object)
• Models may be computed from other models
• It does not matters how many views do you have, 

all views use the same models

(as do services also)
That is something that ember programmers knows very well.
REFACTOR - ADD MODEL
Book
app.value(‘Book’, function Book(id) {
this.id = id;
this.isSciFi = function() { return !!this.tags.sciFi; };
this.takeData = function(bookData) {
angular.extend(this, bookData);
};
});
We discover new responsibilities:
• R5: update and extract information of a book
REFACTOR - ADD MODEL
booksDictionary
app.value(‘booksDictionary’, (Book) => {
this.list = []; this.map = {};
this.getOrCreate = (id) => {
var book = this.map[id];
if (!book) {
book = new Book(id);
this.list.push(book); this.list.map[id] = book;
};
return book;
};
this.takeDatas = (bookDatas) => {
bookInfos.forEach((bookData) => {
this.getOrCreate(bookData.id).takeData(bookData);
});
};
});
We discover new responsibilities:
• R6: manage book instances to avoid replicates
• R7: store books so anyone can access to them
Note that list

is also a model.
booksService (loadAll)
app.service(‘booksService’, (booksDictionary, $http) => {
this.getList = () => {
if (!this.list) {
this.list = $http.get(‘/api/v1/books’).then(response => {
booksDictionary.takeDatas(response.data);
return booksDictionary.list;
});
}
return this.list;
});
};
…
});
REFACTOR - ADD MODEL
getList returns always the same instance of list.
booksService (load)
app.service(‘booksService’, (booksDictionary, $http) => {
…
this.books = {};
this.load = (id) => {
if (!this.books[id]) {
this.books[id] = $http.get(‘/api/v1/books/’+id).then(response => {
var book = booksDictionary.getOrCreate(id);
book.takeData(reponse.data);
return book;
});
}
return this.books[id];
};
…
});
REFACTOR - ADD MODEL
Load(id) returns always the same instance of book for the same id.
And the instance will be contained by the list in getList.
booksService (update)
app.service(‘booksService’, (booksDictionary, $http) => {
…
this.update = (book) => {
var id = book.id;
this.books[id] = $http.put(‘/api/v1/books/’+id).then(response => {
var book = booksDictionary.getOrCreate(id);
book.takeData(response.data);
return book;
});
};
});
REFACTOR - ADD MODEL
Update returns always the same instance than get and getList,
regardless the input. And also updates the same instance.
three layers
REFACTOR - ADD MODEL
SERVICES
MODELS VIEWS
calls
updates
are $watched
NEW FEATURE - UPDATE BOOK
DONE!
NEW FEATURE - UPDATE BOOK
DONE?
What about Sci-Fi list?
• Is computed:

it has to be recomputed each time that a book o list changes

• A filter is expensive
• Watch a derive function is expensive
• Watch all books (aka $watch(,,true)) is expensive
NEW FEATURE - UPDATE BOOK
SHIT!
Solved in the next talk…
MVS: MVC IN
ANGULAR
FRONT MVC
three kinds of components
ORIGINAL MVC
CONTROLLERS
MODELS VIEWS
are listenedupdates
are observed
the truth
ORIGINAL MVC
MODELS VIEWS
knows and queries
are listenedupdates
are observed
knows and queries
CONTROLLERS
ORIGINAL MVC
SHIT!
ORIGINAL MVC
SHIT!
It is not as beautiful and easy as it seems.
May be it worked in ’78, with just few Kb…
and low complexity, but now…
FB comments about MVC
ARCHITECTURES VARIATIONS
https://youtu.be/nYkdrAPrdcw?t=10m20s
FB comments about MVC
ARCHITECTURES VARIATIONS
“MVC works pretty well
for small applications…
but it doesn’t make room
for new features.”
“Flux is a single direction data flow,
that avoids all the arrows
going on all directions
what makes really
hard to understand the system.”
FB comments about MVC
ARCHITECTURES VARIATIONS
“Let’s see a real good example: FB chat”
“How we get to the point, so we were annoying our
users so much the just they wanted us to fix chat?”
“The problems here were:
• The code has no structure
• It was very imperative, that makes it fragile
• It loose a lot of the original intend behind it, its hard to tell what it tries [to do]
• Add more features only gets this code larger
• We had our most annoying chat bug happen over and over
• We were always fixing some pretty good edge case, the whole system was fragile
• …
• This code becomes more fragile with the time.
• No member of the team wanted to touch it, they wanted to jump to any other bug.”
flux
ARCHITECTURES VARIATIONS
AND COMMUNITY ALSO CONTRIBUTED…
ARCHITECTURES VARIATIONS
redux
ARCHITECTURES VARIATIONS
cyclejs
ARCHITECTURES VARIATIONS
Key points are:
• Single direction flow
• Avoid imperative code
• Decoupled state from views
• Computed data consistency

(example: cart.price = ∑item.price * item.quantity)
ARCHITECTURES VARIATIONS
mvc
FROM MVC TO MVS
MODELS VIEWS
knows and queries
are listenedupdates
are observed
knows and queries
CONTROLLERS
mvc-angular
FROM MVC TO MVS
MODELS VIEWS
knows and queries
are $watched
CONTR
OLLERS
the same flow
FROM MVC TO MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
MVS RULES (I)
SERVICES
MODELS VIEWS
calls
updates
are $watched
• Views can call to services
• Services manages models
• Models are watched by views through $watch
• Views cannot modify models but temporary copies
• Each services has its own models and do not modify other
services models
Key points are:
• Single direction flow
• Avoid imperative code
• Decoupled state from views
• Computed data consistency

(example: sciFiBooks = books.filter(isSciFi))
ANGULAR MVS
SOLUTION FOR SCI-FI-BOOKS
• Create a new model for SciFiBooks
• Add a method getSciFiBooks() to bookService
• Recompute the list each time that an update() method is called
BUT!
SOLUTION FOR SCI-FI-BOOKS
BUT!
It does not scale.
¿What happens with more kind of books?
¿What happens with more complex data?
SOLUTION FOR SCI-FI-BOOKS
SOLUTION FOR SCI-FI-BOOKS
• We need a synchronization mechanism
• ex: events or observables
SOLUTION FOR COMPUTED VALUES
MODELS
• Models launch update: ex $broadcast(‘booksChanged’)
for angular1
fire events
SOLUTION FOR COMPUTED VALUES
MODELS
• Models launch update: ex $broadcast(‘booksChanged’)





• Rules:
• Each model has its own event (1 <-> 1)
• We do not pass any information (ex: previous and new value)
• Change event is fired by the Service that manages the model
• Events can be debounced (multiple collapsed in one)
rules
fire events
booksService (update)
app.service(‘booksService’, (booksDictionary, $http, $broadcast) => {
…
this.update = (book) => {
var id = book.id;
this.books[id] = $http.put(‘/api/v1/books/’+id).then(response => {
var book = booksDictionary.getOrCreate(id);
book.takeData(response.data);
$broadcast(‘booksChanged’);
return book;
});
};
});
SOLUTION FOR SCI-FI-BOOKS
<APP-SCI-FI-BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, {
template: ‘…’,
controller(booksService, $scope) {
getSciFiBooks();
$scope.$on(‘booksChanged’, getSciFiBooks);
function getSciFiBooks() {
booksService.getList().then(books => {
this.books = books.filter(isSciFi);
});
}
},
});
<APP-SCI-FI-BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, {
template: ‘…’,
controller(booksService, $scope) {
getSciFiBooks();
$scope.$on(‘booksChanged’, getSciFiBooks);
function getSciFiBooks() {
booksService.getList().then(books => {
this.books = books.filter(isSciFi);
});
}
},
});
It smells to a service function…
sciFiBooksService (update)
app.service(‘sciFiBooksService’, (booksService, $rootScope) => {
this.list = [];
this.getList = () => this.list;
updateList();
$rootScope.$on(‘booksChanged’, updateList);
function updateList() {
booksService.getList().then(books => {
angular.copy(books.filter(isSciFi), this.list);
$broadcast(‘sciFiChanged’);
});
}
});
SOLUTION FOR SCI-FI-BOOKS
<APP-SCI-FI-BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, {
template: ‘…’,
controller(sciFiBooksService, $scope) {
sciFiBooksService.getList().then(books => {
this.books = books;
});
},
});
<APP-SCI-FI-BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, {
template: ‘…’,
controller(booksService, $scope) {
getSciFiBooks();
$scope.$on(‘booksChanged’, getSciFiBooks);
function getSciFiBooks() {
booksService.getList().then(books => {
this.books = books.filter(isSciFi);
});
}
},
});
It smells to a service function…
Hierarchy
SOLUTION FOR SCI-FI-BOOKS
book
Service
sciFiBooks
Service
is listened
calls
Main Rule: no cycles of the arrow same color
Hierarchy
SOLUTION FOR SCI-FI-BOOKS
product
Service
Main Rule: no cycles of the arrow same color
showroom
Service
user
Service
cart
Service
shipping
Service
payment
method
Service
addresses
Service
MVS: MVC IN
ANGULAR
FRONT MVC
the same flow
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
the same flow
MVS
SERVICES
MODELS
VIEWS
calls
updates
are $watched
Dumb
Views
Smart
Views
BROWSER
uses listens
uses listens
the same flow
MVS
SERVICES
MODELS
VIEWS
calls
updates
are $watched
Dumb
Views
Smart
Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
the same flow
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb
Views
Smart
Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
State
Holders
State
Singletons
State
Dictionaries
CI
CI
CICICI
computed data flow
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb
Views
Smart
Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
State
Holders
State
Singletons
State
Dictionaries
CI
CI
CICICI
computed data flow
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb
Views
Smart
Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
State
Holders
State
Singletons
State
Dictionaries
CI
CI
CICICI
are listened
are listened
step by step
COMPUTED DATA FLOW
1. call
5. is fired
Books
Service
Books
Dictionary
Sci-Fi
Service
Sci-Fi
Dictionary
2. updates
3. fire $update
7. updates
8. fire $update
$UPDATE
EVENT MANAGER
4. fire $update
6. reads

More Related Content

What's hot

A single language for backend and frontend from AngularJS to cloud with Clau...
A single language for backend and frontend  from AngularJS to cloud with Clau...A single language for backend and frontend  from AngularJS to cloud with Clau...
A single language for backend and frontend from AngularJS to cloud with Clau...Walter Dal Mut
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesomeAndrew Hull
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationSociable
 
Getting Started with jQuery
Getting Started with jQueryGetting Started with jQuery
Getting Started with jQueryAkshay Mathur
 
Javascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JSJavascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JSMin Ming Lo
 
Developing iOS REST Applications
Developing iOS REST ApplicationsDeveloping iOS REST Applications
Developing iOS REST Applicationslmrei
 
Tools that get you laid
Tools that get you laidTools that get you laid
Tools that get you laidSwizec Teller
 
React && React Native workshop
React && React Native workshopReact && React Native workshop
React && React Native workshopStacy Goh
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsRan Mizrahi
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgetsvelveeta_512
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overviewjeresig
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCalderaLearn
 

What's hot (19)

Intro to ReactJS
Intro to ReactJSIntro to ReactJS
Intro to ReactJS
 
A single language for backend and frontend from AngularJS to cloud with Clau...
A single language for backend and frontend  from AngularJS to cloud with Clau...A single language for backend and frontend  from AngularJS to cloud with Clau...
A single language for backend and frontend from AngularJS to cloud with Clau...
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesome
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentation
 
Getting Started with jQuery
Getting Started with jQueryGetting Started with jQuery
Getting Started with jQuery
 
Javascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JSJavascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JS
 
jQuery Introduction
jQuery IntroductionjQuery Introduction
jQuery Introduction
 
Developing iOS REST Applications
Developing iOS REST ApplicationsDeveloping iOS REST Applications
Developing iOS REST Applications
 
JQuery introduction
JQuery introductionJQuery introduction
JQuery introduction
 
Tools that get you laid
Tools that get you laidTools that get you laid
Tools that get you laid
 
React && React Native workshop
React && React Native workshopReact && React Native workshop
React && React Native workshop
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design Patterns
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgets
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overview
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW Workshop
 
jQuery
jQueryjQuery
jQuery
 
ReactJS for Beginners
ReactJS for BeginnersReactJS for Beginners
ReactJS for Beginners
 

Similar to MVS: An angular MVC

REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4Yuriy Shapovalov
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorialice27
 
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
 
Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Revath S Kumar
 
Single Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and RailsSingle Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and RailsPrateek Dayal
 
Boosting Your Productivity, with Backbone & RactiveJS
Boosting Your Productivity, with Backbone & RactiveJS Boosting Your Productivity, with Backbone & RactiveJS
Boosting Your Productivity, with Backbone & RactiveJS Gabriel Gottgtroy Zigolis
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 ModelsVincent Chien
 
MongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN StackMongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN StackMongoDB
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
RapidApp - YAPC::NA 2014
RapidApp - YAPC::NA 2014RapidApp - YAPC::NA 2014
RapidApp - YAPC::NA 2014Henry Van Styn
 
From Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) AgainFrom Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) Againjonknapp
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Joe Keeley
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with RailsBasayel Said
 
SPA using Rails & Backbone
SPA using Rails & BackboneSPA using Rails & Backbone
SPA using Rails & BackboneAshan Fernando
 
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
 
SQL to NoSQL: Top 6 Questions
SQL to NoSQL: Top 6 QuestionsSQL to NoSQL: Top 6 Questions
SQL to NoSQL: Top 6 QuestionsMike Broberg
 

Similar to MVS: An angular MVC (20)

REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorial
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02
 
Single Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and RailsSingle Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and Rails
 
Boosting Your Productivity, with Backbone & RactiveJS
Boosting Your Productivity, with Backbone & RactiveJS Boosting Your Productivity, with Backbone & RactiveJS
Boosting Your Productivity, with Backbone & RactiveJS
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 Models
 
MongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN StackMongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN Stack
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
RapidApp - YAPC::NA 2014
RapidApp - YAPC::NA 2014RapidApp - YAPC::NA 2014
RapidApp - YAPC::NA 2014
 
From Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) AgainFrom Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) Again
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with Rails
 
SPA using Rails & Backbone
SPA using Rails & BackboneSPA using Rails & Backbone
SPA using Rails & Backbone
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
SQL to NoSQL: Top 6 Questions
SQL to NoSQL: Top 6 QuestionsSQL to NoSQL: Top 6 Questions
SQL to NoSQL: Top 6 Questions
 

More from David Rodenas

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDDavid Rodenas
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingDavid Rodenas
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesDavid Rodenas
 
TDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing TechniquesTDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing TechniquesDavid Rodenas
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingDavid Rodenas
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the WorldDavid Rodenas
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorDavid Rodenas
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataDavid Rodenas
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesDavid Rodenas
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)David Rodenas
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214David Rodenas
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for ProgrammersDavid Rodenas
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS ProgrammersDavid Rodenas
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersDavid Rodenas
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxDavid Rodenas
 
From high school to university and work
From high school to university and workFrom high school to university and work
From high school to university and workDavid Rodenas
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i EnginyeriaDavid Rodenas
 

More from David Rodenas (20)

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
 
TDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing TechniquesTDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing Techniques
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving Testing
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniques
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
Vespres
VespresVespres
Vespres
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
From high school to university and work
From high school to university and workFrom high school to university and work
From high school to university and work
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
 

Recently uploaded

DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024
DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024
DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024APNIC
 
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girlsstephieert
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...APNIC
 
Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Gram Darshan PPT cyber rural in villages of india
Gram Darshan PPT cyber rural  in villages of indiaGram Darshan PPT cyber rural  in villages of india
Gram Darshan PPT cyber rural in villages of indiaimessage0108
 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Servicesexy call girls service in goa
 
Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.soniya singh
 
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130  Available With RoomVIP Kolkata Call Girl Alambazar 👉 8250192130  Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Roomdivyansh0kumar0
 
Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...SofiyaSharma5
 
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...Sheetaleventcompany
 
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts serviceChennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts servicevipmodelshub1
 
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Delhi Call girls
 
AlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsAlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsThierry TROUIN ☁
 
How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)Damian Radcliffe
 
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebGDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebJames Anderson
 
AWS Community DAY Albertini-Ellan Cloud Security (1).pptx
AWS Community DAY Albertini-Ellan Cloud Security (1).pptxAWS Community DAY Albertini-Ellan Cloud Security (1).pptx
AWS Community DAY Albertini-Ellan Cloud Security (1).pptxellan12
 

Recently uploaded (20)

DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024
DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024
DDoS In Oceania and the Pacific, presented by Dave Phelan at NZNOG 2024
 
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girls
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
 
Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Ashram Chowk Delhi 💯Call Us 🔝8264348440🔝
 
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
 
Model Call Girl in Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in  Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in  Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
 
Gram Darshan PPT cyber rural in villages of india
Gram Darshan PPT cyber rural  in villages of indiaGram Darshan PPT cyber rural  in villages of india
Gram Darshan PPT cyber rural in villages of india
 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
 
Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Call Now ☎ 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
 
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130  Available With RoomVIP Kolkata Call Girl Alambazar 👉 8250192130  Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
 
Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida ✔️☆9289244007✔️☆ Female E...
 
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
 
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts serviceChennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
 
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
 
AlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsAlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with Flows
 
How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)
 
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebGDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
 
AWS Community DAY Albertini-Ellan Cloud Security (1).pptx
AWS Community DAY Albertini-Ellan Cloud Security (1).pptxAWS Community DAY Albertini-Ellan Cloud Security (1).pptx
AWS Community DAY Albertini-Ellan Cloud Security (1).pptx
 

MVS: An angular MVC

  • 2. THINGS WRONG THAT I DID TO FIT THINGS IN SLIDES DISCLAIMER • Directives should use controller and bindToController • Directives should never load resources, this should be done by routes or under demand • Use .factory to simplify and homogenize code
 (not .service neither .value) • In a previous talk I said that model was plain JS data, sorry 
 (plain data is the form, but does not defines a model) • Use better variable names
  • 3. MVC - MODEL THE GREAT FORGOTTEN FRONT MVC
  • 4. TYPICAL ANGULAR CODE AS SEEN ON SOME DOCS (AND FROM SOME BEGINNERS)
  • 5. TYPICAL ANGULAR CODE <APP-BOOKS-LIST> app.component(‘appBooksList’, { template: ‘…’, controller($http) { $http.get(‘/api/v1/books’).then(response => { this.books = response.data; }); }, });
  • 6. TYPICAL ANGULAR CODE <APP-SCI-FI-BOOKS-LIST> app.component(‘appSciFiBooksList’, { template: ‘…’, controller($http) { $http.get(‘/api/v1/books’).then(response => { this.books = response.data.filter(isSciFi); }); }, });
  • 7. REFACTORING - SERVICE THERE IS REPLICATED CODE ¡LET’S DO A SERVICE!
  • 8. REFACTORING - SERVICE booksService app.service(‘booksService’, ($http) => { this.getList = () => { return $http.get(‘/api/v1/books’).then(function(response) { return response.data; }); }; }); Acquires the responsibility for: • R1: Know the API context Url • R2: Create a remote connection • R3: Transform response into usable object
  • 9. REFACTORING - SERVICE <APP-BOOKS-LIST> & <APP-SCI-FI-BOOKS-LIST> app.component(‘appBooksList’, { template: ‘…’, controller(booksService) { booksService.getList().then(books => { this.books = books; }); }, }); app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService) { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); }, });
  • 10. PERFORMANCE - CACHING OPS! WE ARE LOADING DATA TWICE ¡LET’S DO A CACHE!
  • 11. PERFORMANCE - CACHING booksService Notice that: • Repairs all directives at once • Acquires one new responsibility (R4: manage cache) app.service(‘booksService’, ($http) => { this.getList = () => { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; });
  • 12. PERFORMANCE - CACHING booksService Notice that: • Repairs all directives at once • Acquires one new responsibility (R4: manage cache) app.service(‘booksService’, ($http) => { this.getList = () => { if (!this.list) { this.list = $http.get(‘/api/v1/books’).then(response => { return response.data; }); } return this.list; }; }); Alternate
  • 13. NEW FEATURE - ONE BOOK WE HAVE A VIEW THAT ONLY SHOWS ONE BOOK
  • 14. NEW FEATURE - ONE BOOK <APP-BOOK-VIEW BOOK-ID=“ID”> app.component(‘appBookView’, { template: ‘…’, bindings: { bookId: ‘<‘ }, controller: function(booksService) { booksService.get(this.bookId).then(book => { this.book = book; }); }, });
  • 15. NEW FEATURE - ONE BOOK booksService (step1) Notice that: • What about repeating loading of books (R4: manage cache) app.service(‘booksService’, ($http) => { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; this.load = (id) => { return $http.get(‘/api/v1/books/’+id).then(response => { return response.data; }); }; });
  • 16. NEW FEATURE - ONE BOOK booksService (step2) • Uhmmmm… about R4… managing caches app.service(‘booksService’, ($http) => { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; this.load = (id) => { return $http.get(‘/api/v1/books/’+id, {cache:true}).then(response => { return response.data; }); }; });
  • 17. NEW FEATURE - ONE BOOK WE ARE LOADING TWICE THE SAME BOOK! It happens when: • Loading one book • Loading all books
  • 18. NEW FEATURE - ONE BOOK OK… MAY BE IT’S OK LOAD TWICE BUT NOT MORE TIMES THE SAME BOOK “We keep it simple…”
  • 19. NEW FEATURE - UPDATE BOOK WE HAVE A VIEW THAT MAKES AN UPDATE OF A BOOK AND SHOWS THE CHANGES INTRODUCED BY API
  • 20. NEW FEATURE - UPDATE BOOK <APP-BOOK-UPDATE BOOK-ID=“ID”> app.component(‘appBookUpdate’, { template: ‘…’, bindings: { bookId: ‘<‘, } constructor(booksService) { booksService.load(this).then(book => { this.book = book; }); this.update = () => { booksService.update(this.book).then(updatedBook => { this.book = updatedBook; }); }; }; });
  • 21. NEW FEATURE - ONE BOOK booksService (step2) • Uhmmmm… about R4… managing caches app.service(‘booksService’, ($http) => { this.getList = () => { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; this.get = (id) => { return $http.get(‘/api/v1/books/’+id, {cache:true}) .then(response => { return response.data; }); }; this.update = (book) => { return $http.put(‘/api/v1/books/’+book.id) .then(function(response) { return response.data; }); }; });
  • 22. NEW FEATURE - UPDATE BOOK SHIT!
  • 23. NEW FEATURE - UPDATE BOOK SHIT! What about: • Cache? • What if we have a list side-by side, it is updated? • What if we have view and update side-by-side?
  • 24. NEW FEATURE - UPDATE BOOK SHIT! How to solve it? • New services? • Callbacks? • RxJS? • More caches? • Events?
  • 25. NEW FEATURE - UPDATE BOOK WHAT IS THE REAL PROBLEM?
  • 26. NEW FEATURE - UPDATE BOOK WHAT IS THE REAL PROBLEM? R4 (manage caches) is hidden another responsibility: • Single source of true We need a model!
  • 27. WHAT A MODEL IS NOT? • A model is not styles in the web • A model is not objects in the scope • A model is not objects stored in the browser (local,websql,…) • A model are not instances of any sort of data • A model is not plain data
  • 28. SINGLE SOURCE OF TRUE WHAT IS A MODEL? • You can find your model • There is only one instance for each “concept”
 (all books with the same id are the same object) • Models may be computed from other models • It does not matters how many views do you have, 
 all views use the same models
 (as do services also) That is something that ember programmers knows very well.
  • 29. REFACTOR - ADD MODEL Book app.value(‘Book’, function Book(id) { this.id = id; this.isSciFi = function() { return !!this.tags.sciFi; }; this.takeData = function(bookData) { angular.extend(this, bookData); }; }); We discover new responsibilities: • R5: update and extract information of a book
  • 30. REFACTOR - ADD MODEL booksDictionary app.value(‘booksDictionary’, (Book) => { this.list = []; this.map = {}; this.getOrCreate = (id) => { var book = this.map[id]; if (!book) { book = new Book(id); this.list.push(book); this.list.map[id] = book; }; return book; }; this.takeDatas = (bookDatas) => { bookInfos.forEach((bookData) => { this.getOrCreate(bookData.id).takeData(bookData); }); }; }); We discover new responsibilities: • R6: manage book instances to avoid replicates • R7: store books so anyone can access to them Note that list
 is also a model.
  • 31. booksService (loadAll) app.service(‘booksService’, (booksDictionary, $http) => { this.getList = () => { if (!this.list) { this.list = $http.get(‘/api/v1/books’).then(response => { booksDictionary.takeDatas(response.data); return booksDictionary.list; }); } return this.list; }); }; … }); REFACTOR - ADD MODEL getList returns always the same instance of list.
  • 32. booksService (load) app.service(‘booksService’, (booksDictionary, $http) => { … this.books = {}; this.load = (id) => { if (!this.books[id]) { this.books[id] = $http.get(‘/api/v1/books/’+id).then(response => { var book = booksDictionary.getOrCreate(id); book.takeData(reponse.data); return book; }); } return this.books[id]; }; … }); REFACTOR - ADD MODEL Load(id) returns always the same instance of book for the same id. And the instance will be contained by the list in getList.
  • 33. booksService (update) app.service(‘booksService’, (booksDictionary, $http) => { … this.update = (book) => { var id = book.id; this.books[id] = $http.put(‘/api/v1/books/’+id).then(response => { var book = booksDictionary.getOrCreate(id); book.takeData(response.data); return book; }); }; }); REFACTOR - ADD MODEL Update returns always the same instance than get and getList, regardless the input. And also updates the same instance.
  • 34. three layers REFACTOR - ADD MODEL SERVICES MODELS VIEWS calls updates are $watched
  • 35. NEW FEATURE - UPDATE BOOK DONE!
  • 36. NEW FEATURE - UPDATE BOOK DONE? What about Sci-Fi list? • Is computed:
 it has to be recomputed each time that a book o list changes
 • A filter is expensive • Watch a derive function is expensive • Watch all books (aka $watch(,,true)) is expensive
  • 37. NEW FEATURE - UPDATE BOOK SHIT! Solved in the next talk…
  • 39. three kinds of components ORIGINAL MVC CONTROLLERS MODELS VIEWS are listenedupdates are observed
  • 40. the truth ORIGINAL MVC MODELS VIEWS knows and queries are listenedupdates are observed knows and queries CONTROLLERS
  • 42. ORIGINAL MVC SHIT! It is not as beautiful and easy as it seems. May be it worked in ’78, with just few Kb… and low complexity, but now…
  • 43. FB comments about MVC ARCHITECTURES VARIATIONS https://youtu.be/nYkdrAPrdcw?t=10m20s
  • 44. FB comments about MVC ARCHITECTURES VARIATIONS “MVC works pretty well for small applications… but it doesn’t make room for new features.” “Flux is a single direction data flow, that avoids all the arrows going on all directions what makes really hard to understand the system.”
  • 45. FB comments about MVC ARCHITECTURES VARIATIONS “Let’s see a real good example: FB chat” “How we get to the point, so we were annoying our users so much the just they wanted us to fix chat?” “The problems here were: • The code has no structure • It was very imperative, that makes it fragile • It loose a lot of the original intend behind it, its hard to tell what it tries [to do] • Add more features only gets this code larger • We had our most annoying chat bug happen over and over • We were always fixing some pretty good edge case, the whole system was fragile • … • This code becomes more fragile with the time. • No member of the team wanted to touch it, they wanted to jump to any other bug.”
  • 47. AND COMMUNITY ALSO CONTRIBUTED… ARCHITECTURES VARIATIONS
  • 50. Key points are: • Single direction flow • Avoid imperative code • Decoupled state from views • Computed data consistency
 (example: cart.price = ∑item.price * item.quantity) ARCHITECTURES VARIATIONS
  • 51. mvc FROM MVC TO MVS MODELS VIEWS knows and queries are listenedupdates are observed knows and queries CONTROLLERS
  • 52. mvc-angular FROM MVC TO MVS MODELS VIEWS knows and queries are $watched CONTR OLLERS
  • 53. the same flow FROM MVC TO MVS SERVICES MODELS VIEWS calls updates are $watched
  • 54. MVS RULES (I) SERVICES MODELS VIEWS calls updates are $watched • Views can call to services • Services manages models • Models are watched by views through $watch • Views cannot modify models but temporary copies • Each services has its own models and do not modify other services models
  • 55. Key points are: • Single direction flow • Avoid imperative code • Decoupled state from views • Computed data consistency
 (example: sciFiBooks = books.filter(isSciFi)) ANGULAR MVS
  • 56. SOLUTION FOR SCI-FI-BOOKS • Create a new model for SciFiBooks • Add a method getSciFiBooks() to bookService • Recompute the list each time that an update() method is called
  • 58. BUT! It does not scale. ¿What happens with more kind of books? ¿What happens with more complex data? SOLUTION FOR SCI-FI-BOOKS
  • 59. SOLUTION FOR SCI-FI-BOOKS • We need a synchronization mechanism • ex: events or observables
  • 60. SOLUTION FOR COMPUTED VALUES MODELS • Models launch update: ex $broadcast(‘booksChanged’) for angular1 fire events
  • 61. SOLUTION FOR COMPUTED VALUES MODELS • Models launch update: ex $broadcast(‘booksChanged’)
 
 
 • Rules: • Each model has its own event (1 <-> 1) • We do not pass any information (ex: previous and new value) • Change event is fired by the Service that manages the model • Events can be debounced (multiple collapsed in one) rules fire events
  • 62. booksService (update) app.service(‘booksService’, (booksDictionary, $http, $broadcast) => { … this.update = (book) => { var id = book.id; this.books[id] = $http.put(‘/api/v1/books/’+id).then(response => { var book = booksDictionary.getOrCreate(id); book.takeData(response.data); $broadcast(‘booksChanged’); return book; }); }; }); SOLUTION FOR SCI-FI-BOOKS
  • 63. <APP-SCI-FI-BOOKS-LIST> (update) SOLUTION FOR SCI-FI-BOOKS app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService, $scope) { getSciFiBooks(); $scope.$on(‘booksChanged’, getSciFiBooks); function getSciFiBooks() { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); } }, });
  • 64. <APP-SCI-FI-BOOKS-LIST> (update) SOLUTION FOR SCI-FI-BOOKS app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService, $scope) { getSciFiBooks(); $scope.$on(‘booksChanged’, getSciFiBooks); function getSciFiBooks() { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); } }, }); It smells to a service function…
  • 65. sciFiBooksService (update) app.service(‘sciFiBooksService’, (booksService, $rootScope) => { this.list = []; this.getList = () => this.list; updateList(); $rootScope.$on(‘booksChanged’, updateList); function updateList() { booksService.getList().then(books => { angular.copy(books.filter(isSciFi), this.list); $broadcast(‘sciFiChanged’); }); } }); SOLUTION FOR SCI-FI-BOOKS
  • 66. <APP-SCI-FI-BOOKS-LIST> (update) SOLUTION FOR SCI-FI-BOOKS app.component(‘appSciFiBooksList’, { template: ‘…’, controller(sciFiBooksService, $scope) { sciFiBooksService.getList().then(books => { this.books = books; }); }, });
  • 67. <APP-SCI-FI-BOOKS-LIST> (update) SOLUTION FOR SCI-FI-BOOKS app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService, $scope) { getSciFiBooks(); $scope.$on(‘booksChanged’, getSciFiBooks); function getSciFiBooks() { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); } }, }); It smells to a service function…
  • 68. Hierarchy SOLUTION FOR SCI-FI-BOOKS book Service sciFiBooks Service is listened calls Main Rule: no cycles of the arrow same color
  • 69. Hierarchy SOLUTION FOR SCI-FI-BOOKS product Service Main Rule: no cycles of the arrow same color showroom Service user Service cart Service shipping Service payment method Service addresses Service
  • 71. the same flow MVS SERVICES MODELS VIEWS calls updates are $watched
  • 72. the same flow MVS SERVICES MODELS VIEWS calls updates are $watched Dumb Views Smart Views BROWSER uses listens uses listens
  • 73. the same flow MVS SERVICES MODELS VIEWS calls updates are $watched Dumb Views Smart Views BROWSER uses listens uses listens Services Remotes Storages callscalls
  • 74. the same flow MVS SERVICES MODELS VIEWS calls updates are $watched Dumb Views Smart Views BROWSER uses listens uses listens Services Remotes Storages callscalls State Holders State Singletons State Dictionaries CI CI CICICI
  • 75. computed data flow MVS SERVICES MODELS VIEWS calls updates are $watched Dumb Views Smart Views BROWSER uses listens uses listens Services Remotes Storages callscalls State Holders State Singletons State Dictionaries CI CI CICICI
  • 76. computed data flow MVS SERVICES MODELS VIEWS calls updates are $watched Dumb Views Smart Views BROWSER uses listens uses listens Services Remotes Storages callscalls State Holders State Singletons State Dictionaries CI CI CICICI are listened are listened
  • 77. step by step COMPUTED DATA FLOW 1. call 5. is fired Books Service Books Dictionary Sci-Fi Service Sci-Fi Dictionary 2. updates 3. fire $update 7. updates 8. fire $update $UPDATE EVENT MANAGER 4. fire $update 6. reads