venerdì 28 dicembre 2012


Vi siete mai trovati nella condizione in cui dovete inserire un immagine all'interno di una cella di una tabella (magari in modo dinamico tramite jQuery) e, in seguito all'inserimento, la cella risulti inspiegabilmente di dimensioni leggermente più grandi rispetto alla vostra immagine? Io sono incappato in questo problema inserendo piccole immagini 20x20 in una griglia, durante lo sviluppo di Battaglia Navale in JavaScript.

Credendo di essere finito in qualche variazione del box model generata in modo automatico dal browser ho impostato le proprietà margin e padding a 0, senza ottenere successo.

Il problema si risolve agilmente impostando font-size a 0. In questo modo eventuali caratteri speciali all'interno della cella non aumentano la sua dimensione, consentendo all'immagine di adattarsi perfettamente.

martedì 16 ottobre 2012

Closures


In questo nuovo appuntamento parlerò di closures. Come per quanto riguarda l'hoisting, le closures sono un concetto fondamentale per comprendere appieno la potenza di JavaScript, in quanto permettono di creare funzioni personalizzate che vincolano le variabili in un ambito. Sono usate generalmente per costruire funzioni di callback.

Una buona definizione di closure si può trovare sul sito Mozilla Developers Network, da cui questo articolo prende ispirazione:

"una closure è un oggetto particolare che combina due cose: una funzione e l'ambiente in cui la funzione è stata creata."

Per capire meglio partiamo con un primo esempio:

