Prácticas recomendadas del patrón de diseño del módulo ExtJS (JavaScript)

I have a question about best practices with the Module Design Pattern. The code below is an example of the way that some of our Components are written (we use ExtJs but that shouldn't matter too much). We build a lot of our components like this and I know that this doesn't match best practices exactly. Have any thoughts to clean up the code?

Ext.ns("TEAM.COMPONENT");

function Foo() {

    // Private vars
    var privateNumber=0, myButton, privateInternalObject;

    var numberField = new Ext.form.NumberField({
        label : 'A NumberField!',
        listeners : {
            'change' : function(theTextField, newVal, oldVal) {
                console.log("You changed: " + oldVal + " to: " + newVal);
            }
        }
    });

    // Some private methods
    function changeNumField(someNumber) {
        numberField.setValue(someNumber);
    }

    // Some public methods
    this.publicFunctionSetNumToSomething() {
        changeNumField(privateNumber); 
    }

    /**
     * Initializes Foo
     */
    function init() {
        // Do some init stuff with variables & components
        myButton  = new Ext.Button({
            handler : function(button, eventObject) {
                console.log("Setting " + numberField + " to zero!");
                changeNumField(0);
            },
            text : 'Set NumberField to 0'

        });

        privateInternalObject = new SomeObject();
        word = "hello world";
        privateNumber = 5; 
    }

    init();

    return this;

};

I'm wondering a few things about this and wanted to ask and get conversation going:

  1. How important is it to initialize variables when they're declared (i.e. at the top of Foo)
  2. How might I re-initialize part of this object if a client of this Module gets to a state that it's foo object needs to be set back to it's originals
  3. What sort of memory issues might this design lead to and how can I refactor to mitigate that risk?
  4. Where can I learn more? Are there any articles that address this without relying too much on the latest and greatest of EcmaScript 5 ?

Actualización 2012-05-24 I just wanted to add, I think this question ( Extjs: ¿extender la clase a través del constructor o initComponent? ) is pretty relevant to the conversation, especially considering that the top voted answer is from a "former Ext JS co-founder and core developer"

Actualización 2012-05-31 One more addition, this question should also be linked ( Miembros privados al extender una clase usando ExtJS ). Also, here is my favorite implementation to date:

/*jshint smarttabs: true */
/*global MY, Ext, jQuery */
Ext.ns("MY.NAMESPACE");

MY.NAMESPACE.Widget = (function($) {
    /**
     * NetBeans (and other IDE's) may complain that the following line has
     * no effect, this form is a useless string literal statement, so it 
     * will be ignored by browsers with implementations lower than EcmaScript 5.
     * Newer browsers, will help developers to debug bad code.
     */
    "use strict";

    // Reference to the super "class" (defined later)
    var $superclass = null;

    // Reference to this "class", i.e. "MY.NAMESPACE.Widget"
    var $this = null;

    // Internal reference to THIS object, which might be useful to private methods
    var $instance = null;

    // Private member variables
    var someCounter, someOtherObject = {
        foo: "bar",
        foo2: 11
    };

    ///////////////////////
    /* Private Functions */
    ///////////////////////
    function somePrivateFunction(newNumber) {
        someCounter = newNumber;
    }

    function getDefaultConfig() {
        var defaultConfiguration = {
            collapsible: true,
            id: 'my-namespace-widget-id',
            title: "My widget's title"
        };
        return defaultConfiguration;
    }

    //////////////////////
    /* Public Functions */
    //////////////////////
    $this = Ext.extend(Ext.Panel, {
        /**
         * This is overriding a super class' function
         */
        constructor: function(config) {
            $instance = this;
            config = $.extend(getDefaultConfig(), config || {});

            // Call the super clas' constructor 
            $superclass.constructor.call(this, config);
        },
        somePublicFunctionExposingPrivateState: function(clientsNewNumber) {
            clientsNewNumber = clientsNewNumber + 11;
            somePrivateFunction(clientsNewNumber);
        },
        /**
         * This is overriding a super class' function
         */
        collapse: function() {
            // Do something fancy
            // ...
            // Last but not least
            $superclass.collapse.call(this);
        }
    });

    $superclass = $this.superclass;
    return $this;

})(jQuery);​

preguntado el 01 de febrero de 12 a las 22:02

ExtJS documentation guides are full of great advice covering this area exactly. Have a look at guides "The Class System", "Components", and "MVC Application Architecture" at least, they will help you a lot. -

1 Respuestas

First, this isn't specifically a module design pattern as I know it, this is a general constructor pattern. The module pattern I know is a singleton, but here you could have many instances of Foo(). That being said...

Q: How important is it to initialize variables when they're declared (i.e. at the top of Foo)

Declaring them at the top is important for clarity, but initializing them isn't as important here since you're doing so in the init. If you weren't doing this, initializing them prevents you from having to do an undefined check before testing the variable later:

var x;

function baz(){
    if (typeof(x) === 'undefined') {
        // init
    } else {
        if (x > 0) { blah } else { blah blah }
    }
}

Q: How might I re-initialize part of this object if a client of this Module gets to a state that it's foo object needs to be set back to it's originals

Is there something wrong with creating a public reset method? It will have access to the private variables.

function Foo() {
    // ...

    this.reset = function () {
        privateNumber = 0;
        // etc
    };

    // ...
}

Q: What sort of memory issues might this design lead to and how can I refactor to mitigate that risk?

No lo sé.

Q: Where can I learn more? Are there any articles that address this without relying too much on the latest and greatest of EcmaScript 5 ?

Here's a good read about the Javascript module (and other) pattern(s): http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript

Respondido 02 Feb 12, 12:02

I am 99.99% going to accept your answer :) I know, slow reply but I do have some follow-up thoughts. Also, I wanted to link to this for future reference for myself: stackoverflow.com/q/4119469/320399 - blong

Any thoughts on the pattern described in this answer? stackoverflow.com/questions/1721935/… - blong

I don't have enough knowlege about ExtJS to speak to it completely, but it looks like a solid implementation of a module pattern to me. - mVChr

Hey mVChr or @Tom, any thoughts on this? stackoverflow.com/questions/4119469/… - blong

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.