Home > anti pattern, ExtJs, javascript > ExtJs. Preconfigured class.

ExtJs. Preconfigured class.

 I just have read the post
http://www.extjs.com/forum/showthread.php?t=26728.

 I disagree the concept of “Preconfigured class” considered as suggestion. Probably, in some cases it is OK but they are few of them. When I first time faced the “Preconfigured class” in extjs, I recall the ASP.NET ecosystem controls immediately. Because both “Preconfigured class” and ASP.NET control class use inheritance to customize, there are some pitfalls that are intrinsic to them:


public partial class MyControl : System.Web.UI.UserControl
{  
        private void CreateUrlResolver(){
        ...

        private Renderer GetRenderer(){
        ...

        protected void Button1_Click(object sender, EventArgs e)
        {
                //some logic
        }
...
  1. The class is not testable as it is part of UI framework so you cannot unit tests it. You need to employ other techniques as is extra effort.
  2. The class is usually littered with a lot of code. There are  event handling, creation methods, and view methods that are related to rendering. These all violate SRP and it is nightmare to maintain such classes in system.

 The javascript environment is much more flexible but people still use inheritance. I have seen a lot of samples where people extend the Ext.Component in order to add one event handler only, thereby making constrains for them to unit test and utilize it again. For instance, there is a panel with button that is charged with task of saving current state. In case of “Preconfigured class” I would have something like this.


var StatePanel = Ext.extend(Ext.Panel,  {
        frame:true,
        renderTo:'panel',
        constructor:function(config) {
           config.items = config.items || [];
           var button = new Ext.Button({text:"Ok", width:50});
           config.items.push(button);
           StatePanel.superclass.constructor.call(config, this);
           button.on("click", this.onClick, this);
        },

        onClick:function() {
                 // save the current state
         }
});

 Let’s assess the implementation above:

  1. Complexity. It invokes extending mechanism to emulate inheritance – that means extra manipulation with JavaScript’s prototypes. It is complex and emits the extra objects and closures that support inheritance.
  2. Reusability. What is really annoying is that the code that is charged with saving state is sealed. It cannot be used anywhere else. Sure, you can derive the base panel class and inject it there, thereby making messy at the abstract level. I mean that you shouldn’t share functionality with the base class. If you would use it as store of common methods it just loses its cohesion. You cannot maintain the class that is littered with a lot of aspects of system in future.
  3. Testability. This class is part of UI framework so the unit testing is an issue. You need some scaffolding to run it.

 If you dare to test it, you need html holder (it is div element with id) for your panel and then you have to init it in “set up”.


function set_up(){
     _testPanel =   new StatePanel({renderId:”testId”});
}
function testMethod(){
     .....
}

 You always need to keep in mind both ExtJs and UnitTestRunner lifecycles. But the most routine would be clean up code after the test as each test is interlaced with html.

 Let’s assess the same “StatePanel” but all handling is moved to “StateHandler” class that acts as controller:

 
function StateHandler(button) {
            this.init = function(component) {
            this._component = component;
            button.on("click", this.onClick, this);
           }

           this.onClick = function() {
                  // save the current state
            }
}

var button = new Ext.Button({text:"Ok", width:50});
var stateHandler = new StateHandler(button);
new Ext.Panel({frame:true, renderTo:'panel',items:[button],plugins:[stateHandler]});

What we have gained here:

  1. Complexity. I have plain object with single responsibility and it’s cool.
  2. Reusability. I can plug it to any component.
  3. I can simply test it without any scaffolding as I have plain object not connected to UI framework.

 This implementation recalls the MVC pattern, especially PassiveView. The idea is to make the view a dumb slave to move all code to the controller. It doesn’t mean that view is untouchable, it rather means that view should encompass methods that are familial to view. It could be methods that deal with the rendering which probably requires the intimate overrides. The new API of view could be subject to extend it.

 In sample above I used the plugins property to inject controller.

    
         var button = new Ext.Button({text:"Ok", width:50});
         var stateHandler = new StateHandler(button);
         new Ext.Panel({frame:true, renderTo:'panel',items:[button],plugins:[stateHandler]});
    
  

 You can use any kind of injection. The “plugins” property as pattern is not requirement. Use any creational patterns not to duplicate the creation of panel as well as gain flexibility in re-using the code and applying conditional algorithms there.


MyApplication.windows.FormBuilder.CreateMySuperPanel = function(){   
           //some conditional logic related to creation
           //
           var panel = new Ext.Panel({frame:true, renderTo:'panel',items:[button]);
           var button = new Ext.Button({text:"Ok", width:50});
           var stateHandler = new StateHandler(button);
           stateHandler.init(panel); 
 
}

 You can approach it in many ways, the main is to keep in mind separation of concerns. The initial concern is to wire all dependencies. I bet it’s much better to have class named “builder” that creates the panel at your will rather than to extend that panel for injection of only creation routine.

  
  var StatePanel = Ext.extend(Ext.Panel,  {
    myConfigConstant:'someConstant',
    frame:true,
    ...
    constructor:function(config) {
           config.items = config.items || [];
           var button = new Ext.Button({text:"Ok", width:50});
           config.items.push(button);
           StatePanel.superclass.constructor.call(config, this);
           button.on("click", this.onClick, this);
        },
   

 The next concerns are view and controller where the controller is the “StateHandler” and view is “Ext.Panel”. This approach will evolve your architecture in future. Though it cannot be considered as remedy. You cannot apply it to everywhere, for instance, a gender control. I wouldn’t implement controller and builder for it I would rather implement “Preconfigured class”.

  
 Ext.extend( Ext.form.ComboBox, {
      typeAhead: true,
      triggerAction: 'all',
      lazyRender:true,
      mode: 'local',
   
   constructor :function(){
       var male = "male";
       var female = "female";
   }

});


 

 I call such component the “primitive component”. It’s not worth to apply builder and controller as separate classes. It is pretty enough to pre-configure. I don’t believe that the gender component will ever grow. In other words if it’s simple per se, don’t add extra complexity. It is not worth to segregate extra classes to highlight their relationships.

Categories: anti pattern, ExtJs, javascript
  1. Vojta
    August 29, 2010 at 3:09 am

    You are absolutely right !!!

    Do you have more hints about TTD with ExtJs ???
    I guess you have experiences with it, I would be really glad to learn some tips about writing testable code in ExtJs.

    I really love TTD, now I’m starting with ExtJs and it’s hard to find good information, as almost all the code on ExtJs web (manuals, forum posts, …) is very untestable…

    I recommend this link for all: http://misko.hevery.com
    This man really knows about testing 😀

    And really nice project for js testing:
    http://code.google.com/p/js-test-driver/

    I’m planning to write my own UnitTest framework for ExtJs (or just write wrapper for http://code.google.com/p/extjs-unit-test/ to run it under js-test-driver), because it’s much more effective to run the tests in command line, than in browser…

  2. September 9, 2010 at 4:41 pm

    Thank you for links.

    Yes, I have couple hints. Currently, we work on application where UI is based on ExtJs. Why I love the ExtJs is that it mimics the desktop developing. It possesses inheritance as well as the same abstractions(panels, grid .etc) from desktops. So in terms of unit testing it would be the same as for desktop application.
    If you going to unit test.
    First of all try to segregate all logic in separate classes. In terms of desktop developing it would be controller that you can run unit test against. This way you will benefit a testable environment as wells as more reusable code. In our workshop we move all component logic in the underlying plugins. We also have rule “one plugin – one functionality”. We call it “aspects”. The rule states that the plugin can be safely ejected and it wouldn’t lead to javascript error but to losing certain functionality. It also tells that plugin can be tested in separately. So, all logic for components is implemented via ExtJs plugins. For instance, registration form that has at least one aspect “validation” that can be packed in plugin and be tested. To run tests we use Yahoo unit test framework. We have separate test page to run tests.

    We also use selenium RC to run more complex scenarios in C# from nunit console. But it’s anohter story. Probably it’s topic for post.

  1. No trackbacks yet.

Leave a comment