SlideShare a Scribd company logo
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

Intro to ReactJS
Intro to ReactJSIntro to ReactJS
Intro to ReactJS
Harvard Web Working Group
 
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 Jasmine
Paulo 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 awesome
Andrew Hull
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentation
Sociable
 
Getting Started with jQuery
Getting Started with jQueryGetting Started with jQuery
Getting Started with jQuery
Akshay Mathur
 
Javascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JSJavascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JS
Min Ming Lo
 
jQuery Introduction
jQuery IntroductionjQuery Introduction
jQuery Introduction
Arwid Bancewicz
 
Developing iOS REST Applications
Developing iOS REST ApplicationsDeveloping iOS REST Applications
Developing iOS REST Applications
lmrei
 
JQuery introduction
JQuery introductionJQuery introduction
JQuery introduction
NexThoughts Technologies
 
Tools that get you laid
Tools that get you laidTools that get you laid
Tools that get you laid
Swizec Teller
 
React && React Native workshop
React && React Native workshopReact && React Native workshop
React && React Native workshop
Stacy Goh
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design Patterns
Ran 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 Widgets
velveeta_512
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
Elena Kolevska
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overview
jeresig
 
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
CalderaLearn
 
jQuery
jQueryjQuery
ReactJS for Beginners
ReactJS for BeginnersReactJS for Beginners
ReactJS for Beginners
Oswald Campesato
 

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 101
Samantha 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 MVC4
Yuriy Shapovalov
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorial
ice27
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02
Revath 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 Rails
Prateek 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 Models
Vincent 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 Stack
MongoDB
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
Jussi Pohjolainen
 
AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014
Spyros Ioakeimidis
 
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
Mike Subelsky
 
RapidApp - YAPC::NA 2014
RapidApp - YAPC::NA 2014RapidApp - YAPC::NA 2014
RapidApp - YAPC::NA 2014
Henry 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) Again
jonknapp
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
Vagmi Mudumbai
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
Joe Keeley
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with Rails
Basayel Said
 
SPA using Rails & Backbone
SPA using Rails & BackboneSPA using Rails & Backbone
SPA using Rails & Backbone
Ashan Fernando
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
SQL to NoSQL: Top 6 Questions
SQL to NoSQL: Top 6 QuestionsSQL to NoSQL: Top 6 Questions
SQL to NoSQL: Top 6 Questions
Mike 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: TDD
David Rodenas
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
David Rodenas
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
David Rodenas
 
TDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing TechniquesTDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing Techniques
David Rodenas
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving Testing
David Rodenas
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
David Rodenas
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
David Rodenas
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
David Rodenas
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniques
David 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
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
David Rodenas
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214
David Rodenas
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
David Rodenas
 
Vespres
VespresVespres
Vespres
David Rodenas
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
David Rodenas
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
David Rodenas
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
David 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 @drpicox
David 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 work
David Rodenas
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
David 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

怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
rtunex8r
 
Integrating Physical and Cybersecurity to Lower Risks in Healthcare!
Integrating Physical and Cybersecurity to Lower Risks in Healthcare!Integrating Physical and Cybersecurity to Lower Risks in Healthcare!
Integrating Physical and Cybersecurity to Lower Risks in Healthcare!
Alec Kassir cozmozone
 
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
3a0sd7z3
 
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
APNIC
 
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
thezot
 
How to make a complaint to the police for Social Media Fraud.pdf
How to make a complaint to the police for Social Media Fraud.pdfHow to make a complaint to the police for Social Media Fraud.pdf
How to make a complaint to the police for Social Media Fraud.pdf
Infosec train
 
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
APNIC
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
k4ncd0z
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
xjq03c34
 
Bengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal BrandingBengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal Branding
Tarandeep Singh
 
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
3a0sd7z3
 
HijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process HollowingHijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process Hollowing
Donato Onofri
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
Paul Walk
 
Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
davidjhones387
 

Recently uploaded (14)

怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
 
Integrating Physical and Cybersecurity to Lower Risks in Healthcare!
Integrating Physical and Cybersecurity to Lower Risks in Healthcare!Integrating Physical and Cybersecurity to Lower Risks in Healthcare!
Integrating Physical and Cybersecurity to Lower Risks in Healthcare!
 
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
 
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
 
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
 
How to make a complaint to the police for Social Media Fraud.pdf
How to make a complaint to the police for Social Media Fraud.pdfHow to make a complaint to the police for Social Media Fraud.pdf
How to make a complaint to the police for Social Media Fraud.pdf
 
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
 
Bengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal BrandingBengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal Branding
 
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
 
HijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process HollowingHijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process Hollowing
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
 
Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
 

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