follow me on Twitter

    Javascript Object Composition

    Nella programmazione ad oggetti spesso si sente l'esigenza di comporre gli oggetti anziche creare complesse gerarchie di codice e per questo sono state introdotte tutta usa serie di tecniche oltre a nuove caratteristiche dei linguaggi stessi. Ad esempio se avessi voluto"Mescolare" del codice in Ruby per ottenere un nuovo oggetto con le caratteristiche risultati (e senza dover usare un foglio A3 per disegnarne l'albero genealogico ;-)) avrei avuto a mia disposizione i Mixin, qualcosa del tipo:
    
    module InutilityModule
    def important_method
      @obj_var = 5
    end
    end
    
    class TClass
    include InutilityModule
    
    def initialize
      @obj_var2 = 2
    end
    
    def add
       return @obj_var2+@obj_var
    end
    end
    
    Le istanze della classe TClass avranno il metodo important_method oltre ai propri. In JavaScript le cose vanno un po' diversamente in quanto non ci sono classi ma oggetti prototipo, e inoltre gli oggetti altro non sono se non Hash tables. Se vogliamo aggiungere un metodo ad un oggetto JavaScript ci basta definirne la nuova proprietà:
    
    var myobj = {
    method1: function() {
      this._var1 = 5;
    }
    };
    
    myobj.method2 = function() {
    this._var2 = 3;
    }
    
    myobj["method3"] = function() {
    alert(this._var1+this._var2);
    }
    
    alle volte pero' mi e' capitato di doverne aggiungere un gruppo e quindi per pulizia ciclo su tutti gli attributi dell'oggetto sorgente:
    
    var codetomix = {
    method2: function() {
      alert("method2");
    },
    
    method3: function() {
      alert("method3");
    }
    }
    
    for (var property_name in codetomix) {
    myobj[property_name] = codetomix[property_name];
    }
    
    volendo (come fanno molti framework javascript) si puo' incapsulare la funzionalita' in una funzione di comodo:
    
    function apply(src, dst) {
    for (var prop in src) {
      dst[prop] = src[prop];
    }
    }
    
    apply(codetomix,myobj);
    
    chiaramente questa versione di "apply" è moooolto minimale ma nella sua minimalita' puo' essere molto utile quando non si vuole ricorrere all'implementazione di un particolare framework (che introduce in genere una maggiore complessita' avendo come obiettivo quello di realizzare l'ereditarietà alla maniera classica) IMHO la cosa simpatica di snippet come questo è che rendono evidente la propensione a scheme del design di JavaScript ;-)

    [Spec] Testing Your Code

    Un anno fa circa ho cambiato il mio approccio al testing del codice passando dal classico Unit Testing allo Spec Testing (e di fatto puntanto alla metodologia BDD anzichè TDD). Inizialmente ho introdotto lo spec testing nello sviluppo di applicazioni ruby/ruby on rails attraverso RSpec. RSpec è un framework di testing BDD implementato attraverso la definizione di un DSL interno per Ruby, consentendomi di scrivere gli spec-test in una sorta di pseudolinguaggio molto gradevole e leggibile:
    
    # mycode_spec.rb
    require 'mycode'
    
    describe MyCode do
    before(:each) do
    @myvar = MyCode.new
    end
    
    it "should work as i want ;-)" do
    ret = @myvar.set_something(45)
    ret.should == true
    end
    end
    
    Oltre ad essere molto gradevole la sintassi del codice, lo è ancora di più il report html che puo' essere generato a valle dell'esecuzione dei test. Ma dato che ora come ora sono intento a scrivere per lo più Javascript sentivo l'esigenza di avere qualcosa di analogo... non sto tranquillo se non ho i test a supporto... durante i refactoring mi tremano le mani ;-) Beh... non ho dovuto cercare molto: c'è JSSpec! La sintassi è molto simile a quella di RSpec, ed è altrettando gradevole ed autoesplicativa:
    
    describe('XPath helpers (snapshot, iter, any)', {
    'before_all': function() {
     // get test xml data
     xhr = new XMLHttpRequest();
     xhr.open("GET","data/test.xml",false);
     xhr.send(null);
    
     // init testing data objects
     xml_dom_obj = xhr.responseXML;
    },
    
    'should create a snapshot from an xpath expression and a dom node': function() {
     var xp_res = $XP_snap(xml_dom_obj, "//*");
     value_of(xp_res.resultType).should_be(XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
     value_of().should_fail("TODO: CHECK RESULT CONTENT");
    },
    
    'should create an interator for the xpath expression and a dom node': function() {
     var xp_res = $XP_iter(xml_dom_obj, "//*");
     value_of(xp_res.resultType).should_be(XPathResult.ORDERED_NODE_ITERATOR_TYPE);
     value_of().should_fail("TODO: CHECK RESULT CONTENT");
    },
    })
    
    Tra l'altro lo sviluppatore è un coreano molto molto cordiale (e sicuramente molto geek ;-): gli ho inviato una patch di poche righe per visualizzare il codice dei test eseguiti nei div html dei singoli test, che ho inserito nella mia copia di JSSpec per aiutarmi nel debugging dei test che falliscono e per valutare la sintassi dell'API dai test che scrivo, e l'ha integrata dopo due giorni nel trunk e dopo avermi inviato una mail di ringraziamento e un per avvisarmi dell'integrazione :-DDD Ed erano solo 2 righe ;-) Chissa se scrivessi una "intera funzione"! magari mi manda un thé coreano :-PPPPP Sono un fanatico del thé... quasi quasi gli propongo il baratto :-D Comunque a conferma (a volte cerco conferme di questo tipo ;-)) che non sono pazzo con il mio flash sui test ecco il post di un altro personaggio che ha fatto più o meno il mio stesso percorso e offre anche qualche altro spunto interessante (lo spec-testing javascript browser-less): Happy Hacking
    View Luca Greco"s profile on LinkedIn

    Rpl

    La mia foto
    Lecce, Italy
    Fulltime Coder and *nix BOFH