function init() {
  var myName = "Mauri";
  function displayName() {
    alert(name);
  }
  displayName();
}
init();
la funzione init() crea una variabile locale myName (che possiamo considerare come parte dell'environment o ambiente) e definisce una funzione interna chiamata displayName(). Questa funzione dispone della variabile dichiarata e inizializzata nella funzione esterna. Il funzionamento di init() è intuitivo ed è un semplice esempio di functional scoping, nel quale le funzioni annidate possono accedere alle variabili dichiarate all'esterno.

Ora proviamo a modificare l'esempio come segue:
function makeDisplay() {
  var myName = "Mauri";
  function displayName() {
    alert(name);
  }
  // NB: una funzione è una variabile,quindi può essere ritornata
  return displayName;
}

var display = makeDisplay();
display();
Il comportamento di questo codice è identico a quello precedente, potete provarlo comodamente su jsFiddle. Ciò che distingue questo esempio è il fatto che la funzione interna viene ritornata dalla funzione esterna prima di essere eseguita. Intuitivamente ci si aspetta che, terminata l'esecuzione di makeDisplay(), la variabile interna myName sia cancellata dallo stack (come avviene nei linguaggi della famiglia C) e non possa venire referenziata da display(), tuttavia l'esecuzione del codice dimostra che la variabile è ancora accessibile è può essere utilizzata.

Questo peculiare aspetto è propro ciò che caratterizza le closures. La variabile myFunction "racchiude" al suo interno la funzione displayName() e le eventuali variabili accessibili alla funzione durante la creazione della closure. Un esempio (variazione spudorata di quello su MDN) un pochino più complesso può essere il seguente:
function increment(base) {
    this.base = base;
    return function(value) {
        return base + value;
    }
} 

var addTo5 = increment(5);
var addTo14 = increment(14);

alert(addTo5(5)); // output: 10
alert(addTo14(3)); // output: 17
La funzione increment in questo caso è un esempio di function factory, ovvero una funzione che aggiunge un valore specifico all'argomento passato. Questa function factory è stata utilizzata per creare due nuove funzioni (addTo5 e addTo14) che impostano rispettivamente, nel proprio ambiente, i valori 5 e 14 come base a cui verranno aggiunti gli argomenti passati (5 e 2). addTo5 e addTo14 sono quindi closures.

E' importante ricordarsi che le variabili interne sono passate per riferimento e non per copia:
function dica33() {
  var num = 32;
  var showAlert = function() {
    alert(num);
  }
  num++;
  return showAlert();
}

var show33 = dica33();
show33();
Per oggi mi fermo qui, ma non è detto che in futuro possa portare ulteriori approfondimenti sul tema.

mercoledì 10 ottobre 2012

Hoisting - Sollevamento

In questo post parliamo di JavaScript. Di recente mi sono riavvicinato a questo linguaggio, dopo molto tempo in cui ho cercato di tenermene alla larga, per ovvie ragioni (incompatibilità, scarsa tipizzazione, ecc.). Tuttavia lavorando sulla tesi di laurea ho cominciato ad apprezzare questo linguaggio e a capire quanto può essere potente se utilizzato nella maniera giusta.

Pertanto, in questa serie di post su JavaScript, cercherò di analizzare quelle piccole sfumature che rendono poco intuitivo questo linguaggio, scoraggiandone spesso l'uso ai meno intraprendenti (come è stato nel mio caso). La padronanza di queste tecniche distingue sicuramente un programmatore JavaScript esperto.

NOTA: la trattazione di questi argomenti presuppone una conoscenza, almeno basilare, di programmazione JavaScript.

Partiamo quindi parlando di "hoisting". Il suo significato letterale è "sollevato", il che non ci da una chiara indicazione di cosa effettivamente si tratta.

Lasciamo per un attimo da parte il significato di hoisting e concentriamoci sul codice, in quanto ci sono alcune piccole premesse da fare.

Immagino che voi tutti sappiate la differenza tra dichiarazione ed inizializzazione di variabile. Tuttavia per qualcuno può non sembrare ovvia. Assumendo myValue come variabile possiamo scrivere

Dichiarazione:
var myValue;

Inizializzazione:
var myValue = 1;

Nel secondo caso la variabile è inizializzata con un valore. Potete verificare semplicemente con un istruzione

alert(typeof myValue);

Un altro aspetto a cui occorre prestare attenzione è lo scope. Per chi proviene dai linguaggi della famiglia del C (C,C++,Java,Pascal...) non avrà problemi ad interpretare il seguente programma:

#include <stdio.h>
int main() {
  int x = 1;
  printf("%d, ", x); // output: 1
  if(1) {
    int x = 2;
    printf("%d ", x); // output: 2
  }
  printf("%d\n", x); // output: 1
}

L'output del programma sarà 1, 2, 1. I linguaggi della famiglia del C possiedono visibilità a livello di blocco (block-level scope). Pertanto quando il programma entra nel costrutto if, una nuova variabile x può essere dichiarata senza sovrascrivere la visibilità al di fuori del blocco. Con JavaScript invece il funzionamento è diverso. Proviamo a tradurre il codice precedente in JavaScript:

var x = 1;
alert(x); // output: 1
if(true) {
  var x = 2;
  alert(x); // output: 2
}
alert(x); // output: 2

Sorprendentemente l'output sarà 1, 2, 2. Perché? Semplicemente JavaScript, a differenza dei linguaggi C-like, ha visibilità a livello di funzione. I blocchi come if o while non creano un nuovo scope.

Consideriamo ora il seguente codice:

var myValue = 1;
alert(myValue); // output: 1

Come è prevedibile l'alert mostrerà 1 come output. Proviamo leggermente a modificare questo codice introducendo una funzione immediata (eseguita esattamente dove è dichiarata):

var myValue = 1;
(function() {
  alert(myValue); // output: 1
}());

L'output sarà nuovamente 1. Ovvio direte voi. Bene introduciamo un ulteriore complessità:

var myValue = 1;
(function() {
  alert(myValue); // output: ?
  var myValue = 2;
}());

Qual'è l'output in questo caso? Provatelo in firebug o in jsFiddle, vedrete che il valore dell'alert è undefined. Perché? Intuitivamente il valore dovrebbe essere 1, in quanto la nuova inizializzazione di myValue è al di sotto dell'istruzione alert.

E' qui che entra in gioco l'hoisting. Le dichiarazioni di variabili e funzioni sono sempre spostate ("sollevate"), in maniera invisibile dall'interprete JavaScript, in cima allo scope che le contiene. Pertanto il codice precedente è perfettamente analogo al seguente:

var myValue = 1;
(function() {
  var myValue;
  alert(myValue); // output: undefined
  myValue = 2;
}());

Cominciate a capire meglio come funziona, non è vero?

Fino ad ora abbiamo esaminato l'hoisting applicato alle variabili. Passiamo ora ad esaminare il caso delle funzioni:

function prova() {
  foo(); 
  function foo() {
    alert("funziona!");
  }
}
prova();

Come si comporta questo programma? Anche in questo caso l'hoisting si applica nuovamente. L'interprete JavaScript sposta la dichiarazione della funzione in cima. L'output ovviamente è "funziona", come è lecito aspettarsi. Tuttavia sappiamo che esiste un altro modo di dichiarare le funzioni, assegnandole a variabili (espressione function):

function prova() {
  foo(); 
  var foo = function() {
    alert("non funziona!");
  }
}
prova();

In questo caso riceveremo un errore (Uncaught TypeError: undefined is not a function) dovuto al fatto che solamente il nome della funzione (foo) viene sollevato, mentre il corpo della stessa viene assegnato solamente durante l'esecuzione. Quindi il codice precedente risulta perfettamente analogo a questo:

function prova() {
  var foo;
  foo(); 
  foo = function() {
    alert("non funziona!");
  }
}
prova();


L'analisi può chiudersi qui, nonostante ci siano casi particolari in cui il discorso si fa decisamente più complesso. La lezione più importante che possiamo trarre è di dichiarare le nostre variabili con un unica istruzione var limitata allo scope, sistemandola esattamente in cima, in modo da evitare la confusione derivante dall'hoisting:

function test() {
  var x,y,z;
  // codice
  x = 1;
  // più codice
  y = 2;
  // altro codice
  z = 3;
  // ulteriore codice
  return;
}

Per chi ha famililarità con l'inglese e volesse mettersi alla prova con l'hoisting, consiglio il quiz disponibile all'indirizzo http://www.nczonline.net/blog/2010/01/26/answering-baranovskiys-javascript-quiz/

Alla prossima!

giovedì 14 luglio 2011

Project Done

The project is almost finished. There are some little details to fix, especially in the user interface, but the most of the work is done. I'll do obviously some testing in order to check the correct behavior of the application. Then I will package the final deliver, with the source code, the ear archive, the SQL scripts and the final relation.

giovedì 7 luglio 2011

Little Logout Issue

In a previous post I mentioned that the connection didn't switch back to HTTP after visiting confidential pages. However I expected that after the entire logout process the website would have switch the connection back to normal HTTP, after invalidating the session. Unfortunately, I was wrong. HTTPS was still present! What to do? Google is the answer! However I was not so lucky to find a solution, maybe the question was wrong, not the answer. So I managed to build a solution on myself, which is this one: in the Logout servlet I check if the request was made using HTTP using the method request.isSecure(). If so I invalidate the session and I redirect the user to an absolute url, which is built using this string:

"http://" + getServletContext().getInitParameter("domain") + request.getContextPath() + "/index.jsp"


Where the parameter "domain" is specified in the deployment descriptor as "mauricius-pc:8080".

sabato 2 luglio 2011

Few notes on SSL Security - Part II

Good practice would be to use Transport Layer Security also when user credentials are sent through the network. I searched for an easy way to implement it, directly using the j_security_check form, however, reading the following quote from the Java EE 6 tutorial I discovered that things are a little bit different:

"Form-based authentication is not particularly secure. In form-based authentication, the content of the user dialog box is sent as plain text, and the target server is not authenticated. This form of authentication can expose your user names and passwords unless all connections are overSSL. If someone can intercept the transmission, the user name and password information can easily be decoded.However, when a secure transport mechanism, such as SSL, or security at the network level, such as the IPSEC protocol or VPN strategies, is used in conjunction with form-based authentication, some of these concerns can be alleviated."


For this reason I decided to keep the authentication mechanism as it is.

venerdì 1 luglio 2011

Few notes on SSL Security

I decided to add support for a secure connection when sensible data is transmitted through the network. Secure data transport is typically implemented using Transport Layer Security (TLS) or Secure Sockets Layer (SSL). HTTP is applied on top of the TLS/SSL protocol to provide both encrypted communication and secure identification of the server. The combination of HTTP with TLS or SSL results in an HTTPS connection, which can be identified in a browser's address bar (https://).

I discovered that Glassfish has a secure service enabled by default (working on port 8181). This service uses a self-signed certificate, which is quite enough for our development purposes. This will lead to some annoying messages in the browser, forcing us to confirm some security exceptions, but that's it. I decided to use HTTPS in the checkout process (because an e-commerce site like this, sometimes requires the user to insert his Credit Card number or other sensitive data, however this is not the case) and in the Registration process, when the user inserts his personal data (as well as his CC number).

The secure connection is defined using XML in the web deployment descriptor, as follows:

<security-constraint>
   <display-name>Checkout</display-name>
   <web-resource-collection>
      <web-resource-name>Checkout</web-resource-name>
      <url-pattern>/checkout</url-pattern>
      <http-method>GET</http-method>
   </web-resource-collection>
   <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
   </user-data-constraint>
</security-constraint>


Wow, it works perfectly. Also it seems that the navigation doesn't switch back to HTTP once the user moves out from a protected page. Should I treat this as a problem? Maybe not.

I noticed on the website of the course that the exam is set for July, 6th, in the morning. Unfortunately, even if the project is almost finished (apart from some little details), I cannot be present on that date because I'm still working. I will join the September session.