martedì 19 novembre 2013

Refactor di un'applicazione web: javascript code isolation

Un problema che sorge nello sviluppo di una applicazione web è affrontare la quantità sempre più crescente di codice javascript.

Se si segue la convenzione di Rails di utilizzare un file javascript per controller l'entropia del codice  aumenta soprattutto se finora si è scritto codice senza usare classi e oggetti.
I problemi aumentano quando in produzione, per motivi di performance, si decide di compilare e comprimere il codice accorpando tutti gli assets javascript e coffescript in un unico file.

Come possiamo evitare che il codice di una pagina venga eseguito anche dove non deve?

Possiamo rifattorizzare il nostro codice seguendo alcune semplici regole:

  1. Il body è il tuo discriminante, da lui discendono i tag che compongono la tua app sfrutta questo fatto per isolare javascript e css
  2. usa un file js per ogni action del tuo controller con questa naming convention controller.action.js (es articles.new.js, articles.edit.js e articles.show.js)
  3. Pensa a oggetti, segui il pattern model-controller-view anche nel client, se hai già molto codice, puoi incominciare a isolarlo creando moduli
  4. Usa un solo document ready per tutta l'applicazione
  5. Elimina le funzioni globali, sono il male, e tu non vuoi fare del male vero? Crea un modulo con le funzioni cross controller (vedi punto 3)


Analizziamo le regole punto per punto:

Body come discriminante
Quando renderizzi il layout usa il body per far conoscere a tutte le componenti della tua app dove sei.

In Rails ad esempio possiamo usare questa sintassi:

<body data-controller='<%= controller.controller_name %>' data-action='<%= controller.action_name%>' data-id='<%= params[:id] %>'>

in questo modo possiamo via javascript capire dove siamo e al document ready lanciare solo quello che ci serve.

Possiamo applicare la stessa tecnica per comunicare a javascript altri stati dell'applicazione ad esempio se siamo loggati o meno:
 <body data-loggedin='<%= logged_in? %>'  ....>

Per far conoscere lo stato dell'applicazione al CSS possiamo dare al body un ID così composto:

 <body id='<%= "#{ controller.controller_name}- #{controller.action} "%>'  ....>

A questo punto possiamo invocare il codice che ci serve solo quando ci serve nell'unico document ready dell'applicazione contenuto nel file application.common.js. Ad esempio se abbiamo stabiliamo che la funzione di caricamento della pagina dev'essere chiamata _initcontrolleraction possiamo procedere così:

$(function(){
  bodyData = $('body').data()
  try{
    var funcName = "_init" + bodyData.controller + bodyData.action;
    window[funcName].apply(this);
  }catch(err){

  }
})


se stiamo visualizzando la pagina /articles/new automaticamente verrà chiamata la funzione _initarticlesnew() che conterrà il codice di inizializzazione della pagina.

Nei prossimi articoli vedremo come migliorare questa tecnica introducendo delle convenzioni sui nomi dei file e sulla modularizzazione del codice.

lunedì 5 dicembre 2011

Using serial port in Ruby

Ruby doesn't have a native library for control serial port. It should be done with standard file I/O opening the device file in /dev/ folder.
Nevertheless the GitHub's user  tenderlove has developed an interesting Ruby library for control RS232 serial port and it can be easily installed like a gem:
gem install serialport

Unfortunately the library is not event-driven, but if you want to throw an event and call a callback while you receive something on serial port you can use a console-like infinite loop. For example:
def check_serial(callback)
opts = {"baud" => 115200, "parity" => SerialPort::NONE, "data_bits" => 8, "stop_bits" => 1}
port = '/dev/ttyS0'
serialport = SerialPort.new(port, opts)
Thread.new do
while true
input = @serialport.gets.chomp
unless input.empty?
callback.call(input)
end
end
end
end

def my_serial_callback(input)
#...do something
end

check_serial(method(:my_serial_callback))

venerdì 17 dicembre 2010

Image Carousel Rilasciato

Image-Carousel è uno script javascript che visualizza in sequenza una serie di immagini con effetti di fade in e fade out, possibilità di andare avanti e indietro la sequenza e di visualizzare una precisa immagine della sequenza.

Attualmente lo script è stato rivisto in ottica object oriented, è basato su prototype ma la prossima versione sarà sviluppato come plugin di jQuery.

Puoi scaricare, ridistribuire, e modificare gratuitamente il codice a patto di citare l'autore e condividere allo stesso modo le modifiche da te effettuate, rispettando la licenza Gnu/GPL v2.

