Arxiu de la categoria ‘Bones pràctiques’

Validacions de formularis: a client o a servidor?

dijous 11 febrer 2010

Els que ens dediquem a sistemes client-servidor, més específicament, a sistemes basats en web,  sovint ens trobem amb la necessitat de construir formularis que executin accions a partir d’una entrada. És ben normal, que un client o un funcional proclami:

  • Vull que el número d’identificació sigui obligatori!
  • El correu electrònic ha d’estar en el format correcte!

O altres típics requeriments que requereixin de fer una validació del formulari.

Davant d’aquest escenari, el primer que ens ve al cap és fer les validacions amb JavaScript a la capa client. Bé, no està malament. Fer les validacions a la capa de client, és ràpid en temps de computació, senzill (normalment) i proporciona una resposta ràpida a l’usuari, fet pel qual assegurem una bona experiència d’usuari mentre introduïm dades. Una de les primeres normes de la usabilitat a formularis és: com més aviat sàpiga l’usuari que s’ha equivocat, més aviat podrà reaccionar-hi (compte amb la interpretació d’aquesta frase made-by-me!). Però mai hem d’acabar aquí!

Fer les validacions només a la capa client és una decisió completament errònia. On de debò s’han de fer aquestes comprovacions és a la capa servidor. Allà és on s’ha de mirar si cert camp existeix, si el format de tal camp és el correcte, de si la relació entre dos camps és correcta, etc. És a la capa servidor on tot aquest algorisme s’ha d’executar per prevenir qualsevol error que pugui tenir l’aplicació. És allà on s’executa la lògica de l’aplicació i on les validacions, com part d’aquesta lògica que són, s’han d’executar. Si només ho féssim a client, què passaria si no tinguéssim disponible el JavaScript? Quin seria el comportament de l’aplicació? Possiblement, acabéssim en un estat d’inconsistència no desitjat per ningú.

Sovint quan es planteja aquest argument (validacions dobles a capa client i servidor), molts arquitectes d’aplicacions (remarco la paraula perquè és el títol que es posen ells, no el que els hi posaria jo) posen el crit al cel i diuen la del porc argumentant que s’està fent una tasca dues vegades i que el rendiment de l’aplicació en general es veu ressentit. Si alguna vegada us trobeu davant d’això, només heu de dir:

D’acord, llavors, les validacions que es facin només a la capa de servidor!

Veureu com els hi canvia la cara ;)

Cal tenir ben presents quines són les implicacions de deixar un processament de dades a una capa tan fràgil com pot ser un navegador, i la nostra tasca és argumentar i deixar ben clar el per què a client no és lloc per fer aquest tipus de processament.

Tingueu aquest consell sempre ben present perquè segur que al llarg de la vostra vida professional us caldrà utilitzar-lo més d’un cop.

Separar la forma del contingut (nom de les classes)

dilluns 29 juny 2009

Es ben sabut per tots els que ens dediquem a la programació d’interfícies web (també anomenats maquetadors o programadors front end) que cal tenir ben present que sempre s’ha de separar el document (HTML) de la seva presentació en un medi concret (CSS) i dels components amb comportament que pugui tenir (JavaScript). Així, és fàcil veure que el següent fragment d’un document és completament incorrecte pel que fa a aquests cànons:


<div style="margin: 5px;">
    <em>Aquest contingut el vull en lletra cursiva</em>
    <small><a onclick="window.location='/lipsum'" href="http://www.example.com">Lorem ipsum dolor</a></small>
</div>

Normalment la majoria de programadors som ben conscients de la incorrecció del fragment anterior, però sovint ens trobem incorreccions d’aquest tipus completament encobertes, i sempre seguint el mateix patró: el mal ús dels noms de classe dels elements.

Usaré exemples de la xarxa per a il·lustrar el que vull dir. Si anem a la portada de la pàgina d’una institució molt important del país podem trobar coses així (canvio els texts per centrar l’atenció):


