Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
AngularJS application
architecture
Gabriele Falace
workshop 11.03.2015
Separation of Concerns
Rule of 1
● each component has 1 role
● 1 component per file
● each component has a single purpose
Separation of Concerns - example
Classifying concerns:
● Cross-Cutting and generic
○ logging
○ exception handling
● Cross-...
Consistent syntax
Many things can be done with different styles.
It is strongly recommended to stick with one,
especially ...
Consistent syntax - example
It is often needed to create an alias for the this
reference.
WHY: in JavaScript a scope is cr...
Consistent syntax - example
function foo(){
this.x = 5;
// other code
function bar(){
// can’t access x through “this”
// ...
Consistent syntax - example
function foo(){
var self = this;
self.x = 5;
// other code
function bar(){
// can access “exte...
Consistent syntax - example
widely used aliases
● in controllers: var vm = this; // view model
● in general js: var self =...
Consistent syntax - services
angular.module('globalServices')
.service('paymentService', PaymentService); // a service is ...
Organizing the App
can be by type of by feature
by type can be ok for small-medium
sized apps.
When the size grows this ge...
naming conventions
Controllers: avoid the suffix “Controller” use
uppercase for the function name (it’s a
constructor)
Fac...
Modules
Modules
use angular.module() for both declaring and
fetching modules.
angular.module(‘app’, []); // CREATES
angular.module...
Modules
Aggregate dependencies, in order to avoid an
overly long list of dependencies in our
modules.
Use a root “app.core...
Controllers
Controllers
● only presentation logic in here
● don’t use anonymous functions
● use the “Controller As” syntax with “this”...
Controllers
Declare the “Controller As” in ngRoutes,
whenever possible, also using resolve for
bootstrapping logic
control...
Controllers
The controller can be injected with “message”
before the controller is instantiated → good
mechanism for boots...
AJAX - sequential requests
$http.get(PRICELIST_URL)
.then(function (data) {
pricelist = data['data'];
console.log('AFTER C...
AJAX - parallel requests
$q.all([fn1(), fn2(),]);
array of functions each returning a Promise
function fn1(){
return $http...
Tips
using value/constant to keep everything in the
scope of the application. constants and values
can be injected.
angula...
Tips
It’s usually nice to consider …
● using ngAnnotate (e.g. /* @ngInject */)
● using jshint (to impose some coding style...
Unit Testing - installation
● choose a framework (e.g. Jasmine)
● choose a test runner (e.g. Karma)
● setup:
npm install -...
Unit Testing - configuring
● in the project root a karma.conf.js file
specifies settings for the tests
○ make sure that th...
Unit Testing - example
describe('testPaymentService', function () {
var paymentService, $httpBackend;
beforeEach(module('g...
E2E Testing - installation
● choose a framework (e.g. Jasmine)
● choose a test runner (e.g. Protractor)
● setup:
npm insta...
Configuring
create the configuration file. Copy the following into conf.js:
exports.config = {
seleniumAddress: 'http://lo...
Write a test
A protractor test, manipulates the actual elements in the app launching the browser and picking up
stuff in t...
References
● John Papa’s course on PluralSight
● Style guide: https://github.com/johnpapa/angular-styleguide
● More on Ser...
Próxima SlideShare
Cargando en…5
×

AngularJS application architecture

11.035 visualizaciones

Publicado el

A short presentation on how to organize an AngularJS app in a clean and maintainable way.

Publicado en: Tecnología
  • Sé el primero en comentar

AngularJS application architecture

  1. 1. AngularJS application architecture Gabriele Falace workshop 11.03.2015
  2. 2. Separation of Concerns Rule of 1 ● each component has 1 role ● 1 component per file ● each component has a single purpose
  3. 3. Separation of Concerns - example Classifying concerns: ● Cross-Cutting and generic ○ logging ○ exception handling ● Cross-Cutting and feature-specific ○ a service fetching Customer data ● Features ○ Customer Controller ○ Customer Address widget
  4. 4. Consistent syntax Many things can be done with different styles. It is strongly recommended to stick with one, especially when working in team!
  5. 5. Consistent syntax - example It is often needed to create an alias for the this reference. WHY: in JavaScript a scope is created by a function definition (and not by {} blocks) → while nesting function definitions, the reference to the “original” this is lost.
  6. 6. Consistent syntax - example function foo(){ this.x = 5; // other code function bar(){ // can’t access x through “this” // this “this” belongs to bar this.x = 6; } }
  7. 7. Consistent syntax - example function foo(){ var self = this; self.x = 5; // other code function bar(){ // can access “external” x through “self” this.x = 6; console.log(self.x); } }
  8. 8. Consistent syntax - example widely used aliases ● in controllers: var vm = this; // view model ● in general js: var self = this;
  9. 9. Consistent syntax - services angular.module('globalServices') .service('paymentService', PaymentService); // a service is a SINGLETON /* @ngInject */ function PaymentService($http, tokenService){ var service = { validateCardNumber: validateCardNumber, properCardNumberLength: properCardNumberLength }; return service; // implementation }
  10. 10. Organizing the App can be by type of by feature by type can be ok for small-medium sized apps. When the size grows this gets confusing. larger app → by feature, then by type
  11. 11. naming conventions Controllers: avoid the suffix “Controller” use uppercase for the function name (it’s a constructor) Factories/Services: same as file name Directives: same as file name + short and consistent prefix (e.g. “eb”)
  12. 12. Modules
  13. 13. Modules use angular.module() for both declaring and fetching modules. angular.module(‘app’, []); // CREATES angular.module(‘app’); // FETCHES var app = angular.module(‘app’, []); //not recommended
  14. 14. Modules Aggregate dependencies, in order to avoid an overly long list of dependencies in our modules. Use a root “app.core” module to aggregate 3rd party and other generic modules.
  15. 15. Controllers
  16. 16. Controllers ● only presentation logic in here ● don’t use anonymous functions ● use the “Controller As” syntax with “this” instead of scope ● separate registration, injection, declaration angular.module(‘app’).controller(‘foo’, Foo); Foo.$inject = [‘$http’, ‘$scope’]; function Foo($http, $scope){ … }
  17. 17. Controllers Declare the “Controller As” in ngRoutes, whenever possible, also using resolve for bootstrapping logic controller: ‘Controller’ controllerAs: ‘ctrl’ resolve: { message: [‘customerService’, function(customerService) { return customerService.getGreetingMessage(); }] }
  18. 18. Controllers The controller can be injected with “message” before the controller is instantiated → good mechanism for bootstrapping logic, better than “app.run” when logic should be specific to the controller Controller.$inject = [‘message’]; function Controller(message){ … }
  19. 19. AJAX - sequential requests $http.get(PRICELIST_URL) .then(function (data) { pricelist = data['data']; console.log('AFTER CALL 1 __ ' + pricelist + '(pricelist)'); return $http.get(CURRENCY_URL); }) .then(function (data) { currency = data['data']; var actualUrl = TARIFFS_URL.replace('{priceListId}', pricelist); return $http.get(actualUrl); }) .then(function (data){ console.log('AFTER CALL 3 __ (tariffs) n' + JSON.stringify(data['data'])); });
  20. 20. AJAX - parallel requests $q.all([fn1(), fn2(),]); array of functions each returning a Promise function fn1(){ return $http.get(SERVICE_URL); }
  21. 21. Tips using value/constant to keep everything in the scope of the application. constants and values can be injected. angular.module('application').constant('origin', 'Sydney'); service('simpleService', ['origin', function (origin) { // implementation ... }
  22. 22. Tips It’s usually nice to consider … ● using ngAnnotate (e.g. /* @ngInject */) ● using jshint (to impose some coding style) ● using JavaScript ○ especially iterators over arrays: ■ someArray.forEach(fn) ■ someArray.filter(fn) ■ someArray.some(fn) ■ someArray.every(fn) ■ someArray.map(fn)
  23. 23. Unit Testing - installation ● choose a framework (e.g. Jasmine) ● choose a test runner (e.g. Karma) ● setup: npm install -g karma npm install -g karma-cli in the project folder run the following karma init
  24. 24. Unit Testing - configuring ● in the project root a karma.conf.js file specifies settings for the tests ○ make sure that the file property in the file references an array of file path where the JS app file and the test are located! ● Typically, most important things to test are Services, as they’re the components which hold business logic
  25. 25. Unit Testing - example describe('testPaymentService', function () { var paymentService, $httpBackend; beforeEach(module('globalServices')); beforeEach(function () { inject(function($injector){ $httpBackend = $injector.get('$httpBackend'); paymentService = $injector.get('paymentService'); }); }); afterEach(function() { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); it('should check mastercard', function () { $httpBackend .when('GET', REST_API_URL + '/services/payment/validateCreditCard/5105105105105100') .respond('MASTERCARD'); var res = paymentService.validateCardNumber('5105105105105100'); $httpBackend.flush(); expect(res.$$state.value.data).toEqual('MASTERCARD'); }); });
  26. 26. E2E Testing - installation ● choose a framework (e.g. Jasmine) ● choose a test runner (e.g. Protractor) ● setup: npm install -g protractor in the project folder run the following, to start the Selenium WebDriver webdriver-manager start
  27. 27. Configuring create the configuration file. Copy the following into conf.js: exports.config = { seleniumAddress: 'http://localhost:4444/wd/hub', specs: ['todo-spec.js'] }; This configuration tells Protractor where your test files (specs) are, and where to talk to your Selenium Server (seleniumAddress).
  28. 28. Write a test A protractor test, manipulates the actual elements in the app launching the browser and picking up stuff in the page through matchers. Run it with protractor conf.js describe('Ebuero CSW number fields validation', function () { beforeEach(function () { browser.sleep(2000); browser.get(URL); ... }); it('should format, validate and copy the phone, mobile and fax number', function () { companyName.sendKeys('000TEST000 ebuero AG'); ... expect(faxNumber.getAttribute('value')).toBe(FORMATTED_PHONE_NUMBER); element(by.cssContainingText('option', 'AG')).click(); nextButton1.click(); expect(createErrorBox.isDisplayed()).toBeFalsy(); }); });
  29. 29. References ● John Papa’s course on PluralSight ● Style guide: https://github.com/johnpapa/angular-styleguide ● More on Services, Providers: http://slides.wesalvaro.com/20121113/#/2/5 ● Possible JSON security threat: http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle- json-vulnerability.aspx/

×