Question

I'm writing to you all because I would like to have some advice and tips about a characteristic module pattern that I'm using.

Searching the topic on the web and in books, I couldn't find anything similar to this architectural choice, except for certains concepts.

The pattern in few words: ° Every webpage must include only one scope, and could include many modules. ° Every module is an IIFE, with subfunctions. ° Every scope has a document ready and calls one or many modules.

I attach you a code example to be more explicative.

Does this pattern reminds you something already seen before? Is a good architectural choice? Any weak points or architectural mistakes in this pattern? Is this a good use of IIFE functions and namespaces?

Thank you in advance, best regards.

index.html

<html>
<head>
    <meta HTTP-EQUIV='content-type' CONTENT='text/html; charset=utf-8'/>
</head>

<body>

    <div id="first"></div>
    <div id="second" style="border:2px solid green;width:150px;height:190px;"></div>

</body>

<script type='text/javascript' src='http://code.jquery.com/jquery-latest.min.js'></script>
<script type='text/javascript' src='js/module.one.js'></script>
<script type='text/javascript' src='js/module.two.js'></script>
<script type='text/javascript' src='js/scope.js'></script>

module.one.js

(function () {


// Module namespace

if (typeof $M === 'undefined') { 
    $M = {}; 
}

// Variables declaration chained
var 
    $first,
    $second,
    $chunk,
    documentHeight,
    animationTime,
    style,
    style2;

/* ===========================================================================================================
    INIT FUNCTION
============================================================================================================= */

var init = function() {

    // calls setup first 
    setup();                        

    // calls other functions
    appendChunk();
    animateChunk();
};

function setup() {

    // Vars caching
    $document = $(document);
    $first = $('#first');
    $second = $('#second');
    $chunk = $("<div id='chunk'> truffle shuffle </div>");
    documentHeight = $document.height(); 
    animationTime = 1000;

    style = {
        'border':'2px solid red',
        'height': documentHeight / 8,
        'width': '150px'
    };

    style2 = {
        'height': documentHeight / 4,
        'width': '300px'
    };

    $second.hide();
}

/* ===========================================================================================================
    OTHER FUNCTIONS
============================================================================================================= */

function appendChunk() {
    $first.append($chunk);
    $chunk.css(style);
}

function animateChunk() {
    $chunk.animate(style2,animationTime,function(){
        $(this).trigger('animationComplete');
    });
}



/* ===========================================================================================================
    INIT MODULE
============================================================================================================= */

$M.one = init;

})();

module.two.js

(function () {


    // Module namespace

    if (typeof $M === 'undefined') { 
        $M = {}; 
    }

    // Variables declaration chained
    var 
        $second,
        $chunk,
        animationTime,
        style;

    /* ===========================================================================================================
        INIT FUNCTION
    ============================================================================================================= */

    var init = function() {

        // calls setup first 
        setup();                        

        // calls other functions
        chunkListener();
        secondListener();
        isSecondVisible();
    };

    function setup() {

        // Vars caching

        $second = $('#second');
        $chunk = $("#chunk");

        animationTime = 1000;

        style = {
            'border':'2px solid red',
            'height': '150px',
            'width': '150px'
        };

    }

    /* ===========================================================================================================
        OTHER FUNCTIONS
    ============================================================================================================= */

    function chunkListener() {
        $chunk.on('animationComplete',function(){
            $second.fadeIn().trigger('animationComplete');
        });
    }

    function secondListener() {
        $second.on('animationComplete',function(){
            $chunk.animate(style,animationTime);
        });
    }


    function isSecondVisible() {
        var time = setInterval(function() {
            if($second.is(':visible')) {
                console.log("visible");
                clearInterval(time);
            } else {
                $second.html("finished!");
            }
        },200);
    }


    /* ===========================================================================================================
        INIT MODULE
    ============================================================================================================= */

    $M.two = init;

})();

scope.js

$(document).ready(function () {

$M.one();
$M.two();

});
Was it helpful?

Solution

Does this pattern reminds you something already seen before?

The Modules structure is similar to the Module Pattern. The principle of extending a "super" module that you refering to as $M looks also familiar. See Module Augmentation

Is it a good architectural choice? Any weak points or architectural mistakes in this pattern?

Thinking Modular is often (of course depending on context, making a 'hello world' application modular is a bit an overkill) a good architectural choice. However, While reading your modules logic i was a bit doubtful about making designed in a procedural way internally and not exposing any api. I believe you have an opportunity for improving you modules design by implementing an M-V-* like architecture.

Is this a good use of IIFE functions and namespaces? I think your usage is fine as it is. I'll perhaps add the "super" module($M) as an argument of you modules IIFE, that should isolate better your modules from the external world (the global scope).

References

Learning JavaScript Design Patterns

Immediately-Invoked Function Expression (IIFE)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top