<ul id="ul_home">
	<li><a class="vermell_nobullet_2" href="http://www.example.com">Ipse quat erimo</a></li>
	<li><a class="vermell_nobullet_2" href="http://www.example.com/dog">Sailer due rit</a></li>
</ul>

<div class="marge_superior">
    <h2><span id="actualitat" class="titol_seccio">Lorem ipsum</span></h2>
</div>
<div id="altres_serveis" class="border_top">
    <div class="border_bottom">
        <a class="text_gris" href="http://www.example.com/bird">Dolor et sumum</a>
    </div>
</div>

El valor de l’atribut @class d’alguns dels elements ja ens dóna informació de com s’estilitzaran al veure-ho associat al seu full d’estils.

Però sovint no es veu tan fàcilment la incorrecció a l’assignació dels noms de les classes. Per exemple, és ben normal trobar-nos sempre al fragment de descripció de l’organització d’un document, classes del tipus:


<body class="3-columnes">
    <div class="columna-esquerra">
        Lorem ipsum
    </div>
    <div class="columna-central">
        Dolor set
    </div>
    <div class="columna-dreta">
        Icse et luopir
    </div>
</body>

Hi veieu res d’estrany? Per saber si les classes són reveladores de la forma final, només cal que us feu la següent pregunta: podríeu saber quina és la forma final de la pàgina només llegint l’HTML? Si la resposta és sí, les classes són errònies. Si és no, doncs la cosa ja està millor.

Per exemple, una forma correcte de fer la divisió del document podria ser:


<body class="layout-complet">
    <div class="contingut-primari">
        Lorem ipsum
    </div>
    <div class="contingut-secundari">
        Dolor set
    </div>
    <div class="contingut-terciari">
        Icse et luopir
    </div>
</body>

Oi que ara ja no us espereu com serà el document final?

Per tant, cal anar amb compte a l’hora d’assignar els noms a les classes. Sempre cal tenir ben present de separar la forma o presentació del contingut i anar una mica amb peus de plom a l’hora de cercar els valors. Així aconseguirem que els nostres documents siguin 100% independents de la forma en que es visualitzen.

Amagar sense ocultar amb CSS

dimarts 12 maig 2009

Sovint ens interessa amagar contingut de la nostra pàgina a l’ull humà com pot ser el cas dels menús per a saltar a continguts de la pàgina, en l’ús de tècniques de reemplaçament de contingut per imatges o per ocultar capçaleres o elements estructurals de la pàgina. És veritat que ens interessa amagar-ho de l’ull humà, però el que no volem de cap de les maneres, és amagar-ho dels lectors de pantalla.

El típic error

Si donem una volta per la xarxa, el que sovint trobem escrit i recomanat, és l’ús de la propietat display: none per a ocultar elements. Amb això satisfem la nostra voluntat de que l’ull humà no percebi el contingut, però el problema és que sovint, els lectors de pantalla tampoc n’interpreten res.

Podríem dir que display: none significa que l’element no existeix: ni es mostra, ni s’imprimeix, ni es llegeix el seu contingut.

La solució

Una tècnica alternativa que es pot considerar és la de posicionar l’element que volem amagar de forma absoluta fora del viewport. Així, l’element existeix però no es percep per l’ull humà. El CSS que podem usar és:

.access {
    left: -9999px;
    position: absolute;
}

Amb això aconseguim el mateix efecte visual però sense ignorar a una part dels usuaris.

Tot això no és pas invenció meva, sinó que és una adaptació d’un article que vaig llegir fa uns dies.

Arguments a favor i en contra de l’ús d’iframes

dimarts 31 març 2009

Per temes de feina avui he hagut de fer un llistat d’arguments a favor i en contra de l’ús d’iframe en un desenvolupament web i m’he decidit a fer-la pública perquè tothom que vulgui pugui opinar-ne.

A favor

  • Integració d’aplicacions. Permet integrar aplicacions externes a dins de la nostra pàgina.
  • Disminució de peticions a servidor. Si tenim una part de la nostra pàgina que és costosa de construir (dins d’un entorn de pagines dinàmiques), podem posar-la dins d’un /iframe fent que no s’hagi de refrescar cada cop que canviem de pàgina (seguint una mica el model del ja deprecat element /frame).

