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:
- Il body è il tuo discriminante, da lui discendono i tag che compongono la tua app sfrutta questo fatto per isolare javascript e css
- 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)
- Pensa a oggetti, segui il pattern model-controller-view anche nel client, se hai già molto codice, puoi incominciare a isolarlo creando moduli.
- Usa un solo document ready per tutta l'applicazione
- 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.