DeftJS Dependency Injection with ExtJS or Sencha Touch

DeftJS provides functionality that allows you to create ExtJS and Sencha Touch applications that are robust and highly maintainable by reducing the spaghetti code created by complex application business logic.  Out of box ExtJS and Sencha Touch give us access to Controllers, ViewContollers, Models, and Views.  Business logic can be performed in the Controllers and ViewControllers for small applications.  For larger applications, this leads to very large Controllers and ViewControllers that can span thousands of lines of code.  In Java and other languages that had strong and robust IDEs, like Eclipse, most people don’t think about it.  It’s very easy in Eclipse to find a hierarchy or traverse a set of method invocations.  With JavaScript and the use of more primitive IDEs this becomes almost impossible, especially if your IDE of choice is a simple text editor.

Dependency Injection

So the first thing we need to do is break up the code in the Controllers and ViewControllers into view logic and business logic.  Anything that is not touching a view component, like your super cool algorithm, can be moved into a new Service class.

Example:

Ext.define('Myapp.controller.MyController', {
  extend: 'Ext.app.ViewController',
  alias: 'controller.mycontroller',
  control: {
    'button': {
      click: 'onClick'
    }
  },
  onClick: function() {
    var me = this,
        value = Math.floor(Math.random() * 10);
    me.lookupReference('label').setValue(value);
  }
});

So the value = Math.floor(Math.random() * 10) is not view logic and if this was a larger algorithm with multiple lines of code and conditional logic, it could easily overwhelm this controller file. To avoid this, we can separate this out into a Service.

Ext.define('Myapp.controller.MyController', {
  extend: 'Ext.app.ViewController',
  alias: 'controller.mycontroller',
  mixins: ['Deft.mixin.Injectable'],
  inject: ['myService'],

  control: {
    'button': {
      click: 'onClick'
    }
  },
  onClick: function() {
    var me = this,
        value = me.myService.getValue();
    me.lookupReference('label').setValue(value);
  }
});

Ext.define('Myapp.service.MyService', {

  getValue: function() {
    return Math.floor(Math.random() * 10);
  }
});

In the application init() function:

init: function() {
  Deft.Injector.configure({
    myStore: {
      className: 'Myapp.service.MyService',
      singleton: true
    }
  });
  ...

Once we create the new Service class MyService, we have to connect to the ViewController. To make this happen we use DeftJS Dependency Injection. Dependency Injection allows us to write loosely coupled classes and then have the Application wire them together for us. This gives us the benefit of having the application itself manage the creation of the Service service and also allows us to easily swap out implementations. You can move from version 1 of your algorithm to version 2 by just changing the className attribute in the Deft.Injector.configure code.

So instead of this overhead you could potentially just define the Myapp.service.MyService class as singleton:true. This is great for utility functionality like date formatters and string formatters but may not be what you need for business logic. First, the class is referenced directly, so your function call would be Myapp.service.Myservice.getValue() rather than the abstract me.myService.getValue() so you would need to find and replace all the class name references in your code as your business logic changes. Secondly, the DeftJS Injector is a factory that allows us more fluid control over the creation of our objects. The singleton:true can be turned into singleton:false and every time we access me.myService we can be presented with a new Object which gives us the ability to work in a prototypical scope. This creates the ability to manage state at a request level which is something the Ext singleton cannot do.