En contra

  • Forat negre. Al poder-hi posar tot el que vulguem, un /iframe pot arribar a ser un problema de seguretat si no som nosaltres els creadors del seu contingut.
  • Accessibilitat. Existeixen navegadors que no suporten l’ús de l’element iframe.
  • Lectors de pantalla. Hi ha navegadors que per defecte donen el focus al iframe en el moment de carregar la pàgina. Això és un problema per a la correcta lectura del document pels lectors de pantalla.
  • Cercadors. Les aranyes dels cercadors no saben navegar correctament per les pàgines que usen marcs. Per tant, pot ser que el nostre lloc no sigui correctament indexat.
  • Estructura del contingut. L’ús de l’element iframe trenca l’estructura lògica del contingut de la pàgina.
  • Gran confusió al interactuar amb el navegador. Diverses interaccions de l’usuari amb el navegador es veuen greument modificades per l’ús de l’element iframe en una pàgina:
    • URL. La URL que es veu al navegador no és sovint la que correspon a la d’una pàgina creada amb marcs: si anem navegant dins del marc, la URL del navegador no canvia, però en canvi, la de la pàgina que estem veient sí que “ha canviat”.
    • Adreces d’interès. Lligat amb el punt anterior, si volem desar l’adreça de la plana, la que desarem serà la que es veu al navegador. Al tornar-hi veurem  que no és pas la mateixa plana que havíem desat (haurem perdut la navegació dins del marc). Tot i que hi ha navegadors que ens donen la possibilitat d’esbrinar l’adreça d’un marc, pot ser que l’usuari sigui no especialitzat i per tant, no sàpiga de l’existència d’aquesta possibilitat. Igualment, un usuari de la plana no ha de saber com està feta la pàgina, i per tant, saber com ha de fer-s’ho per desar l’enllaç  “correcte” a la plana en qüestió.
    • Resultats d’una cerca. Si accedim a una pàgina feta amb marcs des d’un resultat d’un cercador extern, pot dur-nos a una adreça  “incorrecte”: podem anara a l’adreça d’un marc, on veurem el contingut d’aquest però sense el contingut del seu “pare”.
  • Alçada fixa. Un iframe té alçada fixa, i per tant, pot ser que ens aparegui una barra de desplaçament lateral en cas que el contingut ocupi més espai del reservat per l’atribut @height del marc.

Alternatives

En cas que usem marcs només per temes estètics no tenim excusa per abandonar-los, ja que el seu aspecte es pot replicar 100% amb CSS.

Si usem marcs per tal de poder deixar una part de la nostra pàgina fixa mentre fem scroll de la pàgina, podem usar la propietat position: fixed de CSS tal i com s’explica en aquest article.

En canvi, si el que volem és que cert contingut de la pàgina tingui una barra lateral per poder navegar dins seu, podem usar la propietat overflow tal i com s’explica en aquest altre article.

Conclusions

A data d’avui, i a no ser que sigui algun motiu de rendiment o d’integració, l’ús de marcs no està justificat en un inici, ja que provoca més desavantatges que no pas avantatges. Sovint la necessitat d’aquest element recau més per un tema gràfic que no pas per un tema funcional, cosa que com ja hem vist, es pot resoldre amb l’ús de fulls d’estils.

Àmbit d’una variable a javascript

dimarts 13 gener 2009

L’àmbit d’una variable es pot definir com l’àrea del programa en que aquesta és visible i accessible.

Com a la majoria de llenguatges de programació, en javascript pots declarar una variable com a global, definida en tot l’àmbit del codi javascript, o com a local, definida només dins de l’àmbit de la funció que la defineix.

var a = 0;        // variable global
function foo() {
  var b = 1;      // variable local
}

Cal tenir sempre en compte que una variable local sempre té precedència davant d’una variable global, és a dir, si una paràmetre d’una funció o una variable declarada dins del seu àmbit té el mateix nom que una variable global, aquesta darrera queda oculta per la nova declaració.

