JavaScript Design Patterns

Sveliamo il Revealing Module Pattern

Created by Giacomo Secchi

Beer&Learn - @GetConnected 20/4/2016

Cos'è un design pattern?

Un design pattern è una soluzione software

riutilizzabile per uno specifico tipo di problema

che avviene frequentemente

durante lo sviluppo di un prodotto software

Esisono tante tipologie di design pattern

Builder pattern, Prototype pattern, Composite pattern, Facade pattern, Observer pattern, Mediator pattern, ecc. ecc. ecc. ecc. ecc. ecc. ecc. ecc.

JavaScript Module Pattern

Perché?

Vantaggi

  • Uno dei più usati e facilmente integrabile con le librerie più usate (jQuery, Dojo, ExtJS, YUI ecc.)
  • Approccio pulito per gli sviluppatori
  • Namespace più pulito (facile gestione di variabili locali e globali)
  • I componenti rimangono sempre ben separati

Svantaggi

  • I metodi privati non sono accessibili (maggiori difficoltà nei test)
  • Esistono metodologie più recenti ed evolute per gestire progetti di grandi dimensioni (AMD, CommonJS)

Esistono anche varie tipologie di Module Pattern

Anonymous closure, Global import, Object interface Revealing module pattern

Andiamo alla pratica

Questa è la struttua di un modulo


var Beer = {          // Oggetto 
    pushOrSomething: function () { //public method
        GoogleAnalytics.pushOrSomething.apply(this, arguments);
    },
    anotherOne: function (key) {   //altro public method
        this.pushOrSomething('action', key);
    }
};          



                    

Sorge un problema:
il metodo Beer.pushOrSomething() rimane esposto

Soluzione

Usare una Self-Executing Anonymous Function


var Beer = (function() {
    var _pushOrSomething = function () { //private method
        GoogleAnalytics.pushOrSomething.apply(this, arguments);
    };

    var anotherOne = function (key) {   //private method
        _pushOrSomething('action', key);
    };

    return {
    	anotherOne: anotherOne // we've defined what we want to return
    };
})();                    	

Module Pattern
+
Self-Executing Anonymous Function
=
Revealing Module Pattern

ATTENZIONE: la differenza fra Object interface e Revealing Module Pattern è molto labile

Object interface: all'interno dell'export (return) si possono trovare propietà e metodi che implementano le logiche del modulo stesso.

Revealing Module pattern: il return viene utilizzato esclusivamente per esporre metodi e proprietà all'esterno del modulo

notare:
  • per convenzione dichairo metodi e variabili privati con il prefix underscore
  • Tutto ciò che si trova all'interno del return è esposto

Global Import

Importiamo librerie esterne


(function ($, YAHOO) {
	// now have access to globals jQuery (as $) and YAHOO in this code
}(jQuery, YAHOO));
						

Un esempio pratico con Underscore e jQuery


var Beer = (function($, _) {
    var _pushOrSomething = function () { //private method
        GoogleAnalytics.pushOrSomething.apply(this, arguments);
    };

    var anotherOne = function (key) {   //private method
        _pushOrSomething('action', key);
    };

    var format = function (el) {
    	$('.container').html(el);
    };

    findAleBeers = function () {
    	list = _pushOrSomething();
    	_.filter(list, function(item){ return item === 'Ale'; }); 
    }

    return {
    	anotherOne: anotherOne // we've defined what we want to return
    };
})( jQuery, _ );   
	                	

Augmentation

come far interagire più moduli fra di loro

Per i progetti di medie e grandi dimensioni diventa indispensabile suddividere la propria code-base in più files.

Strict augmentation

Esempio: Supponiamo di avere un modulo helper, alcune sue funzionalità sono necessare sia sul file cart.js (disponibile solo nella pagina http://miosito.com/cart/) che su account.js (disponibile solo nella pagina http://miosito.com/account/)

file: /helpers.js

var helperModule = (function() {
    function logMultipleTimes (n) {
        for (i = 0; i < n; i++) {
        	console.log('La funzione logMultipleTimes è stata chiamata ' + n + ' volte dal modulo Beer');
        }
    }
    
    return {
    	logMultipleTimes: logMultipleTimes
    };
})();
                		
file: /cart.js

var Cart = (function(h) {

    function productsAddedToCart (key) {
        // Do some stuff
        helperTest();
        h.logMultipleTimes(2);
    }
    
    function helperTest () {
    	// Do other stuff
    	h.logMultipleTimes(6);
    }

    return {
    	productsAddedToCart: productsAddedToCart
    }
})(helperModule);

						
file: /account.js

var User = (function(h) {

    function logUserName (key) {
        // log user credit cards number
        h.logMultipleTimes(key);
    }
    
    function listCreditCards (key) {
    	// Do some stuff with my helper and underscore libray
    	h.logMultipleTimes(_.size(key));
    }

    return {
    	logUserName: username
    	listCreditCards: listCreditCards
    }
})(helperModule, _);

User.listCreditCards({one: 1, two: 2, three: 3});
						
					

Extending Module Pattern

Loose Augmentation

A differenza della Strict augmentation, la Loose augmentation ti permette di caricare i moduli in modo asincrono (ordine a piacere nella chiamata ai files)


var MODULE = (function (my) {
	// add capabilities...

	return my;
}(MODULE || {}));
                        
Fra i problemi di quest'approccio c'è la difficoltà di override dei metodi ereditati, per risolvere questo problema è indicato usare la Tight Augmentation

Esempio di Thight Augmentation


var MODULE = (function (my) {
    var old_moduleMethod = my.moduleMethod;

    my.moduleMethod = function () {
        // method override, has access to old through old_moduleMethod...
    };

    return my;
}(MODULE));
                        

Credits

https://carldanley.com/javascript-design-patterns/

http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html -> approfondimento per i test http://www.adequatelygood.com/Writing-Testable-JavaScript.html

http://www.raymondcamden.com/2013/05/13/JavaScript-Design-Patterns-The-Revealing-Module-Pattern/

https://addyosmani.com/resources/essentialjsdesignpatterns/book/

https://medium.freecodecamp.com/javascript-modules-a-beginner-s-guide-783f7d7a5fcc#.k4vjrukps

w2ui.com/web/blog/1/A-Variation-of-JavaScript-Module-Pattern

Grazie e buona birra!!!!!