Resources and relationships at front-end
-
Upload
wingify-engineering -
Category
Engineering
-
view
735 -
download
11
description
Transcript of Resources and relationships at front-end
![Page 1: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/1.jpg)
Angular.js and ResourcesEffectively Managing Resources (Models) in Your Angular.js Based Single
Page Applicationby Himanshu Kapoor, Front-end Engineer, Wingify
Web: , Twitter: , Email: fleon.org @himkp [email protected]
This presentation:
Download / Fork on GitHub:
http://lab.fleon.org/angularjs-and-resources/https://github.com/fleon/angularjs-and-resources
![Page 2: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/2.jpg)
The interwebs today...Single Page Apps™
(Today's Hot Topic)
+
Front-end Frameworks(Our Pick: Angular.js)
+
Moar Stuff(Package Management, AMD, Project Organisation, etc.)
![Page 3: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/3.jpg)
Why Single Page Apps™?Why should you make Single Page Apps?
They're coolEverybody else is doing itThe ™ symbol on it looks cool
![Page 4: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/4.jpg)
Why Single Page Apps™?The real reasons...
Faster experience: no page refresh, on-demand data fetchingBetter runtimes: V8, spidermonkeyHeightened expectations: new products, mobile
![Page 5: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/5.jpg)
Well ok, lets make a Single Page App!
![Page 6: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/6.jpg)
Thus begins our SPA Journey...with Angular.js + Angular UI Router + Require.js
![Page 7: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/7.jpg)
And then, there were...
![Page 8: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/8.jpg)
Models, Views and ControllersMVC 101: Angular.js Edition
Views: rendered in the browser
Controllers: makes your view dynamic, has the logic
Models: plain old POJOs
![Page 9: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/9.jpg)
POJOs as Models?Yes, Plain Old Javascript Objects!
Hmm, sounds cool!
![Page 10: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/10.jpg)
OK, here's what we got...The controller
The view
The model
function MyCtrl($scope) { $scope.myModel = 'hello world';}
<h1 ng-controller="MyCtrl"> {{myModel}}</h1>
// myModel is a POJO model
![Page 11: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/11.jpg)
The result:
![Page 12: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/12.jpg)
That was easy, but...
![Page 13: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/13.jpg)
A real model, usually...is a rather big and complex objectlies on the server
![Page 14: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/14.jpg)
Ok, lets request the server!$http shall answer all our queries
![Page 15: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/15.jpg)
The code...The controller
The view
The model
function MyCtrl($scope, $http) { $http.get('/user').success(function (user) { $scope.user = user; });}
<h1 ng-controller="MyCtrl"> Hello there, {{user.name}}</h1>
// HTTP GET{ "id": 1234, "name": "John Doe", "email": "[email protected]"}
![Page 16: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/16.jpg)
The result:
Pretty sweet, right?
![Page 17: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/17.jpg)
But hold on...Back in the real world, things aren't so simple.
![Page 18: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/18.jpg)
The problems:What about multiple views?What about other kinds of actions (POST, PATCH, PUT, DELETE)?What about muliple types of models (users, posts, comments)?How do you handle multiple instances of the same model?
![Page 19: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/19.jpg)
And while answering the questions,How do you make sure your code is:
DRYConsistentScalableTestable
![Page 20: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/20.jpg)
And here are the answers...Q: What about multiple views?
A: Abstract out the model in a service.
Q: What about other kinds of actions?
A: Add support for those methods in the service.
Q: What about muliple types of models?
A: Add support for instantiating different model types in the service.
![Page 21: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/21.jpg)
This looks like a job for...
![Page 22: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/22.jpg)
$resource
![Page 23: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/23.jpg)
$resource to the rescue!A configurable REST adapterAn abstraction of HTTP methodsAbility to add custom actionsPromise-based APIResources are lazily loaded
![Page 24: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/24.jpg)
Time for some code...The model
The controller
The view
app.factory('UserResource', function () { return $resource('/user/:userId', { userId: '@id' });});
function MyCtrl($scope, UserResource) { $scope.user = UserResource.get({ id: 1 });}
<h1 ng-controller="MyCtrl"> Hello there, {{user.name}}</h1>
![Page 25: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/25.jpg)
The result:
Looks no different from the previous output,
but our code is a lot more extendible with the above logic.
![Page 26: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/26.jpg)
The journey continues...Application grows biggerSeveral views, controllers and resourcesEditable content
![Page 27: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/27.jpg)
Incoming problems that say...
![Page 28: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/28.jpg)
Which includeView inconsistenciesDuplicated model functionalityThe code isn't DRY anymore
![Page 29: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/29.jpg)
Editable content
![Page 30: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/30.jpg)
What is it?Edit a model using a formThe model gets updated in that viewBut not other views across the appResult: inconsistency
![Page 31: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/31.jpg)
Inconsistencies?Multiple views render the same modelEach with different valuesExample: Blog, edit author name, save
![Page 32: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/32.jpg)
Why are inconstencies so bad?Contradicting/misleading informationWorse than having no information at all
![Page 33: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/33.jpg)
Here's an example:In addition to the code we already have:
The model
The controller
The view
app.factory('UserResource', function () { return $resource('/user/:userId', { userId: '@id' });});
function MyCtrl($scope, UserResource) { $scope.user = UserResource.get({ id: 1 });}
<h1 ng-controller="MyCtrl"> Hello there, {{user.name}}</h1>
![Page 34: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/34.jpg)
Let us add another view that does something else, and something more...
The view
The controller
<hr><h2>Edit your name</h2><form ng-controller="MyEditCtrl" ng-if="user.name"> New name: <input type="text" ng-model="newName"> <button ng-click="updateName()">Save</button></form>
function MyEditCtrl($scope, UserResource) { $scope.user = UserResource.get({ id: 1 }); $scope.updateName = function () { $scope.user.name = $scope.newName; $scope.user.$save(); };}
![Page 35: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/35.jpg)
The result:
Separation of concerns is good, but not if it leads to such an inconsistency.
![Page 36: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/36.jpg)
The solutionMaintain references of that model throughout the appWhen it changes, propagate that change to all instances
![Page 37: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/37.jpg)
Real world inconsistencies:Editing a resource that is related to multiple parent resourcesExample: author ~ post, author ~ commentMaintaining references here isn’t so trivial
![Page 38: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/38.jpg)
The solution: RelationshipsRelationships to handle sub-resourcesMaintaining a single reference for each unique resource / sub-resource
![Page 39: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/39.jpg)
Relationships
![Page 40: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/40.jpg)
Parent and childrenA property on a resource belongs to another resourceExample:
post.author is an AuthorResource,
author.posts is a collection of PostResourcesFour kinds of relationships: one-to-one, one-to-many, many-to-one, many-to-many
![Page 41: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/41.jpg)
Subsequent problemMaintaining references
![Page 42: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/42.jpg)
References?
![Page 43: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/43.jpg)
What are references?Maintaining references: Ensuring that each unique resource has only one
instance throughout the app.
For instance, there should be only one instance of:
UserResource with id=1UserResource with id=2PostResource with id=1
Q. How are such references maintained?
A. By transforming each backend response.
![Page 44: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/44.jpg)
Looks like a job for...
![Page 45: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/45.jpg)
TransformerA serviceInput: A backend response objectOutput: A transformed mesh of resources
![Page 46: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/46.jpg)
Example input:// GET /posts[{ "id": 1, "createdBy": { "id": 1, "name": "John Doe" } "title": "My First Post", "excerpt": "Lorem Ipsum"}, { "id": 2, "createdBy": { "id": 1, "name": "John Doe" } "title": "My Second Post", "excerpt": "Lorem Ipsum"}, { "id": 3, "createdBy": { "id": 1, "name": "Jony Ive" } "title": "My Third Post", "excerpt": "Lorem Ipsum"}]
![Page 47: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/47.jpg)
The output:// Output obtained by transforming the response abovevar output = /* ... */;
expect(output).toEqual(any(Array));expect(output.length).toBe(3);
expect(output[0]).toEqual(any(PostResource))expect(output[1]).toEqual(any(PostResource))expect(output[2]).toEqual(any(PostResource))
expect(output[0].createdBy).toBe(output[1].createdBy);expect(output[0].createdBy).toBe(output[2].createdBy);
![Page 48: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/48.jpg)
How would such a transformation bepossible?
By identifying unique resources
By getting one or more properties that can uniquely identify a resource
For example: post.id, author.id
By maintaining an index
A key value pair where:
Key: the unique identification above
Value: the actual resource
![Page 49: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/49.jpg)
Scalablity by abstractionSolving the same problem for different resources across the appIndexing each resource instance by a given propertyTransforming relationships between parents and children recursively
How?
Abstract out the core logic from configurable inputIn this particular case: the configuration is a schema
![Page 50: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/50.jpg)
The End ResultAn abstracted base that every resource stands on that is:
ScalableTestableConfigurable
Prevention of mixing resource management logic with the business logic
The core logic stays at a single place
![Page 51: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/51.jpg)
Putting it all togetherRelationshipsResource TransformationIndexing / Maintaining ReferencesA configurable schema
The result: ResourceManager
![Page 52: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/52.jpg)
Resource ManagerAn abstraction of resource-related problems faced while developing VWOA lot of them described in this presentationWe will be open-sourcing it soon
![Page 53: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/53.jpg)
General LearningsAbstract out duplicate logicAbstract out configurations from the logicThink recursivelyResearch along each stepTake inspiration from other libraries (In this particular case, it was Ember-Data)
![Page 54: Resources and relationships at front-end](https://reader033.fdocuments.in/reader033/viewer/2022051817/547e5388b4af9f9b158b56a7/html5/thumbnails/54.jpg)
Thank YouQuestions / Comments / Suggestions?Reach Out
Web: fleon.orgGitHub: @fleonTwitter: @himkpEmail: [email protected]
View this presentation: Download / Fork on GitHub:
http://lab.fleon.org/angularjs-and-resources/http://github.com/fleon/angularjs-and-
resources/