var ambit = 'global';    // Declarem una variable global
function foo() {
  var ambit = 'local';   // Declarem una variable local
  document.write(ambit); // Usem la variable local
}
foo();                   // Imprimeix 'local'

Fins aquí tot força senzill, no? Però si us fixeu, encara no he dit res sobre la paraula reservada var.

Javascript ens deixa usar variables sense haver-les de definir amb la paraula var, però què passa si no ho fem? Doncs bé, si l’interpretador troba que s’està assignant un valor en una variable que no està declarada, la declara com a global i llavors li assigna el valor. Llavors cal tenir en compte que sempre que vulguem declarar una variable local, hem d’usar var.

ambit = 'global';              // Declarem una variable global (sense var)
function foo() {
  ambit = 'local';             // Ostres! Hem canviat el valor de la variable global!
  document.write(ambit);       // Usa la variable global
  nou_ambit = 'local';         // Declarem una nova variable global
  document.write(nou_ambit);   // Usa la nova variable global
}
foo();                         // Imprimeix 'locallocal'
document.write(ambit);         // Imprimeix 'local' (el valor s'ha canviat dins la funció)
document.write(nou_ambit);     // Imprimeix 'local' (la variable s'ha creat a la funció però amb àmbit global)

En general, una funció no sap quines variables estan definides en l’àmbit global i quines no. Així, si una funció usa una variable global en comptes d’una local sense saber-ho, pot estar modificant un valor que pot afectar a d’altres parts del programa. Per sort, la solució a tota aquesta problemàtica és ben senzilla: declareu sempre totes les variables amb var.

Però si seguim estirant del fil, podem trobar altres coses curioses relacionades amb l’àmbit de variables.

A diferència d’altres llenguatges de programació, javascript no defineix l’àmbit d’una variable a nivell de bloc (només existeixen àmbits a nivell global o local!). Així, totes les variables declarades dins d’una funció, sigui on sigui, estan definides a nivell de tota la funció. Si mirem el següent codi podrem entendre-ho:

function foo(a) {
  var i = 0;                       // i està definida a tota la funció
  if (a == 5) {
    var j = 23;                    // j està definida a tota la funció, no només en aquest bloc
    for(var k = 0; k < 20; k++) {  // k està definida a tota la funció, no només en aquest bucle
      document.write(k);
    }
    document.write(k);             // k està definida, i té valor 20
  }
  document.write(j);               // j està definida però pot ser que no estigui inicialitzada
}

Cal tenir en compte que el fet que una variable declarada dins d’una funció està definida per tota la funció pot donar-nos alguna que altra sorpresa. Per exemple:

var ambit = 'global';
function foo() {
  alert(ambit);          // Mostra 'undefined', no pas 'global'
  var ambit = 'local';   // Variable inicialitzada aquí, però definida en tot l'àmbit de la funció
  alert(ambit);          // Mostra 'local'
}
foo();

Pot semblar-nos que el primer cop que es crida a la funció alert() hauria de mostrar-nos “global” ja que la declaració de la variable local encara no s’ha executat. Però si tenim en compte les regles d’àmbit que he anat explicant, la variable local està definida en tot l’àmbit de la funció, ocultant la variable global que du el mateix nom. Però igualment, encara que la variable local està definida, aquesta no està inicialitzada fins que no s’executa la sentència var. Així, la funció foo() anterior és equivalent a la següent:

var ambit = 'global';
function foo() {
  var ambit;             // La variable local es defineix a l'inici de la funció
  alert(ambit);          // En aquest punt existeix, però té valor 'undefined'
  var ambit = 'local';   // En aquest punt la inicialitzem i li donem un valor
  alert(ambit);          // Aquí ja té valor!
}

Amb aquest exemple il·lustra perfectament el perquè és una bona pràctica el declarar totes les variables a l’inici de cada funció.

Tots els exemples que s’usen en aquesta entrada estan basats en els que es poden trobar al del llibre Javascript: The Definitive Guide