SlideShare a Scribd company logo
1 of 37
Download to read offline
MVC - MODEL THE
GREAT FORGOTTEN
@DRPICOX
TYPICAL ANGULAR CODE
AS SEEN ON SOME DOCS
(AND FROM SOME BEGINNERS)
TYPICAL ANGULAR CODE
<APP-BOOKS-LIST>
app.directive(‘appBooksList’, function($http) {
return function link(scope) {
$http.get(‘/api/v1/books’).then(function(response) {
scope.books = response.data;
});
};
});
TYPICAL ANGULAR CODE
<APP-SCI-FI-BOOKS-LIST>
app.directive(‘appSciFiBooksList’, function($http) {
return function link(scope) {
$http.get(‘/api/v1/books’).then(function(response) {
scope.books = response.data.filter(isSciFi);
});
};
});
REFACTORING - SERVICE
THERE IS REPLICATED CODE
¡LET’S DO A SERVICE!
REFACTORING - SERVICE
booksService
app.service(‘booksService’, function($http) {
this.loadAll = function() {
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.directive(‘appBooksList’, function(booksService) {
return function link(scope) {
booksService.loadAll().then(function(books) {
scope.books = books;
});
};
});
app.directive(‘appSciFiBooksList’, function(booksService) {
return function link(scope) {
booksService.loadAll().then(function(books) {
scope.books = books;
});
};
});
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’, function($http) {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) {
return response.data;
});
};
});
NEW FEATURE - ONE BOOK
WE HAVE A VIEW THAT ONLY SHOWS ONE BOOK
NEW FEATURE - ONE BOOK
<APP-BOOK-VIEW BOOK-ID=“ID”>
app.directive(‘appBookView’, function(booksService) {
return function link(scope, element, attrs) {
booksService.load(attrs.bookId).then(function(book) {
scope.book = book;
});
};
});
NEW FEATURE - ONE BOOK
booksService (step1)
Notice that:
• What about repeating loading of books (R4: manage cache)
app.service(‘booksService’, function($http) {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true).then(function(response) {
return response.data;
});
};
this.load = function(id) {
return $http.get(‘/api/v1/books/’+id).then(function(response) {
return response.data;
});
};
});
NEW FEATURE - ONE BOOK
booksService (step2)
• Uhmmmm… about R4… managing caches
app.service(‘booksService’, function($http) {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) {
return response.data;
});
};
this.load = function(id) {
return $http.get(‘/api/v1/books/’+id, {cache:true})
.then(function(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.directive(‘appBookUpdate’, function(booksService) {
return function link(scope, element, attrs) {
booksService.load(attrs.bookId).then(function(book) {
scope.book = book;
});
scope.update = function() {
booksService.update(scope.book).then(function(updatedBook) {
scope.book = updatedBook;
});
};
};
});
NEW FEATURE - ONE BOOK
booksService (step2)
• Uhmmmm… about R4… managing caches
app.service(‘booksService’, function($http) {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) {
return response.data;
});
};
this.load = function(id) {
return $http.get(‘/api/v1/books/’+id, {cache:true})
.then(function(response) { return response.data; });
};
this.update = function(book) {
return $http.put(‘/api/v1/books/’+id, {cache:true})
.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.take = function(info) { angular.extend(this, info); };
});
We discover new responsibilities:
• R5: update and extract information of a book
REFACTOR - ADD MODEL
bookDictionary
app.value(‘bookDictionary’, function(Book) {
this.list = []; this.map = {};
this.getOrCreate() = function(id) {
var book = this.map[id];
if (!book) {
book = new Book(id);
this.list.push(book); this.list.map[id] = book;
};
return book;
};
this.takeAll = function(bookInfos) {
bookInfos.forEach(function(bookInfo) {
this.getOrCreate(bookInfo.id).take(bookInfo);
}, this);
};
});
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
• Uhmmmm… it has caches…
• Uhmmmm… it must interact with models
• Uhmmmm… it must speak api

Too many responsibilities!
REFACTOR - ADD MODEL
app.service(‘booksService’, function($http) {
this.loadAll = function() {
return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) {
return response.data;
});
};
this.load = function(id) {
return $http.get(‘/api/v1/books/’+id, {cache:true})
.then(function(response) { return response.data; });
};
this.update = function(book) {
return $http.put(‘/api/v1/books/’+id, {cache:true})
.then(function(response) { return response.data; });
};
});
booksRemote
app.service(‘booksRemote’, function($http) {
this.retrieveAll = function() {
return $http.get(‘/api/v1/books’,{cache:true}).then(_getData);
};
this.retrieve = function(id) {
return $http.get(‘/api/v1/books/’+id,{cache:true}).then(_getData);
};
this.store = function(book) {
return $http.put(‘/api/v1/books/’+id,{cache:true}).then(_getData);
};
function _getData(response) { return result.data; }
});
REFACTOR - ADD MODEL
Acquires the responsibility for:
• R1: Know the API context Url
• R2: Create a remote connection
• R3: Transform response into usable object
• R4: Manage cache (¿when data must be refreshed?)
booksService (loadAll)
app.service(‘booksService’, function(booksDictionary, booksRemote) {
this.loadAll = function() {
return booksRemote.retrieveAll().then(function(books) {
booksDictionary.takeAll(books);
return booksDictionary.list;
});
};
…
});
REFACTOR - ADD MODEL
LoadAll returns always the same instance of list.
booksService (load)
app.service(‘booksService’, function(booksDictionary, booksRemote) {
…
this.load = function(id) {
return booksRemote.retrieve(id).then(function(bookInfo) {
var book = booksDictionary.getOrCreate(id);
book.take(bookInfo);
return book;
});
};
…
});
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 loadAll.
booksService (update)
app.service(‘booksService’, function(booksDictionary, booksRemote) {
…
this.update = function(book) {
return booksRemote.update(book).then(function(bookInfo) {
var book = booksDictionary.getOrCreate(id);
book.take(bookInfo);
return book;
});
};
});
REFACTOR - ADD MODEL
Update returns always the same instance than load and loadAll,
regardless the input. And also updates the same instance.
three layers
REFACTOR - ADD MODEL
SERVICES
MODELS VIEWS
calls
calls
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 next talk!
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
• I usually like to use .factory to simplify and homogenize code

