Service Oriented Architecture 

Presented by:

Chad King

Sr. Software Engineer @

Front End Web Development is Hard and carries inherent risk to the application

The browser is rapidly evolving

  • ECMAScript 6 && 7 
  • Web Components
  • Internet Explorer Usage is Dropping
  • There are a lot of really cool things coming down the pipeline right now
    • Web Assembly
    • Isomorphic JavaScript
    • Cross Platform Development with JS
    • Numerous new techniques for async programming in JS
      • ​Observables
      • Generator Functions
      • Async Functions

Complexity is shifting from backend to front end

  • Routing
  • Templating
  • Backend as API platform
  • MVC/MVVM/MV*/MV What ever

It's Really hard to pick the best practices.

  • OO/FP/RP
  • AMD or CommonJS
  • Dependency Managing
  • Different Solutions
    • Angular Dirty-checking
    • React's Virtual Dom

Forget About Picking The right Front End Framework:

  • Cappuccino
  • qooxdoo
  • Spine
  • Eyeballs
  • Sammy
  • Choco
  • Agility
  • Knockout
  • Angular
  • Meteor
  • React
  • Aurelia
  • ng2?

So what do we do?

Focus on What Browsers can/will support.

Some Facts:

  • Views are relatively easy to create
  • Business logic can be complex
    • Re-creating business logic can lead to lost lessons

Not Guaranteed:

  • XYZ library/framework will continue to be supported.

Guaranteed:

  • You will need to support your application beyond the life cycle of your framework.

Proposal

Service-oriented Architecture

Why Services?

  • Applications are already service heavy
  • Well written services are least opinionated
  • Avoid abuse of library features

Abusive Code

'use strict';
angular.module('demo').controller('demoCtrl', function ($scope, $http) {
    var itemsPerPage = 5;
    $scope.pagination = [];
    $scope.pageList = [];

    $http.get('http://jsonplaceholder.typicode.com/users/').then(function(data){
      $scope.userList = data.data;
    });

    $scope.getPosts = function(id){
      $http.get('http://jsonplaceholder.typicode.com/users/' + id +'/posts/').then(function(data){
        $scope.postList = data.data;
        pageCount();
      });
    }

    $scope.getComments = function(post){
      $http.get('http://jsonplaceholder.typicode.com/comments?postId=' + post.id).then(function(data){
        $scope.commentList = data.data;
        secondPagination();
      });
    }

  var secondPagination = function(){
    if(!_.isUndefined($scope.postList)){
      var divisor = Math.ceil($scope.commentList.length/itemsPerPage);
      for(var i = 0; i < divisor; i++){
        $scope.pageList.push({currentPage: i});
      }
      $scope.commentList = _.chunk($scope.commentList, itemsPerPage);
    }
  }
  });

Slightly Better

'use strict';

angular.module('sdkDemo.api.users', []).service('Users', function($http){

    this.getUsersList = function(){
      return $http.get('http://jsonplaceholder.typicode.com/users/')
      .then(function(data){
        return data.data
      });
    }

    this.getUserPosts = function(id){
      return $http.get('http://jsonplaceholder.typicode.com/users/' + id +'/posts/')
      .then(function(data){
        return data.data
      });
    }

    this.getPostsComments = function(id){
      return $http.get('http://jsonplaceholder.typicode.com/comments?postId=' + id)
      .then(function(data){
        return data.data
      });
    }
  });

What's Wrong With This?

  • Relies heavily on the existence of $scope
    • Relies on framework to organize our code for us
  • Impossible to migrate to other technologies without rewriting code completely
    • Angular 2.0
    • React 
    • Pure Web Components

How Do We Quit being addicted to frameworks?

  • Use as many standard technologies as you can where you can.
    • Es6
    • Web Components
  • Write your business logic into vanilla es6 services

ES6 Classes

'use strict';
import {RequestProvider} from './request-provider';

export class Resource extends RequestProvider {
  get(path){
    return super._fetch(super.create(path, {method: 'GET'}));
  }

  post(path, payload){
    return super._fetch(super.create(path, {method: 'POST', body: JSON.stringify(payload)}));
  }

  put(path, payload){
    return super._fetch(super.create(path, {method: 'PUT', body: JSON.stringify(payload)}));
  }

  remove(path){
    return super._fetch(super.create(this.path, {method: 'DELETE'}));
  }
}
'use strict';
import {Vigi} from './vigi';
import {BaseUrl} from './base-url-config';
import {Rest} from './rest-service';

 const vigi = () => {
   let baseUrl = new BaseUrl();
   let rest = new Rest();
   return new Vigi(baseUrl, rest);
};


const moduleName = 'vigi';
angular.module(moduleName, []).factory('vigi', vigi);
export default moduleName;

A portable and reusable Rest Service

Consuming a Service

'use strict';
export class DemoService {
  constructor (vigi) {

    vigi.setBaseUrl('http://jsonplaceholder.typicode.com');

    vigi.one('posts')
    .get()
    .then(data => console.log(data));

    vigi.one('posts')
    .post({body: 'super testy', title: 'greatest ever'})
    .then(data => console.log(data));

    vigi.one('posts', 1)
    .update({body: 'updated', title: 'blah'})
    .then(data => console.log(data));
  }
}

DemoService.$inject = ['vigi'];
angular.module(moduleName, []).service('DemoService', DemoService);
export default moduleName;

Benefits

  • Easy to reason about
  • Does not rely on anything framework specific except for rendering
    • Highly Portable
    • Requires rebuilding views and minimal logic 
      • Relatively cheap
  • Highly Testable
  • Not Es6 Reliant
    • Es6 is a tool to assist in code design
    • Can be replicated in normal javascript

Downsides

  • Move into patterns away from framework conventions
    • Lose some conciseness
    • Lose some optimizations
  • Little assistance for application architecture
    • Requires piecing together application from library
    • More low level attention
      • Browser support
      • Implementing already solved problems

What to Do?

That depends...

Business needs

  • How important is scalability?
  • How much time do I have?
  • How disciplined are my teams?

What does this buy me? Framework Independence: You may not be able to swap out frameworks in a single sprint but it will now look like a manageable task.

What can we do to make our services better?

  • Use a Dependency Injection System
    • DI.js
    • Injection module from Aurelia
    • Injection module from ng2
  • Write unopinionated services that can be used as dependencies across your platform/product line 
    • Think about the $http provider. What if you had a similar service written into vanilla JS that you could take with you to any project. 
  • Place these services into Private NPM Modules
    • Rapidly build new applications using your existing code base.

Questions?

deck

By bobbiebarker

deck

  • 956