Archive

Archive for the ‘ExtJs’ Category

ExtJs. Struggling against boilerplate code.

March 23, 2010 Leave a comment

  I don’t like any scent of boilerplate code in any programming language, specially in dynamic languages. The dynamic languages are just not designed for it, having boilerplate code out there twice pain as in static languages.
  If you are using well-known “Preconfigured class” idiom, you will find the following idiom very useful. It delegates part of routine to just one method. I name it “config merge” idiom:

    
Config = {};
Config.merge = function(config, defaultConfig){
        config = config||{};
        defaultConfig =  defaultConfig||{};
        Ext.applyIf(config, defaultConfig);
        return config;
}
    

I bet the following routine of incoming config and default config is repeated in your code sometimes or more often:

    
MyCompany.MySuperPanel = Ext.extend(Ext.Panel, {
   constructor:function(config){
         config = config||{};
         var defaultConfig = {width:100, height:200, autoScroll:false};
         Ext.applyIf(config, defaultConfig);
         MyCompany.MySuperPanel.superclass.constructor.call(this, config);
}});
  

And with “merge” idiom:

  
 MyCompany.MySuperPanel = Ext.extend(Ext.Panel, {
    constructor:function(config){
          Config.merge(config, {width:100, height:200, autoScroll:false});
          MyCompany.MySuperPanel.superclass.constructor.call(this, config);
}});

Applying this idiom results in twice less code or even in one line code.

 MyCompany.MySuperPanel.superclass.constructor.call(this,
    Config.merge(config, {width:100, height:200, autoScroll:false}));

ExtJs. Preconfigured class.

October 28, 2009 2 comments

 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