(over .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

More Related Content

What's hot

jQuery - Chapter 5 - Ajax
jQuery - Chapter 5 -  AjaxjQuery - Chapter 5 -  Ajax
jQuery - Chapter 5 - AjaxWebStackAcademy
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module PatternsNicholas Jansma
 
Simpler Core Data with RubyMotion
Simpler Core Data with RubyMotionSimpler Core Data with RubyMotion
Simpler Core Data with RubyMotionStefan Haflidason
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesPeter Friese
 
Learn javascript easy steps
Learn javascript easy stepsLearn javascript easy steps
Learn javascript easy stepsprince Loffar
 
jQuery - Chapter 4 - DOM Handling
jQuery - Chapter 4 - DOM Handling jQuery - Chapter 4 - DOM Handling
jQuery - Chapter 4 - DOM Handling WebStackAcademy
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - ComponentsVisual Engineering
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Codemotion
 
React && React Native workshop
React && React Native workshopReact && React Native workshop
React && React Native workshopStacy Goh
 
JavaScript and jQuery Basics
JavaScript and jQuery BasicsJavaScript and jQuery Basics
JavaScript and jQuery BasicsKaloyan Kosev
 
How to write easy-to-test JavaScript
How to write easy-to-test JavaScriptHow to write easy-to-test JavaScript
How to write easy-to-test JavaScriptYnon Perek
 
Getting Started with jQuery
Getting Started with jQueryGetting Started with jQuery
Getting Started with jQueryAkshay Mathur
 
Introduction to Jquery
Introduction to Jquery Introduction to Jquery
Introduction to Jquery Tajendar Arora
 
[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert Pankowiecki[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert PankowieckiPROIDEA
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Codemotion
 

What's hot (20)

jQuery - Chapter 5 - Ajax
jQuery - Chapter 5 -  AjaxjQuery - Chapter 5 -  Ajax
jQuery - Chapter 5 - Ajax
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module Patterns
 
Simpler Core Data with RubyMotion
Simpler Core Data with RubyMotionSimpler Core Data with RubyMotion
Simpler Core Data with RubyMotion
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroes
 
Learn javascript easy steps
Learn javascript easy stepsLearn javascript easy steps
Learn javascript easy steps
 
jQuery - Chapter 4 - DOM Handling
jQuery - Chapter 4 - DOM Handling jQuery - Chapter 4 - DOM Handling
jQuery - Chapter 4 - DOM Handling
 
Rails3 changesets
Rails3 changesetsRails3 changesets
Rails3 changesets
 
Workshop 17: EmberJS parte II
Workshop 17: EmberJS parte IIWorkshop 17: EmberJS parte II
Workshop 17: EmberJS parte II
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
 
jQuery Introduction
jQuery IntroductionjQuery Introduction
jQuery Introduction
 
JavaScript
JavaScriptJavaScript
JavaScript
 
React && React Native workshop
React && React Native workshopReact && React Native workshop
React && React Native workshop
 
jQuery
jQueryjQuery
jQuery
 
JavaScript and jQuery Basics
JavaScript and jQuery BasicsJavaScript and jQuery Basics
JavaScript and jQuery Basics
 
How to write easy-to-test JavaScript
How to write easy-to-test JavaScriptHow to write easy-to-test JavaScript
How to write easy-to-test JavaScript
 
Getting Started with jQuery
Getting Started with jQueryGetting Started with jQuery
Getting Started with jQuery
 
Introduction to Jquery
Introduction to Jquery Introduction to Jquery
Introduction to Jquery
 
[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert Pankowiecki[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert Pankowiecki
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
 

Similar to Mvc - Model: the great forgotten

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
 
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
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto UniversityAngular.js Primer in Aalto University
Angular.js Primer in Aalto UniversitySC5.io
 
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...Corley S.r.l.
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
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
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
WordPress as the Backbone(.js)
WordPress as the Backbone(.js)WordPress as the Backbone(.js)
WordPress as the Backbone(.js)Beau Lebens
 
Flask & Flask-restx
Flask & Flask-restxFlask & Flask-restx
Flask & Flask-restxammaraslam18
 
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017Codemotion
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 ModelsVincent Chien
 
Tools that get you laid
Tools that get you laidTools that get you laid
Tools that get you laidSwizec Teller
 
Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJavaJobaer Chowdhury
 
iOS Swift application architecture
iOS Swift application architectureiOS Swift application architecture
iOS Swift application architectureRomain Rochegude
 
Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Revath S Kumar
 

Similar to Mvc - Model: the great forgotten (20)

Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
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
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto UniversityAngular.js Primer in Aalto University
Angular.js Primer in Aalto University
 
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...
 
ParisJS #10 : RequireJS
ParisJS #10 : RequireJSParisJS #10 : RequireJS
ParisJS #10 : RequireJS
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
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
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
WordPress as the Backbone(.js)
WordPress as the Backbone(.js)WordPress as the Backbone(.js)
WordPress as the Backbone(.js)
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Flask & Flask-restx
Flask & Flask-restxFlask & Flask-restx
Flask & Flask-restx
 
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 Models
 
RESTful API in Node.pdf
RESTful API in Node.pdfRESTful API in Node.pdf
RESTful API in Node.pdf
 
Tools that get you laid
Tools that get you laidTools that get you laid
Tools that get you laid
 
Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJava
 
iOS Swift application architecture
iOS Swift application architectureiOS Swift application architecture
iOS Swift application architecture
 
Rails vu d'un Javaiste
Rails vu d'un JavaisteRails vu d'un Javaiste
Rails vu d'un Javaiste
 
Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02Prateek dayal backbonerails-110528024926-phpapp02
Prateek dayal backbonerails-110528024926-phpapp02
 

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

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 

Recently uploaded (20)

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 

Mvc - Model: the great forgotten

  • 1. MVC - MODEL THE GREAT FORGOTTEN @DRPICOX
  • 2. TYPICAL ANGULAR CODE AS SEEN ON SOME DOCS (AND FROM SOME BEGINNERS)
  • 3. TYPICAL ANGULAR CODE <APP-BOOKS-LIST> app.directive(‘appBooksList’, function($http) { return function link(scope) { $http.get(‘/api/v1/books’).then(function(response) { scope.books = response.data; }); }; });
  • 4. TYPICAL ANGULAR CODE <APP-SCI-FI-BOOKS-LIST> app.directive(‘appSciFiBooksList’, function($http) { return function link(scope) { $http.get(‘/api/v1/books’).then(function(response) { scope.books = response.data.filter(isSciFi); }); }; });
  • 5. REFACTORING - SERVICE THERE IS REPLICATED CODE ¡LET’S DO A SERVICE!
  • 6. REFACTORING - SERVICE booksService app.service(‘booksService’, function($http) { this.loadAll = function() { 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
  • 7. REFACTORING - SERVICE <APP-BOOKS-LIST> & <APP-SCI-FI-BOOKS-LIST> app.directive(‘appBooksList’, function(booksService) { return function link(scope) { booksService.loadAll().then(function(books) { scope.books = books; }); }; }); app.directive(‘appSciFiBooksList’, function(booksService) { return function link(scope) { booksService.loadAll().then(function(books) { scope.books = books; }); }; });
  • 8. PERFORMANCE - CACHING OPS! WE ARE LOADING DATA TWICE ¡LET’S DO A CACHE!
  • 9. PERFORMANCE - CACHING booksService Notice that: • Repairs all directives at once • Acquires one new responsibility (R4: manage cache) app.service(‘booksService’, function($http) { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) { return response.data; }); }; });
  • 10. NEW FEATURE - ONE BOOK WE HAVE A VIEW THAT ONLY SHOWS ONE BOOK
  • 11. NEW FEATURE - ONE BOOK <APP-BOOK-VIEW BOOK-ID=“ID”> app.directive(‘appBookView’, function(booksService) { return function link(scope, element, attrs) { booksService.load(attrs.bookId).then(function(book) { scope.book = book; }); }; });
  • 12. NEW FEATURE - ONE BOOK booksService (step1) Notice that: • What about repeating loading of books (R4: manage cache) app.service(‘booksService’, function($http) { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true).then(function(response) { return response.data; }); }; this.load = function(id) { return $http.get(‘/api/v1/books/’+id).then(function(response) { return response.data; }); }; });
  • 13. NEW FEATURE - ONE BOOK booksService (step2) • Uhmmmm… about R4… managing caches app.service(‘booksService’, function($http) { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) { return response.data; }); }; this.load = function(id) { return $http.get(‘/api/v1/books/’+id, {cache:true}) .then(function(response) { return response.data; }); }; });
  • 14. NEW FEATURE - ONE BOOK WE ARE LOADING TWICE THE SAME BOOK! It happens when: • Loading one book • Loading all books
  • 15. NEW FEATURE - ONE BOOK OK… MAY BE IT’S OK LOAD TWICE BUT NOT MORE TIMES THE SAME BOOK “We keep it simple…”
  • 16. NEW FEATURE - UPDATE BOOK WE HAVE A VIEW THAT MAKES AN UPDATE OF A BOOK AND SHOWS THE CHANGES INTRODUCED BY API
  • 17. NEW FEATURE - UPDATE BOOK <APP-BOOK-UPDATE BOOK-ID=“ID”> app.directive(‘appBookUpdate’, function(booksService) { return function link(scope, element, attrs) { booksService.load(attrs.bookId).then(function(book) { scope.book = book; }); scope.update = function() { booksService.update(scope.book).then(function(updatedBook) { scope.book = updatedBook; }); }; }; });
  • 18. NEW FEATURE - ONE BOOK booksService (step2) • Uhmmmm… about R4… managing caches app.service(‘booksService’, function($http) { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) { return response.data; }); }; this.load = function(id) { return $http.get(‘/api/v1/books/’+id, {cache:true}) .then(function(response) { return response.data; }); }; this.update = function(book) { return $http.put(‘/api/v1/books/’+id, {cache:true}) .then(function(response) { return response.data; }); }; });
  • 19. NEW FEATURE - UPDATE BOOK SHIT!
  • 20. 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?
  • 21. NEW FEATURE - UPDATE BOOK SHIT! How to solve it? • New services? • Callbacks? • RxJS? • More caches? • Events?
  • 22. NEW FEATURE - UPDATE BOOK WHAT IS THE REAL PROBLEM?
  • 23. NEW FEATURE - UPDATE BOOK WHAT IS THE REAL PROBLEM? R4 (manage caches) is hidden another responsibility: • Single source of true We need a model!
  • 24. 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
  • 25. 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.
  • 26. REFACTOR - ADD MODEL Book app.value(‘Book’, function Book(id) { this.id = id; this.isSciFi = function() { return !!this.tags.sciFi; }; this.take = function(info) { angular.extend(this, info); }; }); We discover new responsibilities: • R5: update and extract information of a book
  • 27. REFACTOR - ADD MODEL bookDictionary app.value(‘bookDictionary’, function(Book) { this.list = []; this.map = {}; this.getOrCreate() = function(id) { var book = this.map[id]; if (!book) { book = new Book(id); this.list.push(book); this.list.map[id] = book; }; return book; }; this.takeAll = function(bookInfos) { bookInfos.forEach(function(bookInfo) { this.getOrCreate(bookInfo.id).take(bookInfo); }, this); }; }); 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.
  • 28. booksService • Uhmmmm… it has caches… • Uhmmmm… it must interact with models • Uhmmmm… it must speak api
 Too many responsibilities! REFACTOR - ADD MODEL app.service(‘booksService’, function($http) { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(function(response) { return response.data; }); }; this.load = function(id) { return $http.get(‘/api/v1/books/’+id, {cache:true}) .then(function(response) { return response.data; }); }; this.update = function(book) { return $http.put(‘/api/v1/books/’+id, {cache:true}) .then(function(response) { return response.data; }); }; });
  • 29. booksRemote app.service(‘booksRemote’, function($http) { this.retrieveAll = function() { return $http.get(‘/api/v1/books’,{cache:true}).then(_getData); }; this.retrieve = function(id) { return $http.get(‘/api/v1/books/’+id,{cache:true}).then(_getData); }; this.store = function(book) { return $http.put(‘/api/v1/books/’+id,{cache:true}).then(_getData); }; function _getData(response) { return result.data; } }); REFACTOR - ADD MODEL Acquires the responsibility for: • R1: Know the API context Url • R2: Create a remote connection • R3: Transform response into usable object • R4: Manage cache (¿when data must be refreshed?)
  • 30. booksService (loadAll) app.service(‘booksService’, function(booksDictionary, booksRemote) { this.loadAll = function() { return booksRemote.retrieveAll().then(function(books) { booksDictionary.takeAll(books); return booksDictionary.list; }); }; … }); REFACTOR - ADD MODEL LoadAll returns always the same instance of list.
  • 31. booksService (load) app.service(‘booksService’, function(booksDictionary, booksRemote) { … this.load = function(id) { return booksRemote.retrieve(id).then(function(bookInfo) { var book = booksDictionary.getOrCreate(id); book.take(bookInfo); return book; }); }; … }); 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 loadAll.
  • 32. booksService (update) app.service(‘booksService’, function(booksDictionary, booksRemote) { … this.update = function(book) { return booksRemote.update(book).then(function(bookInfo) { var book = booksDictionary.getOrCreate(id); book.take(bookInfo); return book; }); }; }); REFACTOR - ADD MODEL Update returns always the same instance than load and loadAll, regardless the input. And also updates the same instance.
  • 33. three layers REFACTOR - ADD MODEL SERVICES MODELS VIEWS calls calls are $watched
  • 34. NEW FEATURE - UPDATE BOOK DONE!
  • 35. 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
  • 36. NEW FEATURE - UPDATE BOOK SHIT! Solved in next talk!
  • 37. 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 • I usually like to use .factory to simplify and homogenize code
 (over .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