Il pacchetto è scaricabile attraverso GitHub a questo indirizzo.

Tips in Python #1: Avviare un webserver nella directory corrente

Con Python configurato e installato è possibile lanciare nella cartella corrente un web server semplicemente lanciando il comando da console:

python -m SimpleHTTPServer &

mercoledì 3 novembre 2010

Italian Agile Day 2010!

Venerdi’ 19 Novembre 2010 si terrà a Genova il settimo Italian Agile Day. Si tratta di una conferenza gratuita di un giorno dedicata alle metodologie Agili per lo sviluppo e la gestione dei progetti software rivolta agli sviluppatori, project leaders, IT managers, tester, architetti e coach che hanno esperienze da condividere o che iniziano solo ora ad interessarsi a queste tematiche. La giornata ha come obiettivo la conoscenza pratica, le esperienze sul campo e un attivo coinvolgimento di tutti i partecipanti. L’accesso è libero previa registrazione, i posti sono limitati. L’evento, per la quarta volta consecutiva, si auto-finanzierà.

martedì 24 agosto 2010

Facebook API: un fallimento di grande successo

Le nuove API (Application Programming Interface) annunciate durante la conferenza F8, che dovevano semplificare tanto la vita agli sviluppatori, sono arrivate già da un pò e anzichè semplificarla hanno incasintato ancora di più la vita al programmatore. Già perchè sebbene alcune idee siano molto buone (interfaccia REST, protocollo oAuth 2.0) la documentazione e gli esempi sono completamente errati e sbagliati, privi di coerenza e nella fattispecie inutilizzabili. E' una vergogna che il sito con più iscrizioni al mondo si presenti così male dal punto di vista professionale. L'unico modo per imparare le nuove API è quello di cercare in giro per internet su blog o articoli vari e procedere a TASTONI!

Probabilmente le nuove funzionalità sono state rilasciate in fretta e furia, senza controllare che ciò che rende una libreria o una API utilizzabile: la documentiazione.

Facebook gioca con la pazienza e con la vita dei programmatori (si perchè ovviamente si deve perdere tempo per cercare di capire come funzionano queste API che definirle uscite dal sedere di una vacca è un gran complimento).

Cosa andrebbe fatto:

  1. Stilare una VERA guida che indichi cosa si può fare oggi e cosa è sconsigliato

  2. Completare la documentazione

  3. Scrivere esempi funzionanti

  4. Infine riorganizzare la documentazione (com'erano le vecchie api andava benissimo!)

giovedì 22 luglio 2010

Installare CUnit sotto SnowLeopard

Il Test Driven Development è una tecnica di design del software che permette di scrivere del buon codice con un ampio tasso di coverage di test automatizzati. Esistono diverse librerie per fare questo, generalmente almeno una per linguaggio, basate tutte sul design di SUnit (originariamente xUnit), il framework di test scritto da Kent Beck (ideatore di Extreme Programming).

Non fa eccezione il linguaggio C che possiede diverse librerie di testing, tra cui Check e CUnit. Queste due sono caratterizzate dall'essere implementate in puro C e non in C++ come ad esempio googletest.

Installare CUnit sotto Mac è molto semplice anche se mi ha dato qualche problema dovuto alle numerose piattaforme su MacOs X ha girato nel corso degli anni (nato su PPC, PPC64, portato su i386 e ora x86_64, senza contare universal che racchiude le due famiglie).

Per prima cosa possiamo installare la libreria da MacPort:

  1. sudo port install cunit
    MacPort  scaricherà, compilerà e installerà CUnit e libncurses

  2. Modificare il path di MacOS X
    Purtroppo l'installazione di port non mi ha aggiunto i path alle librerie e agli include installati tramite MacPort, quindi è necessario modificare il file /etc/paths e aggiungere le seguenti righe:
    /opt/local/
    /opt/local/lib
    /opt/local/include/


  3. Riavviare il Mac per rendere attive le modifiche al path

  4. A questo punto possiamo provare a compilare il codice di esempio presente sul sito di CUnit con l'accortezza di specificare l'architettura e l'inclusione delle librerie CUnit e Ncurses:
    gcc -lcunit -lncurses -Wall example.c -o example -arch x86_64


  5. Il codice di test ora risulta essere compilato e funzionante possiamo lanciarlo con
    ./example




Happy coding!